从 Win32

问题描述

我一直在尝试从 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,FALSE,&si,&pi);

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

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

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

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

解决方法

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

如果lpApplicationNamelpCommandLine都为非NULL,则lpApplicationName指向的空终止字符串指定要执行的模块,lpCommandLine指向的空终止字符串指定要执行的模块{1}} 指定命令行。新进程可以使用 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,FALSE,&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,...)