创建流程和匿名管道

时间:2016-05-25 05:51:24

标签: c winapi pipeline createprocess

更新问题:所以我已经能够创建流程并将程序编译。但是,我遇到了一个新问题。当我尝试将Source程序传递给Filter程序时。它似乎没有为sink程序提供任何输入。没有错误消息。我还使用Windows“cmd”中的管道运算符测试了我的所有独立程序。

我正在尝试这个小项目来了解匿名管道和创建流程。我创建了3个名为Source,Filter和Sink的小型独立程序。这三个已编译并运行正常。以下是3个独立程序的说明。

Source:从命令行获取源文本文件文件名,打开文件,并一次一个字符地读取和复制文件内容到标准输出(stdout)。复制文件后,Source将终止(关闭所有打开的文件句柄)。

过滤程序不使用任何文件名命令行参数。相反,Filter从标准输入(stdin)读取文本文件,并将标准输出(stdout)写入输入的副本,所有大写字母都转换为小写。特别是过滤器必须设计为读取一个字符,转换它,输出它,然后循环,直到输入数据结束。

Sink程序从其命令行获取目标文本文件文件名,打开文件进行写入,然后从标准输入文件(stdin)一次读取一个字符,并将每个传入字符直接写入目标接收器文件。

接下来,我将分别驱动一个主驱动程序,创建2个管道,并产生3个独立子项,其输入和输出配置为执行指示的并发执行和数据流。像这样:

  • srcfile - >来源 - > pipe1 - >过滤器 - > Pipe2 - >接收器 - > destfile

驱动程序将需要2个命令行参数:

  • C:\> Driver.exe srcfile destfile

其中srcfile是现有数据文本文件,destfile是由Sink应用程序创建的新目标文件的文件名。

这是我的驱动程序代码。它尚未完成。但是在尝试为Source程序创建进程时遇到了打嗝。

更新代码:

#include <windows.h>
#include <WinBase.h>
#include <stdio.h>


#define DELAY_A_WHILE() {volatile long j; for(j = 1; j< 10000; j++) ; } 

int main(int argc, char *argv[])
{
    HANDLE hPipeRead, hPipeWrite, hPipeRead2, hPipeWrite2;
    STARTUPINFO StartupInfoSource;
    STARTUPINFO StartupInfoFilter;
    STARTUPINFO StartupInfoSink;
    PROCESS_INFORMATION ProcInfoSource;
    PROCESS_INFORMATION ProcInfoFilter;
    PROCESS_INFORMATION ProcInfoSink;
    SECURITY_ATTRIBUTES PipeAttributes;
    SECURITY_ATTRIBUTES PipeAttributes2;
    char cmdline[200];

    PipeAttributes.nLength = sizeof(SECURITY_ATTRIBUTES);
    PipeAttributes.lpSecurityDescriptor = NULL;     //ignore
    PipeAttributes.bInheritHandle = TRUE;           //child can inherit

    //Create first pipe
    if (!CreatePipe(&hPipeRead, &hPipeWrite, &PipeAttributes, 0)) {
        fprintf(stderr, "Error creating pipe: %d\n", GetLastError());
        exit(1);
    }

    sprintf_s(cmdline, 200, "Source.exe %s", argv[1]);
    printf("Create process: %s\n", cmdline);

    GetStartupInfo(&StartupInfoSource);
    StartupInfoSource.dwFlags = StartupInfoSource.dwFlags | STARTF_USESTDHANDLES;


    //Mapping
    StartupInfoSource.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
    StartupInfoSource.hStdOutput = hPipeWrite;
    StartupInfoSource.hStdError = GetStdHandle(STD_ERROR_HANDLE);

    if (!CreateProcess(
        NULL, cmdline, NULL, NULL,
        TRUE,
        CREATE_NEW_CONSOLE, NULL, NULL,
        &StartupInfoSource,
        &ProcInfoSource))
    {
        fprintf(stderr, "Error creating child process: %d",GetLastError());
        exit(1);
    }

    CloseHandle(hPipeWrite);
    CloseHandle(ProcInfoSource.hProcess);
    CloseHandle(ProcInfoSource.hThread);

    PipeAttributes2.nLength = sizeof(SECURITY_ATTRIBUTES);
    PipeAttributes2.lpSecurityDescriptor = NULL;        //ignore
    PipeAttributes2.bInheritHandle = TRUE;          //child can inherit
    //Create Second Pipe
    if (!CreatePipe(&hPipeRead2, &hPipeWrite2, &PipeAttributes2, 0)) {
        fprintf(stderr, "Error creating pipe: %d\n", GetLastError());
        exit(1);
    } 

    GetStartupInfo(&StartupInfoFilter);
    StartupInfoFilter.dwFlags = StartupInfoFilter.dwFlags | STARTF_USESTDHANDLES;

    //Mapping
    StartupInfoFilter.hStdInput = hPipeRead;
    StartupInfoFilter.hStdOutput = hPipeWrite2;
    StartupInfoFilter.hStdError = GetStdHandle(STD_ERROR_HANDLE);

    sprintf_s(cmdline, 200, "Filter.exe");
    printf("Create process: %s\n", cmdline);

    //Filter
    GetStartupInfo(&StartupInfoFilter);
    if (!CreateProcess(
        NULL, cmdline, NULL, NULL,
        TRUE,
        CREATE_NEW_CONSOLE, NULL, NULL,
        &StartupInfoFilter,
        &ProcInfoFilter))
    {
        fprintf(stderr, "Error creating child process: %d", GetLastError());
        exit(1);
    }
//  int exitStatus;
    //  GetExitCodeProcess(ProcInfoFilter.hProcess, &exitStatus);
    CloseHandle(hPipeRead);
    CloseHandle(hPipeWrite2);
    CloseHandle(ProcInfoFilter.hProcess);
    CloseHandle(ProcInfoFilter.hThread);


    GetStartupInfo(&StartupInfoSink);
    StartupInfoSink.dwFlags = StartupInfoSink.dwFlags | STARTF_USESTDHANDLES;



    //Mapping
    StartupInfoSink.hStdInput = hPipeRead2;
    StartupInfoSink.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
    StartupInfoSink.hStdError = GetStdHandle(STD_ERROR_HANDLE);

    sprintf_s(cmdline, 200, "Sink.exe %s", argv[2]);
    printf("Create process: %s\n", cmdline);

    GetStartupInfo(&StartupInfoSink);
    if (!CreateProcess(
        NULL, cmdline, NULL, NULL,
        TRUE,
        CREATE_NEW_CONSOLE, NULL, NULL,
        &StartupInfoSink,
        &ProcInfoSink))
    {
        fprintf(stderr, "Error creating child process: %d", GetLastError());
        exit(1);
    }

    CloseHandle(hPipeRead2);
    CloseHandle(ProcInfoSink.hProcess);
    CloseHandle(ProcInfoSink.hThread);


    return 0;
}

该程序编译良好。但是,当它尝试创建Process时,它总是会失败并退出。解析时的cmdline值是“Source.exe test.txt”,这正是我用来执行独立源程序的。有人可以解释为什么我的CreateProcess失败了吗?是因为我解析了错误的参数吗?

2 个答案:

答案 0 :(得分:2)

我在这里看到的唯一问题是Source.exe应用程序可能不在Driver.exe所在的同一目录中。我尝试了你的代码,这是CreateProcess失败的唯一情况。

答案 1 :(得分:-1)

我弄明白了为什么。我的项目的属性是使用Unicode字符集。当我切换到多字节字符集时,它工作正常。