Получить исполняемый путь с AssocQueryString в C ++ - PullRequest
0 голосов
/ 10 мая 2019

Helo! Мне нужно запросить полный путь к приложению в 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

Есть идеи, что я пропустил?

UPDATE: Также хорошо работает с foobar200 из C: \ Program Files (x86) \ foobar2000 \ foobar2000.exe Я подозреваю, что это должно быть связано с 32/64 битным реестром. Я использую 64-битную Windows 10, а мое приложение 64-битное

1 Ответ

0 голосов
/ 10 мая 2019

Я считаю, ASSOCF_OPEN_BYEXENAME:ASSOCSTR_EXECUTABLE ищет HKEY_CLASSES_ROOT\Applications.

ShellExecuteEx выполняет поиск в "нормальных каталогах" и ключ путей к приложениям :

Поиск исполняемого файла приложения

Когда функция ShellExecuteEx вызывается с именем исполняемого файла в его параметре lpFile, есть несколько мест, где функция ищет файл. Мы рекомендуем зарегистрировать ваше приложение в разделе реестра «Пути к приложениям». Это избавляет приложения от необходимости изменять системную переменную среды PATH.

Файл ищется в следующих местах:

  • Текущий рабочий каталог.

  • Только каталог Windows (подкаталоги не ищутся).

  • Каталог Windows \ System32.

  • Каталоги, перечисленные в переменной среды PATH.

  • HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Пути к приложениям

(HKEY_CURRENT_USER также используется в последних версиях Windows)

Assoc API больше ориентирован на ассоциации файлов.

Если вы просто собираетесь выполнить файл, тогда вам нужно просто использовать ShellExecuteEx. Если вы просто хотите найти полный путь, вы можете использовать некоторые вспомогательные функции, чтобы выполнить часть работы за вас:

FindExecutable кажется многообещающим, но у него есть некоторые обходные пути совместимости , и он также найдет исполняемый файл, используемый для открытия зарегистрированных типов (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 строк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...