createprocess 重定向子进程的标准输入为管道的读端,父进程向管道写入数据时,子进程标准输入输入一些数据

官方参考https://docs.microsoft.com/en-us/windows/win32/procthread/creating-a-child-process-with-redirected-input-and-output
由于我并不需要读取子进程的输出,所以简化了一下过程,改动不多

代码流程并不复杂:

  • 父进程向管道写入数据
  • 子进程从管道读取数据到标准输入

直接贴出代码:

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

using namespace std;

#pragma comment(lib,"winmm.lib")
#define BUFSIZE 4096 


HANDLE g_hChildStd_IN_Rd = NULL;   //管道读端作为子进程标准输入
HANDLE g_hChildStd_IN_Wr = NULL;

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

int _tmain(int argc, TCHAR* 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 STDIN. 

    if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
        ErrorExit(TEXT(PTSTR)("Stdin CreatePipe"));

    // Ensure the write handle to the pipe for STDIN is not inherited. 
    // 设置g_hChildStd_IN_Wr句柄不可继承
    if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
        ErrorExit(TEXT(PTSTR)("Stdin SetHandleInformation"));

    // Create the child process. 

    CreateChildProcess();

    // Get a handle to an input file for the parent. 
    // This example assumes a plain text file and uses string output to verify data flow. 


    //向管道写入‘q’
    printf("\n->Enter 'q': ");
    while (1)
    {
        if (cin.get() == 'q')
        {
            DWORD start = timeGetTime();
            WriteToPipe();//往管道写数据
            DWORD end = timeGetTime();
            cout << (end - start) << "ms!" << endl;
        }
    }

    // Read from pipe that is the standard output for child process. 
    printf("\n->End of parent execution.\n");

    // The remaining open handles are cleaned up when this process terminates. 
    // To avoid resource leaks in a larger application, close handles explicitly. 

    return 0;
}

void CreateChildProcess()
// Create a child process that uses the previously created pipes for STDIN and STDOUT.
{
    //TCHAR szCmdline[] = TEXT(".\\child\\child.exe");
    TCHAR szCmdline[] = TEXT(".\\ffmpeg.exe  -stream_loop -1 -re -i swt.mp3 -codec copy -y faj.mp3");
    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;    //使用hStdInput、hStdOutput 和hStdError 成员

    // 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)
        ErrorExit(TEXT(PTSTR)("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);

        // Close handles to the stdin and stdout pipes no longer needed by the child process.
        // If they are not explicitly closed, there is no way to recognize that the child process has ended.

        CloseHandle(g_hChildStd_IN_Rd);
    }
}

void WriteToPipe(void)

// Read from a file and write its contents to the pipe for the child's STDIN.
// Stop when there is no more data. 
{
    DWORD dwRead, dwWritten;
    BOOL bSuccess = FALSE;
    CHAR tchBuf[BUFSIZE] = "q\r\n";


    //数据写进管道    -   管道另一端是子进程的标准输入
    bSuccess = WriteFile(g_hChildStd_IN_Wr, tchBuf, strlen(tchBuf), &dwWritten, NULL);
    if (!bSuccess)
    {
        ErrorExit(TEXT(PTSTR)("WriteFile"));
    }
    
    return;

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

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


void ErrorExit(PTSTR lpszFunction)

// Format a readable error message, display a message box, 
// and exit from the application.
{
    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
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值