如何处理“dir”的输出?

沃尔夫冈·罗斯

我编写了一个程序,它实现了一个微型 shell 来处理来自用户的命令。如果输入的命令被识别为内部命令,我的程序将执行此命令。

这些命令是作为内部函数实现的,它们的输出由另一个内部函数处理,该函数能够将文本发送到控制台和/或文件以进行记录。

如果无法识别输入的命令,我会尝试将输入的命令作为 Windows 命令外壳的一部分cmd dir执行,例如 :将执行dir命令并在控制台上打印输出。这是通过CreateProcess. 到现在为止我没有指定成员hStdErrorhStdOutputhStdInput在的STARTUPINFO参数。

我尝试实施和调整使用重定向输入和输出创建子进程的示例

我没有使用他们对子进程的实现,而是尝试将 dir 命令的输出放入我的应用程序中:

#include "pch.h"
#include <windows.h>

#define BUFSIZE 512

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



PROCESS_INFORMATION piProcInfo;
STARTUPINFO siStartInfo;
void CreateChildProcess()
// Create a child process that uses the previously created pipes for STDIN and STDOUT.
{
    TCHAR szCmdline[] = TEXT("cmd /c dir q:\\Sicherung\\Bilder /s");
    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)
        return; // ErrorExit(("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);
    }
}
void ReadFromPipe(void)
// 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. 
{
    DWORD dwRead, dwWritten;
    CHAR chBuf[BUFSIZE];
    BOOL bSuccess = FALSE;
    HANDLE hParentStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

    for (;;)
    {
        DWORD objectstat = WAIT_TIMEOUT;
        //do
        //{
        //  objectstat = WaitForSingleObject(piProcInfo.hProcess, 0);
        //} while (objectstat != WAIT_OBJECT_0);
        memset(&chBuf[0], 0x00, BUFSIZE);
        bSuccess = ReadFile(g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
        if (!bSuccess)
            break;

        bSuccess = WriteFile(hParentStdOut, chBuf,
            dwRead, &dwWritten, NULL);
        if (!bSuccess) 
            break;
        if (dwRead == 0)
            break;
    }
}
int main()
{
    SECURITY_ATTRIBUTES saAttr;

    printf("\n->Start of parent execution.\n");

    // 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))
        return -1;// ErrorExit("StdoutRd CreatePipe");

    // Ensure the read handle to the pipe for STDOUT is not inherited.

    if (!SetHandleInformation(g_hChildStd_OUT_Rd, HANDLE_FLAG_INHERIT, 0))
        return -2;// ErrorExit(("Stdout SetHandleInformation"));

    // Create a pipe for the child process's STDIN. 

    if (!CreatePipe(&g_hChildStd_IN_Rd, &g_hChildStd_IN_Wr, &saAttr, 0))
        return -3 ;// ErrorExit(("Stdin CreatePipe"));

    // Ensure the write handle to the pipe for STDIN is not inherited. 

    if (!SetHandleInformation(g_hChildStd_IN_Wr, HANDLE_FLAG_INHERIT, 0))
        return -4;// ErrorExit(("Stdin SetHandleInformation"));

    // Create the child process. 
    CreateChildProcess();
    ReadFromPipe();
    CloseHandle(piProcInfo.hProcess);
    CloseHandle(piProcInfo.hThread);
    return 0;
}

我知道,问题必须出在 ReadFile 上。我无法确定何时处理了 dir 命令的所有输出。检查dwRead0 或 forBUFSIZE不起作用。dwRead永远不会变成 0,并且它可能小于BUFSIZE,因为 dir 命令不够快。

那么,我应该如何结束管道数据的处理?

沃尔夫冈·罗斯

好的,在我在 google 中搜索了一些不同的术语后,我想出了这个 stackoverflow 的链接;):如何使用 CreateProcess() 和 CreatePipe() 从 cmd.exe 读取输出

伊恩博伊德在那里写道:

一旦你启动了你的子进程:一定要关闭那些你不再需要的管道末端。

result = CreateProcess(...);



//CreateProcess demands that we close these two populated handles when we're done with them. We're done with them.

CloseHandle(pi.hProcess);

CloseHandle(pi.hThread);



/*

   We've given the console app the writable end of the pipe during CreateProcess; we don't need it anymore.

   We do keep the handle for the *readable* end of the pipe; as we still need to read from it.

   The other reason to close the writable-end handle now is so that there's only one out-standing reference to the writeable end: held by the console app.

   When the app closes, it will close the pipe, and ReadFile will return code 109 (The pipe has been ended).

   That's how we'll know the console app is done. (no need to wait on process handles with buggy infinite waits)

*/

CloseHandle(g_hChildStd_OUT_Wr);

g_hChildStd_OUT_Wr = 0;

CloseHandle(g_hChildStd_IN_Rd);

g_hChildStd_OUT_Wr = 0;

大多数解决方案的常见问题是人们试图等待进程句柄。这有很多问题;主要的一点是,如果您等待孩子终止,则孩子将永远无法终止。

关闭不需要的句柄后ReadFile按预期工作。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

如何处理对ItemsSource的输出?

来自分类Dev

如何处理输出:trim_with_solid

来自分类Linux

如何处理后台Linux任务的输出

来自分类Dev

Linux内核如何处理键盘输入/输出?

来自分类Dev

如何处理jq中match函数的输出?

来自分类Dev

snakemake:如何处理从规则的输出变量数

来自分类Java

读取输出时如何处理Java Processes的孙代?

来自分类Dev

如何处理Expect块中的不同输出

来自分类Dev

如何处理带有FOR循环的批处理文件中的“ net use”命令错误输出?

来自分类Dev

如何处理JSON

来自分类Dev

如何处理AccessViolationException

来自分类Java

如何处理URISyntaxException

来自分类Dev

如何处理例外?

来自分类Dev

如何处理BLOB?

来自分类Dev

如何处理逼近

来自分类Java

如何处理SIGTERM

来自分类Dev

如何处理常量?

来自分类Java

如何处理MaxUploadSizeExceededException

来自分类Dev

会话如何处理?

来自分类Dev

如何处理ViewBox

来自分类Dev

如何处理StackOverflowException

来自分类Dev

如何处理 OutOfMemoryException

来自分类Dev

如何处理 StackOverflowException

来自分类Dev

如何处理UnexpectedRollbackException?

来自分类Dev

如何处理UnkownProducerIdException

来自分类Android

如何处理ActionAppNotificationSettings?

来自分类Dev

如何处理FirebaseAuthUserCollisionException

来自分类Dev

如何处理IDisposable?

来自分类Dev

如何处理 HTMLCollection {}?