【发布时间】:2013-06-01 00:19:17
【问题描述】:
我正在维护某人只是在他们退休之前编写的代码,这意味着我找不到他们来提问。 :-) 这基本上是一个用于启动程序的 C++ 包装器。有问题的代码块是这样的:
BOOL bSuccess = CreateProcess(NULL, (char *)strBatFile.c_str(),
NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, strLocalWorkingDir.c_str(), &si, &pi );
if( bSuccess )
{
DWORD dwMillisec = INFINITE;
DWORD dwWaitStatus = WaitForSingleObject( pi.hProcess, dwMillisec );
if( dwWaitStatus == WAIT_OBJECT_0 )
{
DWORD dwExitCode = NULL;
GetExitCodeProcess( pi.hProcess, &dwExitCode );
nRet = (int)dwExitCode;
}
CloseHandle( pi.hThread );
CloseHandle( pi.hProcess );
}
else
nRet = START_PROCESS_FAILED;
如果一次只运行一个实例,它总是可以正常工作。但是,如果在很短的时间范围内运行多个,则其中大约一半的 dwExitCode 设置为 1 而不是 0,即使进程没有崩溃,并且内部程序写入的日志文件正在完成。
所以澄清一下,这个过程总是开始正常,它总是进入 if 语句,但它是由 GetExitCodeProcess 设置的 dwExitCode 的值,它不包含预期的内容。由于我们对此进行了错误检查,因此我们将其中一些运行标记为不完整,而实际上它们都很好。
有什么方法可以将此值设置为与进程退出代码不同的值?和/或是否有我可以同时运行的实用程序来确认退出代码是我认为的那样?
谢谢!
ETA: 刚刚意识到这是将内部程序调用放在一个 .bat 文件中 - “C:\\ --flags etc...”,然后在第二个参数,而不是直接使用 lpApplicationName 调用它。不知道这是否有所作为!但是当我打印进程的 PID 时,我可以看到它是 cmd.exe 进程的 PID,然后我们的程序有一个子 PID。但是,当我在 Process Monitor 中进行跟踪时,我可以看到父母和孩子都以退出代码 0 退出。
【问题讨论】:
-
您是否偶然在多个线程中同时共享
pi?否则,此代码返回 1 的 ExitCode 的唯一方法是生成的进程确实返回值 1,或者nRet未正确初始化(因为dwWaitStatus值不是WAIT_OBJECT_0更新nRet)。 -
GetExitCodeProcess似乎不太可能被破坏 - 它经常被 Windows 和第三方代码用于命令提示符和 GUI 程序。您确定将正确的 hProcess 值传递给GetExitCodeProcess。 -
您没有检查
GetExitCodeProcess的返回值。来自文档:“如果函数成功,则返回值非零。如果函数失败,则返回值为零。要获取扩展错误信息,请调用 GetLastError。”。您的代码不知道它是成功还是失败,因为它不检查。 -
除了缺少的检查之外,该代码片段看起来很合理,但是如果不查看已启动的程序或不知道它的作用,很难给出明确的答案:您确定它总是正确设置退出成功代码为0,错误代码为1? MSDN
GetExitCodeProcess()文档中列出了进程设置其退出代码的不同方式。 -
@RemyLebeau - nRet 已提前初始化,在这方面看起来一切正常。我必须进一步研究线程(我对这种类型的编码很陌生),但这会产生什么影响?