使用C ++中的AssocQueryString获取可执行路径

时间:2019-05-10 16:08:56

标签: c++ windows winapi registry

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

此信息存在于HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ App Paths中,但我不想直接使用注册表,因此我正在使用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位

1 个答案:

答案 0 :(得分:0)

我相信ASSOCF_OPEN_BYEXENAME:ASSOCSTR_EXECUTABLE搜索HKEY_CLASSES_ROOT\Applications

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

  

查找可执行文件

     

使用可执行文件的名称(在其lpFile参数中)调用ShellExecuteEx函数时,该函数会在多个位置查找文件。我们建议您在“应用程序路径”注册表子项中注册您的应用程序。这样做避免了应用程序需要修改系统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),但必须注意搜索字符串中不包含\:。 / p>

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

这两个函数都不在“应用程序路径”键中查找,它们没有使用与ShellExecuteEx完全相同的搜索顺序(%windir%之前是system32?),并且很可能仅限于MAX_PATH。

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