exe在c中的输出和输入

exe在c中的输出和输入

本文介绍了通过管道重定向CMD.exe在c中的输出和输入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图像正常的cmd.exe一样打印接收到stdout的cmd命令的输出和输入.我可以使用功能_popen,但是当我启动像Python或Powershell这样的程序时,它不起作用. 所以我需要子进程的输出,并且能够将命令发送到子进程.

Im trying to print the output and input of cmd commands recieved to stdout just like a normal cmd.exe would do.I could use the function _popen but when i start a program like Python or Powershell whith it, it doesnt work. So i Need the Output of the child process and be able to send commands to the child process.

有一个类似的问题此处

所以我从链接看起来像这样:

So i modified the code from this link to look like this:

void WriteToPipe(char* command){
    DWORD dwRead, dwWritten;
    BOOL bSuccess = FALSE;

    bSuccess = WriteFile(g_hChildStd_IN_Wr, command, strlen(command), &dwWritten, NULL);

    // Close the pipe handle so the child process stops reading.

    if (!CloseHandle(g_hChildStd_IN_Wr))
        ErrorExit(TEXT("StdInWr CloseHandle"));
}

void ReadFromPipe(void){
    DWORD dwRead, dwWritten;
    CHAR chBuf[BUFSIZE];
    BOOL bSuccess = FALSE;
    HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

    bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
    bSuccess = WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL);
    //bSuccess = PeekNamedPipe(g_hChildStd_OUT_Rd, NULL, BUFSIZE, &dwRead, &dwTotalAvailBytes, &dwBytesLeft);
}

主循环如下:

CreateChildProcess("C:\\Python27\\python.exe");
char input_buffer[100] = { 0 };
while (1){
    fgets(input_buffer, 99, stdin);
    WriteToPipe(input_buffer);
    ReadFromPipe();
}

其他所有(来自代码)保持不变.

everything else (from the code) stayed the same.

现在我的问题是,我想在同一进程中输入多个命令,但是WriteToPipe中有一个CloseHandle功能,在关闭句柄之后,我无法输入更多命令.

Now my Problem is, i want to enter multiple commands to the same process, but there is a CloseHandle fucntion in WriteToPipe, after the handle is closed i cant enter more commands.

如何获取有效的HANDLE以便向进程写入多个命令?

推荐答案

将ReadFromPipe()放在单独的线程中;我的代码在这里是垃圾,但它是有效的代码,仅用于测试目的.

put ReadFromPipe() in a separate Thread;my code here is a garbage but it is working code, it is for test purpose only.

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

#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;

int CreateChildProcess(TCHAR *szCmdline);

void PrintError(char *text,int err);
int InitPipes();


int WriteToPipe(char* command){
    DWORD dwRead, dwWritten;
    BOOL bSuccess = FALSE;
    SetLastError(0);
    WriteFile(g_hChildStd_IN_Wr, command, strlen(command), &dwWritten, NULL);


    bSuccess=GetLastError();

    PrintError("WriteToPipe",bSuccess);
    return (bSuccess==0)||(bSuccess==ERROR_IO_PENDING);
}

int ReadFromPipe(void){
    DWORD dwRead, dwWritten;
    CHAR chBuf[BUFSIZE];
    BOOL bSuccess = FALSE;
    HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

    SetLastError(0);
    while(
        ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL)
        &&
        WriteFile(hParentStdOut, chBuf, dwRead, &dwWritten, NULL)
        );

    bSuccess=GetLastError();
    PrintError("ReadFromPipe",bSuccess);


    return (bSuccess==0)||(bSuccess==ERROR_IO_PENDING);
}

HANDLE hThread;

int __stdcall ThreadProc(int arg){

    while(ReadFromPipe())
        ;

    return 0;
}

int main(){
    char input_buffer[100] = { 0 };
    if(!InitPipes()){
        printf("Failed to CreatePipes\n");
        return -1;
    }

    if(!CreateChildProcess("cmd.exe")){
        printf("Failed to create child process\n");
        return -2;
    }


    hThread=CreateThread(NULL,0,ThreadProc,NULL,0,NULL);

    while (1){
        fgets(input_buffer, 99, stdin);
        if(!WriteToPipe(input_buffer)) break;
    }
    printf("Program terminated\n");
    return 0;
}





int CreateChildProcess(TCHAR *szCmdline){

   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(NULL,
      szCmdline,     // 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 ){
      // 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);
   }
    return bSuccess;
}



int InitPipes(){
   SECURITY_ATTRIBUTES saAttr;

// Set the bInheritHandle flag so pipe handles are inherited.

   saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
   saAttr.bInheritHandle = TRUE;
   saAttr.lpSecurityDescriptor = NULL;



   if ( ! CreatePipe(&g_hChildStd_OUT_Rd, &g_hChildStd_OUT_Wr, &saAttr, 0) )
      return 0;

   if ( ! SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0) )
      return 0;

   if (! CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
      return 0;

   if ( ! SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0) )
      return 0;

    return 1;
}





void PrintError(char *text,int err){
     DWORD retSize;
     LPTSTR pTemp=NULL;

    if(!err) return;

     retSize=FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER|
                           FORMAT_MESSAGE_FROM_SYSTEM|
                           FORMAT_MESSAGE_ARGUMENT_ARRAY,
                           NULL,
                           err,
                           LANG_NEUTRAL,
                           (LPTSTR)&pTemp,
                           0,
                           NULL );


    if(pTemp) printf("%s: %s\n",text,pTemp);
     LocalFree((HLOCAL)pTemp);
    return ;

}

这篇关于通过管道重定向CMD.exe在c中的输出和输入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 19:32