【问题标题】:How to to open a program with CreateProcess if only its name is known?如果只知道名称,如何使用 CreateProcess 打开程序?
【发布时间】:2016-07-02 08:45:18
【问题描述】:

如下例所示,我尝试使用 Windows API 函数 CreateProcess 从 Windows 应用程序启动 Google 的 Chrome 浏览器。

我遇到的问题是我不知道 Chrome 应用程序(或程序路径中的任何其他应用程序)的路径。我怎样才能得到这个?

在下面的代码中,我注释了三个不同的示例。如果我启动“calc”,计算器会在 Windows/System32 路径中启动。如果我用它运行的应用程序的完整路径启动 Chrome。但是,如果我省略了路径并尝试启动“chrome”,则会收到错误 #2。

#include <windows.h>
#include <stdio.h>
#include <tchar.h>

void _tmain()
{

    char* cmd = "calc"; // works... calc.exe is in windows/system32 
    // char* cmd = "chrome"; // doesn't work... how can I add the path if it's not known (e.g. windows installed on D:\)
    // char* cmd = "c:/program files (x86)/google/chrome/application/chrome"; // works (even without extension .exe)

    STARTUPINFO si;
    PROCESS_INFORMATION pi;

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

    // Start the child process. 
    if (!CreateProcess(NULL,   // No module name (use command line)
        cmd,            // Command line
        NULL,           // Process handle not inheritable
        NULL,           // Thread handle not inheritable
        FALSE,          // Set handle inheritance to FALSE
        0,              // No creation flags
        NULL,           // Use parent's environment block
        NULL,           // Use parent's starting directory 
        &si,            // Pointer to STARTUPINFO structure
        &pi)           // Pointer to PROCESS_INFORMATION structure
        )
    {
        printf("CreateProcess failed (%d).\n", GetLastError());
        return;
    }

    // Wait until child process exits.
    WaitForSingleObject(pi.hProcess, INFINITE);

    // Close process and thread handles. 
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

注意:如果我在 Windows 运行命令窗口中输入“chrome”(不带引号),Chrome 也会启动。我正在寻找的是相同的功能。但是,我的应用程序可以驻留在任何地方,并且不一定位于与 Chrome 相同的驱动器上。

【问题讨论】:

  • 尝试system("path") 在您的应用程序运行时查看 PATH env.variable 的内容
  • 当您输入calc 和当您输入chrome 时,cmd 控制台会发生什么?
  • 我只是需要类似的东西,并通过在调用CreateProcess之前调用PathFindOnPath找到完整路径来解决问题。但在这种特定情况下,对于想要启动 Chrome 浏览器,我认为 David Heffernan 的回答更好。我还要求您重新考虑明确启动 Chrome 的想法。如果用户喜欢不同的浏览器,比如 Firefox 或 Opera,该怎么办?只需使用 ShellExecuteEx 启动网页或 HTML 文档,允许用户的默认浏览器打开它,无论是什么。

标签: c++ c windows winapi


【解决方案1】:

如果你真的必须使用CreateProcess,那么你需要找出它的安装位置并将完整路径传递给可执行文件。这将需要一些注册表黑客攻击。

不过,我觉得有一种更简单、更健壮的方法。 Chrome 在AppPaths 注册表中注册自己,因此ShellExecuteEx 使用指定为L"chrome" 的文件,默认动词将完成这项工作。

【讨论】:

  • @david-hefferman:因为我需要访问流程信息,所以我必须使用 CreateProcess。然而,你让我走上了正轨。在我的解决方案中,我最终使用 RegOpenKeyEx 来获取注册表项的句柄,然后使用 RegQueryValueEx 获取路径的值。不像我预期的那么简单,但效果很好。
  • 不是这样。您可以从 ShellExecuteEx 获取进程句柄。
  • 我感兴趣的是 PROCESS_INFORMATION 结构。我不知道(并且仍然不知道)如何使用 ShellExecuteEx 来获得它。如果可能的话,它可能会更容易。然而,一旦我有了如何去做的想法,只需要几行代码就可以了。
  • @ShyRobbiani PROCESS_INFORMATION 为您提供的唯一信息是进程 ID+句柄和线程 ID+句柄。如果您使用SEE_MASK_NOCLOSEPROCESSShellExecuteEx 可以为您提供进程句柄。其他值可以使用GetProcessId()CreateToolhelp32Snapshot()/Thread32First()(参见Enumerating threads in a process)和OpenThread()从进程句柄中获取。
【解决方案2】:

这可能与 WinAPI 和 CreateProcess 函数无关,而仅与环境变量 PATH 相关。默认情况下,它包含所有标准 Windows 命令的路径,例如 calcnotepad,但您必须为稍后添加的其他命令添加路径,无论是在 Program Files 下还是其他任何地方。

做什么:

  • 仔细记下chrome的实际路径
  • 打开控制面板/系统/高级系统参数
  • 单击环境变量:您会在用户和系统变量中找到一个 PATH(大小写无关)。
  • 在其中添加 chrome 的路径(系统适用于所有用户)

现在应该可以在不指定完整路径的情况下启动 chrome。

注意:不确定以上所有内容的实际标签,我自己的盒子会说法语......

【讨论】:

  • "calc""notepad" 不是命令。它们是程序或应用程序。
猜你喜欢
  • 2010-10-05
  • 1970-01-01
  • 1970-01-01
  • 2015-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多