2

我正在尝试从服务启动另一个进程(它是一个控制台应用程序,它收集一些数据并将其写入注册表)但由于某种原因我无法让它正确启动。

我正在尝试做的基本情况如下:

  1. 启动进程
  2. 等待过程完成
  3. 从进程中检索返回码

我目前正在使用以下代码:

STARTUPINFO info={sizeof(info)};
PROCESS_INFORMATION processInfo;
if (CreateProcess(PATH, ARGS, NULL, NULL, TRUE, 0, NULL, NULL, &info, &processInfo))
{
    ::WaitForSingleObject(processInfo.hProcess, INFINITE);

    DWORD exit = 100;
    GetExitCodeProcess(processInfo.hProcess, &exit);

    CloseHandle(processInfo.hProcess);
    CloseHandle(processInfo.hThread);

    return exit;
}

在调用 CreateProcess() 时,它成功并进入 if 语句的主体。对 WaitForSingleObject 的调用会立即返回,这是不应该的,因为该过程大约需要 20-30 秒才能完成。最后,调用 GetExitCodeProcess() 失败并且没有设置值“exit”。

仅供参考,这是我在其他地方成功使用过的代码,只是不在服务中。

难道是它是从服务启动的并且存在权限问题?

编辑: 我现在意识到它实际上会启动应用程序(我可以在 TaskMan 中看到它),但它似乎被卡住了。它在那里,但没有做任何事情。
根据 Rob Kennedy 的建议,我修复了进程句柄问题,它实际上确实在等待进程完成。但除非我手动杀死它,否则它永远不会完成。

4

3 回答 3

2

WaitForSingleObjectGetExitCodeProcess期望进程句柄本身,而不是指向进程句柄的指针。删除与号。

另外,检查返回值并GetLastError在它们失败时调用。这将帮助您诊断未来的问题。永远不要假设 API 函数总是会成功。

一旦你正确调用了函数,并且新进程开始但没有进展,你就可以合理地确定这段代码不是罪魁祸首。问题出在新进程上,所以将调试任务集中在新进程上,而不是服务进程上。

于 2008-11-25T18:04:14.437 回答
0

在更新和编辑之后,这听起来像是从服务启动进程时的许多可能陷阱之一。是否有任何可能性 - 您的外部进程正在等待用户交互?我能想到三个主要示例,例如一个命令行应用程序,在某些情况下可能需要键盘输入(例如,“cmd /c del *.*”之类的内容需要用户确认)。如果应用程序需要一个窗口并且正在显示它但您看不到它,则其他示例将适用。如果是这种情况,您可能希望在调试时将服务设置为“与桌面交互”,然后能够看到应用程序窗口(或意外的 Windows 错误消息,例如无法找到 DLL 或类似信息)。

如果这有助于您进行调试,通常是“啊哈!” 时刻来自于意识到环境变量、路径、当前目录等可能不是您对服务的期望。权限不是此类问题的最常见原因。您能否提供有关您尝试启动的外部应用程序的一些详细信息,也许这将有助于思考这一点。

于 2008-11-25T18:29:47.490 回答
0

由于您正在启动控制台应用程序,因此可能存在试图初始化控制台的隐藏启动代码。服务未附加到桌面,并且我确定该服务启动的进程也不会,因此它将无法创建控制台。那可能是它挂起的地方。

如果可以,请尝试将您的进程更改为完整的 Windows 可执行文件,但跳过您尝试创建窗口的部分。

于 2008-11-25T18:30:08.597 回答