2017-08-08 87 views
1

我想捕獲PuTTY的STDIN和STDOUT管道。所以我打開putty.exe通過CreateProcess與傳遞創建管道,但我不能從管道讀取任何東西。我的代碼在我運行bat文件時起作用。通過管道與PuTTY通信

我該如何做到這一點?

由於

//This code is from MSDN and I edited it a little 
#include <QCoreApplication> 
#include <windows.h> 
#include <tchar.h> 
#include <stdio.h> 
#include <strsafe.h> 
#pragma comment(lib, "user32.lib") 
#define BUFSIZE 4096 

HANDLE g_hChildStd_IN_Rd = NULL; 
HANDLE g_hChildStd_IN_Wr = NULL; 
HANDLE g_hChildStd_OUT_Rd = NULL; 
HANDLE g_hChildStd_OUT_Wr = NULL; 

HANDLE g_hInputFile = NULL; 

void CreateChildProcess(void); 
void WriteToPipe(void); 
void ReadFromPipe(void); 
void ErrorExit(PTSTR); 

int main(int argc, char *argv[]) 
{ 
    SECURITY_ATTRIBUTES saAttr; 
    // Set the bInheritHandle flag so pipe handles are inherited. 
    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
    saAttr.bInheritHandle = TRUE; 
    saAttr.lpSecurityDescriptor = NULL; 

    // Create a pipe for the child process's STDOUT. 
    if (! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0)) 
     ErrorExit((PTSTR)TEXT("StdoutRd CreatePipe")); 

    // Ensure the read handle to the pipe for STDOUT is not inherited. 
    if (! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0)) 
     ErrorExit((PTSTR)TEXT("Stdout SetHandleInformation")); 

    // Create a pipe for the child process's STDIN. 
    if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0)) 
     ErrorExit((PTSTR)TEXT("Stdin CreatePipe")); 

    // Ensure the write handle to the pipe for STDIN is not inherited. 
    if (! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0)) 
     ErrorExit((PTSTR)TEXT("Stdin SetHandleInformation")); 

    // Create the child process: putty 
    CreateChildProcess(); 

    // read from pipe and printf incoming data 
    ReadFromPipe(); 
} 

// Read output from the child process's pipe for STDOUT 
// and write to the parent process's pipe for STDOUT. 
// Stop when there is no more data. 
void ReadFromPipe(void) 
{ 
    DWORD dwRead, dwWritten; 
    CHAR chBuf[BUFSIZE]; 
    BOOL bSuccess = FALSE; 
    HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE); 

    for (;;) 
    { 
     bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL); 
     if(! bSuccess || dwRead == 0) 
      break; 

     printf("received hex:\n"); 
     for (int i = 0; i < dwRead; i++) 
     { 
      printf("%02X", chBuf[i]); 
     } 
     printf("\nactual string: %s\n",chBuf); 
    } 
} 

void CreateChildProcess() 
// Create a child process that uses the previously created pipes for STDIN and STDOUT. 
{ 
    PROCESS_INFORMATION piProcInfo; 
    STARTUPINFO siStartInfo; 
    BOOL bSuccess = FALSE; 

    // Set up members of the PROCESS_INFORMATION structure. 
    ZeroMemory(&piProcInfo, sizeof(PROCESS_INFORMATION)); 

    // Set up members of the STARTUPINFO structure. 
    // This structure specifies the STDIN and STDOUT handles for redirection. 

    ZeroMemory(&siStartInfo, sizeof(STARTUPINFO)); 
    siStartInfo.cb = sizeof(STARTUPINFO); 
    siStartInfo.hStdError = g_hChildStd_OUT_Wr; 
    siStartInfo.hStdOutput = g_hChildStd_OUT_Wr; 
    siStartInfo.hStdInput = g_hChildStd_IN_Rd; 
    siStartInfo.dwFlags |= STARTF_USESTDHANDLES; 

    // Create the child process. 

    bSuccess = CreateProcess(L"E:\\putty.exe", 
          NULL,   // command line 
          NULL,   // process security attributes 
          NULL,   // primary thread security attributes 
          TRUE,   // handles are inherited 
          0,    // creation flags 
          NULL,   // use parent's environment 
          NULL,   // use parent's current directory 
          &siStartInfo, // STARTUPINFO pointer 
          &piProcInfo); // receives PROCESS_INFORMATION 

    // If an error occurs, exit the application. 
    if (! bSuccess) 
     ErrorExit((PTSTR)TEXT("CreateProcess")); 
    else 
    { 
     // Close handles to the child process and its primary thread. 
     // Some applications might keep these handles to monitor the status 
     // of the child process, for example. 

     CloseHandle(piProcInfo.hProcess); 
     CloseHandle(piProcInfo.hThread); 
    } 
} 

// Format a readable error message, display a message box, 
// and exit from the application. 
void ErrorExit(PTSTR lpszFunction) 
{ 
    LPVOID lpMsgBuf; 
    LPVOID lpDisplayBuf; 
    DWORD dw = GetLastError(); 

    FormatMessage(
     FORMAT_MESSAGE_ALLOCATE_BUFFER | 
     FORMAT_MESSAGE_FROM_SYSTEM | 
     FORMAT_MESSAGE_IGNORE_INSERTS, 
     NULL, 
     dw, 
     MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), 
     (LPTSTR) &lpMsgBuf, 
     0, NULL); 

    lpDisplayBuf = (LPVOID)LocalAlloc(LMEM_ZEROINIT, 
     (lstrlen((LPCTSTR)lpMsgBuf)+lstrlen((LPCTSTR)lpszFunction)+40)*sizeof(TCHAR)); 
    StringCchPrintf((LPTSTR)lpDisplayBuf, 
     LocalSize(lpDisplayBuf)/sizeof(TCHAR), 
     TEXT("%s failed with error %d: %s"), 
     lpszFunction, dw, lpMsgBuf); 
    MessageBox(NULL, (LPCTSTR)lpDisplayBuf, TEXT("Error"), MB_OK); 

    LocalFree(lpMsgBuf); 
    LocalFree(lpDisplayBuf); 
    ExitProcess(1); 
} 

回答

0

我發現PuTTY沒有用於此目的的管道,因爲我不想使用plink,所以我修改了PuTTY的源代碼和嵌入管道。現在它按我的意思工作。

+0

因此,您已經有效地實施了Plink。爲什麼? –

+0

好膩子和plink不一樣。由於客戶將使用我的應用程序,我不能限制用戶使用plink。相反,客戶將能夠通過我的管道通信使用豐富的膩子,一切都會很好。 –

2

膩子是一個GUI的應用程序。您無法使用輸入/輸出重定向與它進行通信。使用plink.exe from PuTTY package。它是一個控制檯應用程序,具有與PuTTY相同的一組命令行參數和功能。

雖然更好,但使用一些C++ SSH庫代替。