Возвращаясь ко временам Windows XP, можно использовать следующий код, чтобы узнать, не существует ли файловая ассоциация для расширения:
TCHAR buffPath[MAX_PATH] = {0};
DWORD dwszBuffPath = MAX_PATH;
HRESULT hR = ::AssocQueryString(
ASSOCF_NOFIXUPS | ASSOCF_VERIFY,
ASSOCSTR_EXECUTABLE,
_T(".weirdassextension"),
NULL,
buffPath,
&dwszBuffPath);
if(hR != S_OK &&
hR != E_POINTER)
{
//Association does not exist
}
Но начиная с Windows 8, AssocQueryString
Возврат API S_OK
а также buffPath
настроен на что-то вроде C:\WINDOWS\system32\OpenWith.exe
если ничего не находит.
Есть ли лучший способ определить, что расширение файла не связано с Shell?
PS. Я не хочу просто сравнивать имя файла с OpenWith.exe
, Что если есть законный исполняемый файл, который называется просто так … Должен быть лучший способ.
Я думаю, что понял. Хитрость заключалась в том, чтобы использовать правильные флаги. Это похоже на работу с XP и выше:
WCHAR wbuffPath[MAX_PATH] = {0};
DWORD dwszBuffPath = MAX_PATH;
HRESULT hR = ::AssocQueryStringW(ASSOCF_INIT_IGNOREUNKNOWN,
ASSOCSTR_EXECUTABLE,
L".weirdassextension",
NULL,
wbuffPath,
&dwszBuffPath);
if(hR == 0x80070483) // HRESULT_FROM_WIN32(ERROR_NO_ASSOCIATION)
{
//The association is missing
}
Там есть еще один трюк, который потребовал у меня некоторое время, чтобы выяснить — не используйте AssocQueryStringA()
, Шим для AssocQueryStringA()
который преобразует свои переданные строковые параметры в Unicode, имеет ошибку в XP (и очевидно в Vista а также) это приведет к сбою этого API в этих ОС. Итак, если вы делаете свое собственное преобразование ANSI в Unicode и вызываете AssocQueryStringW()
проблема исчезнет (очевидно, 14 лет не достаточно для того, чтобы Microsoft исправила эту ошибку?).
Других решений пока нет …