代码之家  ›  专栏  ›  技术社区  ›  Adam Haile

从服务启动进程

  •  2
  • Adam Haile  · 技术社区  · 16 年前

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

    我想做的基本工作如下:

    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的 suggestion 我修复了进程处理问题,它实际上等待进程完成。但除非我手动杀死它,否则它永远不会结束。

    3 回复  |  直到 16 年前
        1
  •  2
  •   Rob Kennedy    16 年前

    WaitForSingleObject GetExitCodeProcess 应该是进程句柄本身,而不是指向进程句柄的指针。拆下和号。

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

    一旦您正确地调用函数,并且新流程开始但没有进展,您就可以合理地确定 代码不是罪魁祸首。问题在于新进程,因此请将调试任务集中在那里,而不是服务进程中。

        2
  •  0
  •   Chris    16 年前

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

    如果这有助于您调试或不调试,通常是“A-HA!”时刻来自于认识到环境变量、路径、当前目录等可能不是您期望的服务中的内容。权限不是此类问题的最常见原因。您能提供一些关于您试图启动的外部应用程序的详细信息吗,也许这有助于您思考这个问题。

        3
  •  0
  •   Mark Ransom    16 年前

    因为您正在启动一个控制台应用程序,所以可能有隐藏的启动代码试图初始化一个控制台。一个服务没有连接到桌面上,我确信该服务启动的进程也不会是这样,因此它将无法创建控制台。这可能就是它悬挂的地方。

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