CreateProcess 无法运行 sfc.exe ?为啥

Posted

技术标签:

【中文标题】CreateProcess 无法运行 sfc.exe ?为啥【英文标题】:CreateProcess can not run sfc.exe ? whyCreateProcess 无法运行 sfc.exe ?为什么 【发布时间】:2021-03-31 09:48:54 【问题描述】:

使用 CreateProcess 创建一个运行 sfc.exe 的进程。但是,没有效果。 我有管理员权限来运行这个程序

我使用 CreateProcess API 来控制 CUI 输出并捕获 CUI 程序输出信息。

我想使用管道接收 sfc /scannow 命令输出,并且

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

    HANDLE hReadPipe = NULL;
    HANDLE hWirtePipe = NULL;
    if (!CreatePipe(&hReadPipe, &hWirtePipe, &sa, NULL)) 
        std::cout << "create pipe failed \n";
        return -1;
     


    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    ZeroMemory(&si, sizeof(STARTUPINFO));
    ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
    si.cb = sizeof(STARTUPINFO);
    si.dwFlags = STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES,
    si.wShowWindow = SW_HIDE;
    si.hStdError = hWirtePipe;
    si.hStdOutput = hWirtePipe;

    TCHAR szCommand[] = TEXT("sfc /scannow");
    if (!CreateProcess(NULL, szCommand, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) 
    
        cout << "process create failed ,errno is :"<< GetLastError() << endl;
        CloseHandle(hReadPipe);
        CloseHandle(hWirtePipe);
        return -1;
    
    
    DWORD dwRead = 0;
    DWORD stdRead = 0;
    DWORD total;
    DWORD timeout = 50;
    TCHAR bufferOutPipe[1024] = 0;
    TCHAR readBuffer[1024] = 0;
    BOOL flag = true;
    while (flag) 
        if (WAIT_TIMEOUT == WaitForSingleObject(pi.hProcess, timeout)) 
            if (!PeekNamedPipe(hReadPipe, bufferOutPipe, 1024, &dwRead, &total, 0) || dwRead <= 0) 
                continue;
            
            else 
                ReadFile(hReadPipe, readBuffer, dwRead, &stdRead, NULL);
                printf("%s\n", readBuffer);
                dwRead = 0;
            
        
        else if (WAIT_OBJECT_0 == WaitForSingleObject(pi.hProcess, timeout)) 
            if (PeekNamedPipe(hReadPipe, bufferOutPipe, 1024, &dwRead, &total, 0) && dwRead > 0) 

                ReadFile(hReadPipe, readBuffer, dwRead, &stdRead, NULL);
                printf("%s\n", readBuffer);
            
            flag = false;
        
        ZeroMemory(readBuffer, 1024);
    
    CloseHandle(hReadPipe);
    CloseHandle(hWirtePipe);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);

我想接收'SFC / scannow'命令的输出并使用匿名管道和进程重定向输出,但我听不到任何管道数据,创建的进程立即启动,

我和管理员一起开始了 Visual Studio

【问题讨论】:

您能发布一些以sfc.exe 开头的代码吗?它是否适用于其他程序,例如calc.exe 是的,有些工具可以通过 CreateProcess 启动,例如:Dism.exe 这是什么编程语言? C++?为语言添加标签将提高您的问题的可见性,并可能导致更有用的答案。 我通过删除 CREATE_NEW_CONSOLE 标志让您的示例正常工作。 (Ofc,您的 sn-p 中缺少一些元素,例如 processInfo 的声明)。最后你还需要调用CloseHandle(processInfo.hProcess)CloseHandle(processInfo.hThread) 是的,你说的没错,但是我要指出的是,CreateProcess创建的进程无法得到SFC的输出。奇怪的是,我使用 dism /?现在不是SFC/scan,而是有输出信息 【参考方案1】:

si.hStdInput 未初始化为有效值。 0 无效。你似乎想要INVALID_HANDLE_VALUE

对于bInheritHandles 使用FALSE,您的输出重定向无论如何都不起作用。这似乎是您当前的根本问题。

此外,一旦进程打开,您的代码将永远旋转,因为CloseHandle(hWirtePipe); 不是及时调用而是在循环之后调用。然后处理您的句柄泄漏。

现在该等待循环了。呸。正常的构造是读取到管道结束,然后才等待进程退出。就循环而言,您有一个竞争条件,这将导致您(很可能)失去输出的尾端。请注意,这将永远阻塞,直到您在进入循环之前关闭写入端的副本。您也不需要任何 PeekWhatever 废话。只需读取句柄,直到您收到管道结束的特定错误。

【讨论】:

我已经更新了我的代码。当进程结束时,WaitForSingleObject 将返回 WAIT_OBJECT_0 @Marsontao_:您不应该在循环内多次调用WaitForSingleObject。而是保存返回值,并将该返回值与WAIT_TIMEOUTWAIT_OBJECT_0 进行比较 @Joshua:你的意思是异步读取管道? @Marsontao_:其实我的意思是同步。 ReadFile 将阻塞,直到有东西要读取。 @Joshua:我认真考虑了您的上述指导。不好意思我傻了,还是看不懂/跨度>

以上是关于CreateProcess 无法运行 sfc.exe ?为啥的主要内容,如果未能解决你的问题,请参考以下文章

Windows 7 CreateProcess,子进程无法写入文件?

无法通过Java运行命令,但可以通过cmd运行它CreateProcess error = 2,系统找不到指定的文件

无法运行程序“C:\Users\admin\AppData\Local\Android\Sdk\platform-tools\adb.exe”:CreateProcess 错误=193,%1 不是有效

无法启动应用程序(CreateProcess 错误=87),不能使用缩短类路径解决方法

pyinstallerexe无法createprocess调用

UNC 路径上的 VC++ Createprocess