У меня есть приложение-обертка, которое должно идентифицировать все опубликованные приложения в режиме XP; все они находятся в одной папке, и я использую Qt для получения всех файлов .lnk.
Этот бит работает — проблема в том, что все приложения Virtual PC используют rundll32 для запуска виртуальной машины и / или ее приложения (например, %SystemRoot%\system32\rundll32.exe %SystemRoot%\system32\VMCPropertyHandler.dll,LaunchVMSal "Windows XP Mode" "||some_id" "some_name"
), и поэтому мне нужно прочитать полную цель.
Чтение Документов MSDN, GetArguments()
на IShellLink
должен возвращать эти данные — но он только извлекает путь к rundll32.exe
и никогда с какими-либо конечными данными командной строки. GetPath()
делает то же самое, что и ожидалось, но я не вижу других методов для вызова, которые могли бы получить необходимые мне данные.
Я создал тестовый ярлык с разными стилями аргументов (/param
, -param
и просто param
), но ничего не меняет дело. Это не просто виртуальный ПК с ошибками — это относится ко всем ярлыкам.
Вот код функции:
QString GetShortcutTarget(const char* shortcut)
{
IShellLink* psl = NULL;
IPersistFile* ppf = NULL;
wchar_t wsz[MAX_PATH];
wchar_t target[MAX_PATH * 4]; // w/e
QString retval;
if ( MultiByteToWideChar(CP_ACP, 0, shortcut, -1, wsz, MAX_PATH) == 0 )
goto cleanup;
if ( FAILED(CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER, IID_IShellLink, (void **)&psl)) )
goto cleanup;
if ( FAILED(psl->QueryInterface(IID_IPersistFile, (void **)&ppf)) )
goto cleanup;
if ( FAILED(ppf->Load(wsz, STGM_READ)) )
goto cleanup;
// GetPath() and GetArguments return the same
//if ( NOERROR != psl->GetPath(target, _countof(target), nullptr, 0) )
if ( NOERROR != psl->GetArguments(target, _countof(target)) )
goto cleanup;
retval = QString::fromWCharArray(target);
cleanup:
if ( ppf )
ppf->Release();
if ( psl )
psl->Release();
return retval;
}
РЕДАКТИРОВАТЬ
Не переопределять интерфейс где-либо, включая и связывать с:
#include <objidl.h> // IPersistFile
#include <shlobj.h> // IShellLink
#pragma comment ( lib, "ole32.lib" )
#pragma comment ( lib, "uuid.lib" )
Только другой связанный с COM код находится в конструкторе и деструкторе в другом месте (да, он уже вызван!):
CoInitialize(NULL);
...
CoUninitialize();
Надеюсь, Qt не должен иметь с этим ничего общего, так как COM определенно открывает и читает .lnk ..
Я обнаружил проблему — ярлык ввода был .lnk, но не абсолютный путь к файлу; поскольку в моем текущем каталоге не было места, где был расположен ярлык, это естественным образом приводило к невозможности загрузки.
У меня была Qt итерация по абсолютным путям, но я только передавал имя файла при поиске цели. Я изменил свой предыдущий звонок в другом месте из:
file_info.fileName()
чтобы:
file_info.absoluteFilePath()
и это исправило проблему!