首页 文章

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

提问于
浏览
1

我们正在运行一个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来使用CreateProcess,因此它能够更好地监视已定义的作业(因为它获取了进程的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导致图像处理失败,因为我们高度依赖于有效时间戳 .

问题(A和B)仅在Service.exe作为服务运行时出现 . 从命令行运行Service.exe或Camera.exe时,不会出现任何问题 .

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

1 回答

  • 3
    DWORD creationFlags = REALTIME_PRIORITY_CLASS;
    

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

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

    你真的不想这样做!

    0 作为创建标志传递 . documentation说:

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

    对于它的 Value ,您可以使用 ShellExecuteEx 而不是 ShellExecute 来获取进程句柄 . 事实上,你应该总是更喜欢 ShellExecuteExShellExecute ,因为后者无法正确报告错误 . 即便如此,您正在创建一个新流程,因此 CreateProcess 是该任务的正确功能 .

相关问题