依赖进程创建的执行异常(ShellExecute vs CreateProcess)

Execution abnormalities depending on process creation (ShellExecute vs CreateProcess)

我们正在 运行ning 一个 Windows 服务,该服务负责监视一组进程。该服务基本上只负责 (a) 检查定义的作业是否 运行ning,以及 (b) 如果不是,则启动作业。

该服务是通过以下命令创建的 (sc: https://technet.microsoft.com/en-us/library/bb490995.aspx):

sc create "My Service" binPath= C:\heyoo\myservice.exe type= own start= auto error= normal
sc start "SCF Service"

该服务负责创建的作业之一是 'Camera.exe'。 Camera.exe 从连接的摄像机 (FireWire 1394) 检索视频源,并对它们进行一些处理。

一周前,该服务从使用 ShellExecute 重写为使用 CreateProcess,因此它能够更好地监控定义的作业 (因为它获取进程的句柄)

ShellExecute 调用(旧方法):

bool Execute()
{
    int result = (int)ShellExecute(NULL, "open", "C:\bin\Camera.exe", NULL, NULL, SW_SHOWDEFAULT);
    return result > 32;
}

CreateProcess 调用(新方法):

// Called with Execute("C:\bin\Camera.exe", "");
bool Execute(std::string prog, std::string args)
{
    std::string cmd = std::string(prog) + " " + args;
    char *path = new char[cmd.length()+1];
    strcpy(path, cmd.c_str());

    STARTUPINFO si = {0};
    si.cb = sizeof(STARTUPINFO);
    PROCESS_INFORMATION pi;
    ZeroMemory(&pi, sizeof(pi));

    DWORD creationFlags = REALTIME_PRIORITY_CLASS;

    BOOL result = CreateProcess(NULL, path, NULL, NULL, FALSE, creationFlags, NULL, NULL, &si, &pi);
    delete[] path;

    if (result) {
        SetProcInfo(pi);
    }

    return result;
}

使用新的 CreateProcess 方法,我们注意到 (A) 网络在一定时间间隔后系统性失败,并且 (B) 从摄像机检索的图像包含无效时间戳(正确的时间戳对我们至关重要)。

A 经常断开整个网络连接,需要重新启动才能重新联机。 B 导致图像处理失败,因为我们高度依赖有效的时间戳。

当 Service.exe 是 运行 作为服务 时, 会出现问题(A 和 B) .当从命令行 运行ning Service.exe 或 Camera.exe 时,会出现 none 的问题。

今天我从服务 (回到 ShellExecute) 中删除了 CreateProcess 调用,问题又消失了。 API 调用我做错了什么?

DWORD creationFlags = REALTIME_PRIORITY_CLASS;

这是最明显的区别。当您调用 ShellExecute 时,进程将以正常优先级创建。实时优先级的 documentation 表示:

Process that has the highest possible priority. The threads of a real-time priority class process preempt the threads of all other processes, including operating system processes performing important tasks. For example, a real-time process that executes for more than a very brief interval can cause disk caches not to flush or cause the mouse to be unresponsive.

你真的不想这样做!

0作为创建标志。 documentation 表示:

If none of the priority class flags is specified, the priority class defaults to NORMAL_PRIORITY_CLASS unless the priority class of the creating process is IDLE_PRIORITY_CLASS or BELOW_NORMAL_PRIORITY_CLASS. In this case, the child process receives the default priority class of the calling process.

就其价值而言,您可以使用 ShellExecuteEx 而不是 ShellExecute 来获取进程句柄。事实上,你应该总是更喜欢 ShellExecuteEx 而不是 ShellExecute 因为后者不能正确报告错误。即便如此,您还是在创建一个新流程,因此 CreateProcess 是该任务的正确函数。