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

标签 windows winapi createprocess shellexecute

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

服务是通过以下命令创建的 (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 导致图像处理失败,因为我们高度依赖有效的时间戳。

当 Service.exe 作为服务运行时,问题(A 和 B)出现。从命令行运行 Service.exe 或 Camera.exe 时,没有出现任何问题。

今天我从服务中删除了 CreateProcess 调用(返回到 ShellExecute),问题又消失了。我在调用 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.

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

关于windows - 依赖进程创建的执行异常(ShellExecute vs CreateProcess),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32863252/

相关文章:

c++ - 获取 H.264 视频的解码器 MFT

c++ - WinApi - 如何获取 SHELLDLL_DefView

检查之前由应用程序启动的进程是否始终返回事件进程

python - 由于警告和 ValueError,无法在 Windows 的 virtualenv 中 pip 安装 PIL

c++ - 在没有 Chrome 的情况下运行 Chrome Native Client (NaCL) 插件

c# - 来自共享位置的数据的私有(private)副本

windows - TrackPopupMenu "harm"是我的 HMENU 吗?

c++ - LoadLibrary 找不到 ntoskrnl

c - 获取由 CreateProcess() 启动的进程的 PID

c++ - 如何设置从 CreateProcess 创建的进程的入口点