Communicating with PuTTY via pipe

匿名 (未验证) 提交于 2019-12-03 09:52:54

问题:

I want to capture PuTTY's STDIN and STDOUT pipes. So I open putty.exe via CreateProcess with passing created pipes but I can't read anything from pipes. My code works when I run a bat file.

How can I accomplish this?

Thanks

//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); } 

回答1:

PuTTY is a GUI application. You cannot communicate with it using input/output redirection.

Use plink.exe from PuTTY package. It's a console application with the same set of command-line arguments and features as PuTTY.

Though even better, using some C++ SSH library instead.



回答2:

I found out that PuTTY doesn't have pipe for this purpose and since I didn't want to use plink, I modified PuTTY's source code and embedded pipe in it. Now it works as I want.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!