【问题标题】:Launch an .exe file from Win32从 Win32 启动 .exe 文件
【发布时间】:2021-05-08 06:28:11
【问题描述】:

我一直在尝试从 Win32 应用程序启动 exe 文件,但是我无法让它工作。我也想向它传递一个论点,但我认为我做的不正确。之前在这里问过类似的问题,但似乎他们想运行命令(cmd.exe),而不是启动另一个 exe 文件。具体来说,我想启动 Java appletviewer。

我当前的代码是这样的:

LPCWSTR pszViewerPath = L"C:\\Path\\to\\appletviewer.exe"; // I know that this path is correct
PWSTR pszFilePath;
// get the path to the HTML file to pass to appletviewer.exe, store it in pszFilePath...

STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));

CreateProcess(pszViewerPath,
   pszFilePath,
   NULL,
   NULL,
   FALSE,
   0,
   NULL,
   NULL,
   &si,
   &pi);

CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

我遇到的问题是命令提示符窗口短暂出现,然后消失得无影无踪。

我做错了什么?我原本打算使用ShellExcecute,但读到那效率很低。

我该如何解决这个问题?感谢您的帮助。

【问题讨论】:

  • 您不检查错误。从修复它开始。文档告诉你怎么做。
  • "命令提示符窗口短暂出现" - 这是您运行控制台应用程序时完全正常的行为..."在消失之前" - ...因为应用程序没有等待任何用户输入的请求。
  • 如果你使用LPCWSTR,你应该将它初始化为LPCWSTR pszViewerPath = L"C:\\Path\\to\\appletviewer.exe";。并确保调用CreateProcessW 函数。而你用pszFilePath好像是错的,参数表示要执行的命令行,而你没有初始化。参考:CreateProcessW function

标签: winapi createprocess


【解决方案1】:

当同时使用CreateProcess()lpApplicationNamelpCommandLine 参数时,习惯上重复应用程序文件路径作为第一个命令行参数。这甚至在CreateProcess() documentation 中有说明:

如果lpApplicationNamelpCommandLine都不是NULL,则lpApplicationName指向的以null结尾的字符串指定要执行的模块,lpCommandLine指向的以null结尾的字符串指定命令行.新进程可以使用GetCommandLine 检索整个命令行。 用 C 编写的控制台进程可以使用 argcargv 参数来解析命令行。因为argv[0]是模块名,所以C程序员一般会重复模块名作为命令行中的第一个记号。

试试这样的:

LPCWSTR pszViewerPath = L"C:\\Path\\to\\appletviewer.exe"; // I know that this path is correct

PWSTR pszFilePath;
// get the path to the HTML file to pass to appletviewer.exe, store it in pszFilePath...

PWSTR pszCmdLine = (PWSTR) malloc((lstrlen(pszViewerPath) + lstrlen(pszFilePath) + 6) * sizeof(WCHAR));
if (!pszCmdLine)
{
    // error handling...
}
else
{
    wsprintf(pszCmdLine, L"\"%s\" \"%s\"", pszViewerPath, pszFilePath);

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));
    si.cb = sizeof(si);
    ZeroMemory(&pi, sizeof(pi));

    if (!CreateProcess(
        pszViewerPath,
        pszCmdLine,
        NULL,
        NULL,
        FALSE,
        0,
        NULL,
        NULL,
        &si,
        &pi))
    {
        // error handling...
    }
    else
    {
        // optional: wait for the process to terminate...
        WaitForSingleObject(pi.hProcess, INFINITE);

        CloseHandle(pi.hProcess);
        CloseHandle(pi.hThread);
    }

    free(pszCmdLine);
}

在这种情况下,使用lpApplicationName 参数根本没有意义:

如果 lpApplicationName 为 NULL,则命令行的第一个空格分隔标记指定模块名称。如果您使用的是包含空格的长文件名,请使用带引号的字符串来指示文件名的结束位置和参数的开始位置

CreateProcess(NULL, pszCmdLine, ...)

【讨论】:

  • 谢谢!这实际上对其他应用程序也非常有帮助。顺便说一句,缺少的L 是我写问题时犯的一个错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多