【问题标题】:Get executable path with AssocQueryString in C++在 C++ 中使用 AssocQueryString 获取可执行路径
【发布时间】:2019-09-28 13:52:48
【问题描述】:

喂!我需要在 C++ 中查询应用程序完整路径,例如“meshlab”->“C:\Program Files\VCG\MeshLab\meshlab.exe”

此信息存在于 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App 路径中,但我不想直接使用注册表,所以我使用 AssocQueryString 如下:

#include "pch.h"
#include <iostream>
#include <Windows.h>

#include <Shlwapi.h>

int main()
{
    char* executablePath = nullptr;
    DWORD executablePathLen = 0;
    std::string shortName = "mspaint";

    HRESULT res = AssocQueryStringA(ASSOCF_OPEN_BYEXENAME,
        ASSOCSTR_EXECUTABLE,
        shortName.c_str(),
        NULL,
        executablePath,
        &executablePathLen);

    executablePath = new char[executablePathLen];



    res = AssocQueryStringA(ASSOCF_OPEN_BYEXENAME,
        ASSOCSTR_EXECUTABLE,
        shortName.c_str(),
        NULL,
        executablePath,
        &executablePathLen);

    std::cout << executablePath; // prints: C:\Windows\system32\mspaint.exe
    delete[] executablePath;
    std::cin.get();
}

对于 mspaint,它按预期工作,但对于 meshlab,它没有。 HRESULT 是 ERROR_NO_ASSOCIATION

有什么我错过的想法吗?

更新: 也适用于 C:\Program Files (x86)\foobar2000\foobar2000.exe 中的 foobar200 我怀疑它一定与 32/64 位注册表有关。我使用的是 Windows 10 64 位,而我的应用程序是 64 位

【问题讨论】:

  • AssocQueryStringA 的返回值是多少,函数调用后&amp;executablePathLen 的结果是什么?
  • 并非每个程序都必须在注册表中列出自己。你确定meshlab可以吗?搜索您的本地注册表并查看确切位置。键名可能不是“meshlab”。一般来说,在 Windows 上查找第三方可执行文件并不是一门精确的科学,尤其是在构建它们时没有首先考虑编程访问。
  • @SevaAlekseyev 因为我很遗憾注册表中存在信息
  • ERROR_NO_ASSOCIATION 是一个非常强烈的信号
  • 用 Procmon 运行 ShellExecuteEx,看看它读到了什么。 OBTW,meshlab 是否有可能在 PATH 中?

标签: c++ windows winapi registry


【解决方案1】:

我相信ASSOCF_OPEN_BYEXENAME:ASSOCSTR_EXECUTABLE会搜索HKEY_CLASSES_ROOT\Applications

ShellExecuteEx搜索“普通目录”和the App Paths key

查找应用程序可执行文件

ShellExecuteEx 函数在其 lpFile 参数中使用可执行文件的名称调用时,函数会在多个位置查找文件。我们建议在 App Paths 注册表子项中注册您的应用程序。这样做可以避免应用程序修改系统 PATH 环境变量。

在以下位置查找文件:

  • 当前工作目录。

  • 仅 Windows 目录(不搜索子目录)。

  • Windows\System32 目录。

  • PATH 环境变量中列出的目录。

  • HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App 路径

(HKEY_CURRENT_USER 也用于最新版本的 Windows)

Assoc API 更侧重于文件关联。

如果您只是要执行该文件,那么您应该使用ShellExecuteEx。如果您只想找到完全限定的路径,您可以使用一些辅助函数为您完成一些工作:

FindExecutable 看起来很有希望,但它有一些compatibility workarounds,它还会找到用于打开注册类型的可执行文件(c:\foo\bar.txt 可能解析为c:\Windows\Notepad.exe 等,因为它使用ASSOCSTR_EXECUTABLE),

如果您想自动查找 .exe 和 .bat 等扩展名,您可以使用 PathResolve(..., PRF_REQUIREABSOLUTE|PRF_VERIFYEXISTS|PRF_TRYPROGRAMEXTENSIONS|PRF_DONTFINDLNK),但您必须注意搜索字符串不包含 \:

如果您只想查找 .exe,则必须手动附加扩展名(如果不存在),然后调用 PathFindOnPath(, NULL)

这些函数都不会在 App Paths 键中查找,它们不使用与 ShellExecuteEx 完全相同的搜索顺序(system32 在 %windir% 之前?)并且它们很可能仅限于 MAX_PATH。

如果这些功能(或您自己的等效版本)失败,那么您可以检查 App Paths 键。从注册表读取时,如果没有扩展名,则必须附加 .exe,并使用 SHQueryValueEx 之类的辅助函数来扩展 REG_EXPAND_SZ 字符串。

【讨论】:

    猜你喜欢
    • 2010-12-12
    • 1970-01-01
    • 2018-02-14
    • 2012-01-24
    • 2019-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-24
    相关资源
    最近更新 更多