2017-04-14 109 views
0

因此,如果您运行下面的代码,它将永远停止在int retVal = WaitForSingleObject(processInfo.hProcess, INFINITE);。但是当我运行“ipconfig”或“ping 192.168.0.1”而不是“systeminfo”时,代码完美地工作。我想知道如何解决问题以及导致此问题的原因是什么?执行“systeminfo”命令后,waitforsingleobject停止

#include <windows.h> 

int WINAPI WinMain(
        HINSTANCE hInstance, 
        HINSTANCE hPrevInstance, 
        LPSTR lpComLine, 
        int nCmdShow) 
{ 
    SECURITY_ATTRIBUTES secAttr; 
    HANDLE hRead,hWrite; 

secAttr.nLength = sizeof(SECURITY_ATTRIBUTES); 
secAttr.lpSecurityDescriptor = NULL; 
secAttr.bInheritHandle = TRUE; 
if (!CreatePipe(&hRead,&hWrite,&secAttr,0)) 
{ 
    return FALSE; 
} 

char command[1024]; 
strcpy(command, "systeminfo"); 

STARTUPINFO startupInfo; 
PROCESS_INFORMATION processInfo; 
startupInfo.cb = sizeof(STARTUPINFO); 
GetStartupInfo(&startupInfo); 
startupInfo.hStdError = hWrite; 
startupInfo.hStdOutput = hWrite;  
startupInfo.hStdInput = hRead;  
startupInfo.lpTitle = "CMD"; 
startupInfo.wShowWindow = SW_HIDE; 
startupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; 
if (!CreateProcess(NULL, command,NULL,NULL,TRUE,NULL,NULL,NULL,&startupInfo,&processInfo)) 
{ 
    MessageBox(NULL, "Error", NULL, MB_OK); 
    CloseHandle(hWrite); 
    CloseHandle(hRead); 
    return FALSE; 
} 

char buffer[1024] = {0};   
DWORD bytesRead; 

int retVal = WaitForSingleObject(processInfo.hProcess, INFINITE); 
if (retVal == WAIT_FAILED) 
    MessageBox(NULL, "WAIT_FAILED", NULL, MB_OK); 
else if (retVal == WAIT_TIMEOUT) 
    MessageBox(NULL, "WAIT_TIMEOUT", NULL, MB_OK); 
ReadFile(hRead,buffer,1024,&bytesRead,NULL); 
MessageBox(NULL, buffer, NULL, MB_OK); 

CloseHandle(hWrite); 
CloseHandle(hRead); 

return 0; 
} 

回答

0

虽然我在运行代码时没有任何问题,但我怀疑我知道这个问题。

您可能在尝试写入管道句柄的过程和等待它退出的代码之间发生死锁。

systeminfo向管道写出至少2K的数据。这可能会超过内置于管道中的缓冲区。但是你的程序不能同时读取它。所以systeminfo程序不能退出,因为它写入标准输出。而你的程序块等待应用程序退出。经典的僵局。不输出尽可能多的字符的程序工作正常。

我没有时间编写完整的解决方案,但我相信您会希望使用一个为读取句柄和进程句柄执行WaitForMultipleObjects的循环。如果可能,请在读取手柄上使用非阻塞或重叠的I/O。

此外,修改您的通话ReadFile的如下:

DWORD dwResult = ReadFile(hRead,buffer,sizeof(buffer)-1,&bytesRead,NULL); 
if (dwResult > 0) 
{ 
    buffer[dwResult] = '\0'; 
} 

,这样你保证,当整个缓冲区,字符填充空终止。

+0

好的,你说的话对我有意义,我有点理解我的程序中有什么问题。但是当你运行它时,同样的代码是如何工作的,而它却不能在我的编译器上工作?而我仍然无法弄清楚这个谣言。 systeminfo程序完全退出后,我想要ReadFile。 –

+0

你是完全正确的,管道写在我的电脑上4KB。不知何故,我认为它是64kb在你的这就是为什么它在你的计算机上完美运行。我使用文件重定向输出而不是管道。我现在可以成功地获得输出,但我仍然输入来控制任何解决方案? –