我有一个DLL作为扩展加载到第三方父进程中。从这个DLL我使用CreateProcess API实例化外部进程(我自己的)。这在99.999%的情况下效果很好,但有时会突然失败并永久停止工作(也许重启父进程会解决这个问题,但这是不可取的,我不想在我解决问题之前建议这样做。)即使CreteProcess()没有报告错误并且GetExitCodeProcess()返回128,也不再调用外部进程来表示失败。这是我正在做的简化版本:
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE;
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
if(!CreateProcess(
NULL, // No module name (use command line).
"<my command line>",
NULL, // Process handle not inheritable.
NULL, // Thread handle not inheritable.
FALSE, // Set handle inheritance to FALSE.
CREATE_SUSPENDED, // Create suspended.
NULL, // Use parent's environment block.
NULL, // Use parent's starting directory.
&si, // Pointer to STARTUPINFO structure.
&pi)) // Pointer to PROCESS_INFORMATION structure.
{
// Handle error.
}
else
{
// Do something.
// Resume the external process thread.
DWORD resumeThreadResult = ResumeThread(pi.hThread);
// ResumeThread() returns 1 which is OK
// (it means that the thread was suspended but then restarted)
// Wait for the external process to finish.
DWORD waitForSingelObjectResult = WaitForSingleObject(pi.hProcess, INFINITE);
// WaitForSingleObject() returns 0 which is OK.
// Get the exit code of the external process.
DWORD exitCode;
if(!GetExitCodeProcess(pi.hProcess, &exitCode))
{
// Handle error.
}
else
{
// There is no error but exitCode is 128, a value that
// doesn't exist in the external process (and even if it
// existed it doesn't matter as it isn't being invoked any more)
// Error code 128 is ERROR_WAIT_NO_CHILDREN which would make some
// sense *if* GetExitCodeProcess() returned FALSE and then I were to
// get ERROR_WAIT_NO_CHILDREN with GetLastError()
}
// PROCESS_INFORMATION handles for process and thread are closed.
}
可以从Windows资源管理器或命令行手动调用外部进程,它可以自行启动。在执行任何实际工作之前,调用它会创建一个日志文件并记录一些有关它的信息。但是如上所述调用此日志信息根本不会出现,所以我假设外部进程的主线程永远不会进入main()(我现在正在测试这个假设。)
我至少可以做一件事来试图规避问题(不要启动线程暂停),但我首先要先了解失败的根源。有谁知道可能导致这种情况的原因以及如何解决这个问题?
答案 0 :(得分:1)
引自GetExitCodeProcess上的MSDN文章:
如果流程已终止,则可以返回以下终止状态:
鉴于您描述的情景,我认为最可能的原因是第三种:未处理的异常。查看您创建的流程的来源。
答案 1 :(得分:1)
查看桌面堆内存。
本质上,桌面堆问题归结为耗尽资源(例如,启动太多进程)。当您的应用程序用完这些资源时,其中一个症状是您将无法启动新进程,并且对CreateProcess的调用将失败并显示代码128.
请注意,您运行的上下文也有一些效果。例如,作为服务运行,与在控制台应用程序中测试代码相比,您将耗尽桌面堆。
这个post有很多关于桌面堆的好信息
Microsoft Support也有一些有用的信息。
答案 2 :(得分:0)
我可以从您的代码示例中找到2个问题
1.获取前2个参数的使用权,先使用creatprocess命令。硬编码路径并调用notepad.exe并查看是否出现。继续调整这个,直到你有记事本运行。
2.Contrary to your comment,如果您已将新进程的currentdirectory参数传递为NULL,它将使用进程的当前工作目录从父进程启动新进程,而不是父进程。
我认为由于无法在新路径中解析的dll依赖项,外部进程exe无法正常启动。
ps:在@ err,hr的调试器监视中,它会告诉你上一个错误代码的解释,