C ++ ShellExecute специально не открывает файлы LNK - PullRequest
0 голосов
/ 17 января 2019

-Windows 7 64-bit
-Визуальная Студия 2013 (v120)
-Юникод включен
-Target Build- Отладка 32-битная

Я хотел бы создать модуль запуска (для личного использования), однако я не могу заставить ShellExecute работать со всеми типами файлов или путями, особенно с ярлыками (LNK). Я исследовал и попробовал следующее во многих комбинациях ...
-Я использую escape-последовательности
-Я добавляю расширение файла (и пробовал без)
-Я включил Windows.h
-Печатный каталог FindFirstFile / FindNextFile, чтобы явно убедиться, что путь не содержит опечаток
-Пробовал использовать как литерал, так и переменную в качестве аргумента пути к файлу
-Пробовал запустить VS с правами администратора
-Пробовал ShellExecute, ShellExecuteA, ShellExecuteEx и System (с соответствующими наборами символов)
-Пробовал NULL, "runas" и "open" для глагола
-Отлично запускается из командной строки или проводника по тому же пути
-Пробовал использовать макрос% USERPROFILE% вместо имени пользователя (возвращает 2)
-Похоже на работу с EXE и URL
- Кажется, не работает ни с одним LNK по любому пути, включая C: \ напрямую

Подозреваемый вопрос
-32-битное / 64-битное расхождение
-UAC / Privelages
-Символ набора
Расширение файла
-Антивирусное вмешательство (хотя AV не предупреждает меня о каких-либо проблемах), и я проверил, отключив AV

Вот одна из самых простых программ, которые я пробовал ...

#include "stdafx.h"
#include <iostream>
#include <Windows.h>
#include <atlstr.h>

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);

    // Variables below for testing as path argument
    // Paths that end with LNK are the only ones that I can't get to launch
    CStringW link("C:\\Users\\Home\\Documents\\Art\\blender.lnk"); // Doesn't work
    CStringW target("C:\\Program Files\\Blender Foundation\\Blender\\blender.exe"); // Launches software as expected
    CStringW url("https://stackoverflow.com"); // Launches browser with URL as expected

    int error = reinterpret_cast<int>(ShellExecute(
        NULL, 
        NULL, 
        L"C:\\Users\\Home\\Documents\\Art\\blender.lnk", // Using literal with LNK extension also does not work
        NULL, 
        NULL, 
        SW_SHOWDEFAULT
        ));


    // EVEN SYSTEM CAN NOT FIND THE PATH!!!
    // system("C:\\Users\\Home\\Documents\\Art\\blender.lnk");

    std::cout << error << std::endl; // Returns 3 "The specified path was not found.".

    // Free COM
    CoUninitialize();

    return 0;
}

1 Ответ

0 голосов
/ 17 января 2019

Сначала убедитесь, что ваш файл .lnk находится в пути.

Затем (и наиболее вероятная причина вашей проблемы) проверьте, что ваше имя файла .lnk создано правильно. Чтобы убедиться, что это не похоже на «blender.lnk.lnk» (я могу воспроизвести вашу проблему, если я установил как это).

Вы также можете попытаться самостоятельно проанализировать путь к файлу ссылки. Вот образец:

void ShortcutToRealpath(LPWSTR pszString, LPSTR pdzString)
{
    IShellLink   *pShellLink;
    HRESULT hRes;

    ::CoInitialize(NULL);
    hRes = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&pShellLink);
    if (SUCCEEDED(hRes))
    {
        IPersistFile   *ppf;
        hRes = pShellLink->QueryInterface(IID_IPersistFile, (void **)&ppf);
        if (SUCCEEDED(hRes))
        {
            hRes = ppf->Load(pszString, TRUE);
            if (SUCCEEDED(hRes))
            {
                pShellLink->GetPath(pdzString, MAX_PATH, NULL, 0);
            }
            ppf->Release();
        }
        pShellLink->Release();
    }
    ::CoUninitialize();
}

Когда я создаю платформу x86, путь будет проанализирован следующим образом: enter image description here Вот почему ваша программа не может найти путь.

И если я выберу x64: enter image description here

Поместите целевой файл в соответствующий файл.

EDIT:

После того, как я протестировал его с помощью инструмента MS Procmom.exe , я нашел что-то другое, если он будет работать как 32-битный, он покажет: enter image description here

Значение ключа - C:\Program Files (x86), и если мы запустим его как 64-разрядный, ключ будет ссылаться на «HKLM \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ ProgramFilesDir», значение ключа - C:\Program Files. После того, как я проверил реестр: enter image description here enter image description here Кажется, что C:\Program Files не отображается по умолчанию в 32-разрядном реестре (я не уверен насчет конкретной причины). Если вы измените ключ ProgramFilesDir на C:\Program Files в 32-битном реестре, проблема будет исправлена.

...