【问题标题】:Using CreateProcess() and exit/close the opened Application使用 CreateProcess() 并退出/关闭打开的应用程序
【发布时间】:2016-10-31 01:34:11
【问题描述】:

我正在构建一个可以打开 Sublime 文本并在一段时间后关闭应用程序本身的程序。我不知道如何使用现有代码关闭应用程序。

这是我目前所拥有的:

STARTUPINFO         siStartupInfo;
PROCESS_INFORMATION piProcessInfo;

memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));

siStartupInfo.cb = sizeof(siStartupInfo);

if (CreateProcess(L"C:\\Program Files\\Sublime Text 2\\sublime_text.exe",       
    L" source.cpp",                 
    NULL,
    NULL,
    FALSE,
    CREATE_DEFAULT_ERROR_MODE,
    NULL,
    NULL,
    &siStartupInfo,
    &piProcessInfo) == FALSE)

    WaitForSingleObject(piProcessInfo.hProcess, INFINITE);

::CloseHandle(piProcessInfo.hThread);
::CloseHandle(piProcessInfo.hProcess);

【问题讨论】:

  • &piProcessInfo) == FALSE) 行删除“==FALSE” - 根据doc CreateProcess 如果成功则返回非零值(即非 FALSE)
  • 为什么需要强制终止进程?通常,您使用WaitForSingleObject 等待进程自行退出。对于交互式过程,“自行退出”实际上是“用户退出它”。如果我开始在那个 Sublime Text 窗口中输入内容,那将是对用户非常不利的,然后你在我有机会保存之前从我下面杀死了这个进程。
  • @CodyGray 该程序在某种意义上是有时间限制的,我需要在一段时间后终止应用程序。你能在那个方向帮忙吗?

标签: c++ windows winapi


【解决方案1】:

首先,如果CreateProcess() 失败,你正在调用WaitForSingleObject()CloseHandle(),这是没用的。除非它成功,否则不要调用这些函数。

其次,您正在调用CreateProcess() 的Unicode 版本,它有一个警告,即您的代码无法处理。根据CreateProcess() documentation

lpCommandLine [输入、输出、可选]
要执行的命令行。此字符串的最大长度为 32,768 个字符,包括 Unicode 终止空字符。如果 lpApplicationName 为 NULL,则 lpCommandLine 的模块名称部分仅限于 MAX_PATH 字符。

此函数的 Unicode 版本 CreateProcessW 可以修改此字符串的内容。因此,此参数不能是指向只读内存的指针(例如 const 变量或文字字符串)。如果此参数是一个常量字符串,该函数可能会导致访问冲突。

第三,如果你想在超时后终止进程,你可以使用TerminateProcess(),但这是蛮力的,应该尽可能避免。 Sublime 有一个 UI,因此首选的解决方案是要求 UI 自行关闭,然后等待它这样做,如 MSDN 上所述:

How To Terminate an Application "Cleanly" in Win32.

如果您绝对必须关闭某个进程,请按照以下步骤操作:

  1. 向您要关闭的进程拥有的所有顶级窗口发布 WM_CLOSE。许多 Windows 应用程序通过关闭来响应此消息。

    注意:控制台应用程序对 WM_CLOSE 的响应取决于它是否安装了控制处理程序。

    使用 EnumWindows() 查找目标窗口的句柄。在您的回调函数中,检查 Windows 的进程 ID 是否与您要关闭的进程匹配。您可以通过调用 GetWindowThreadProcessId() 来执行此操作。建立匹配后,使用 PostMessage() 或 SendMessageTimeout() 将 WM_CLOSE 消息发布到窗口。

  2. 使用 WaitForSingleObject() 等待进程的句柄。确保使用超时值等待,因为在很多情况下 WM_CLOSE 不会关闭应用程序。请记住使超时时间足够长(使用 WaitForSingleObject() 或 SendMessageTimeout()),以便用户可以响应为响应 WM_CLOSE 消息而创建的任何对话框。

  3. 如果返回值为 WAIT_OBJECT_0,则应用程序完全关闭了自己。如果返回值为 WAIT_TIMEOUT,则必须使用 TerminateProcess() 关闭应用程序。

    注意:如果您从 WaitForSingleObject() 获得的返回值不是 WAIT_OBJECT_0 或 WAIT_TIMEOUT,请使用 GetLastError() 来确定原因。

通过执行这些步骤,您可以为应用程序提供干净关闭的最佳机会(除了 IPC 或用户干预)。

话虽如此,请尝试更多类似的东西:

BOOL CALLBACK SendWMCloseMsg(HWND hwnd, LPARAM lParam)
{
    DWORD dwProcessId = 0;
    GetWindowThreadProcessId(hwnd, &dwProcessId);
    if (dwProcessId == lParam)
        SendMessageTimeout(hwnd, WM_CLOSE, 0, 0, SMTO_ABORTIFHUNG, 30000, NULL);
    return TRUE;
}

...

STARTUPINFO         siStartupInfo;
PROCESS_INFORMATION piProcessInfo;

memset(&siStartupInfo, 0, sizeof(siStartupInfo));
memset(&piProcessInfo, 0, sizeof(piProcessInfo));

siStartupInfo.cb = sizeof(siStartupInfo);

WCHAR szFilename[] = L"C:\\full path to\\source.cpp";

if (CreateProcess(L"C:\\Program Files\\Sublime Text 2\\sublime_text.exe",       
    szFileName,                 
    NULL,
    NULL,
    FALSE,
    CREATE_DEFAULT_ERROR_MODE,
    NULL,
    NULL,
    &siStartupInfo,
    &piProcessInfo))
{
    CloseHandle(piProcessInfo.hThread);
    WaitForInputIdle(piProcessInfo.hProcess, INFINITE);

    if (WaitForSingleObject(piProcessInfo.hProcess, SomeTimeoutHere) == WAIT_TIMEOUT)
    {
        EnumWindows(&SendWMCloseMsg, piProcessInfo.dwProcessId);
        if (WaitForSingleObject(piProcessInfo.hProcess, AnotherTimeoutHere) == WAIT_TIMEOUT)
        {
            // application did not close in a timely manner, do something...

            // in this example, just kill it.  In a real world
            // app, you should ask the user what to do...
            TerminateProcess(piProcessInfo.hProcess, 0);
        }
    }

    CloseHandle(piProcessInfo.hProcess);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多