执行异常取决于进程创建(ShellExecute vs CreateProcess)

时间:2015-09-30 10:02:05

标签: windows winapi createprocess shellexecute

我们正在运行一个Windows服务,负责监控一组进程。该服务基本上只负责(a)检查已定义的作业是否正在运行,以及(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来使用C​​reateProcess,因此它能够更好地监控已定义的作业(因为它获得了处理的HANDLE)

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)仅 。从命令行运行Service.exe或Camera.exe时,不会出现任何问题。

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

1 个答案:

答案 0 :(得分:3)

DWORD creationFlags = REALTIME_PRIORITY_CLASS;

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

  

具有最高优先级的进程。实时优先级类进程的线程抢占所有其他进程的线程,包括执行重要任务的操作系统进程。例如,执行时间超过一小段时间的实时进程可能导致磁盘缓存不刷新或导致鼠标无响应。

你真的不想这样做!

0作为创建标记传递。 documentation说:

  

如果未指定任何优先级类别标志,则优先级类默认为NORMAL_PRIORITY_CLASS,除非创建进程的优先级类别为IDLE_PRIORITY_CLASS或BELOW_NORMAL_PRIORITY_CLASS。在这种情况下,子进程接收调用进程的默认优先级。

对于它的价值,您可以使用ShellExecuteEx而不是ShellExecute来获取流程处理。实际上,您应该始终选择ShellExecuteExShellExecute,因为后者无法正确报告错误。即便如此,您正在创建一个新流程,因此CreateProcess是该任务的正确功能。