Как 32-разрядное приложение может найти расположение каталога 64-разрядных программных файлов в 64-разрядной версии Windows Vista?

Я борюсь с проблемой того, как определить расположение каталога 64-битных программных файлов в 64-битной Windows Vista из 32-битного приложения.

Звонки в SHGetKnownFolderPath(FOLDERID_ProgramFilesX64) не возвращай ничего. В статье MSDN KNOWNFOLDERID также говорится, что этот конкретный вызов с FOLDERID_ProgramFilesX64 не поддерживается для 32-битного приложения.

Я бы хотел как можно больше не указывать путь к "C:\Program Files". Делать что-то вроде GetWindowsDirectory()извлечение диска из возвращаемого значения и добавление к нему "\Program Files" также не является привлекательным.

Как 32-разрядное приложение может правильно определить местоположение папки в 64-разрядной версии Windows Vista?

Фон

В нашем приложении есть служебный компонент, который должен запускать другие процессы на основе запросов от пользовательского сеанса. Запускаемые приложения могут быть 32-разрядными или 64-разрядными. Мы делаем это через CreateProcessAsUser() путем передачи токена от инициации пользовательского сеанса. Для звонка CreateProcessAsUserмы создаем блок среды через CreateEnvironmentBlock() API. Проблема в том, что CreateEnvironmentBlock()с помощью токена приложения пользовательского сеанса создает блок с ProgramW6432="C:\Program Files (x86)", что является проблемой для 64-разрядных приложений. Нам нужно переопределить это с надлежащим значением.

4 ответа

Решение

Как вы упомянули, использование SHGetKnownFolderPath из 32-разрядного приложения не будет работать в 64-разрядной операционной системе. Это потому, что эмуляция Wow64 действует.

Однако вы можете использовать RegOpenKeyEx, передавая флаг KEY_WOW64_64KEY а затем прочитайте каталог программных файлов из реестра.

Расположение в реестре:

HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion

Вас интересует строковое значение:

ProgramFilesDir

Если вы внимательно прочитаете эту страницу, то увидите, что FOLDERID_ProgramFilesX64 поддерживается для 32-битных приложений в 64-битной ОС. Это НЕ поддерживается на 32-битной ОС, что имеет смысл.

Вы также можете запросить переменную среды ProgramW6432, Очевидно, что он существует только в 64-битной Windows, но он должен возвращать настоящий каталог 64-битных программных файлов, и, похоже, он определен как для 64-битных, так и для 32-битных программ. По крайней мере, у меня это сработало (C#, GetEnvironmentVariable)...

FOLDERID_ProgramFilesX64 поддерживается...

MSDN говорит, что это поддерживается, но в документе Microsoft "WOW64" говорится, что это не так. См. http://download.microsoft.com/download/A/F/7/AF7777E5-7DCD-4800-8A0A-B18336565F5B/wow64_bestprac.docx

Цитировать:

• Некоторые переменные работают, только если процесс является 64-битным. Например, FOLDERID_ProgramFilesX64 не работает для 32-битных абонентов. В версиях Windows, предшествующих Windows 7, %ProgramW6432% не работал в контексте 32-разрядных процессов. Приложение должно определить, выполняется ли оно в 64-разрядном процессе, прежде чем использовать эти переменные.

В Windows 7 x64, при запуске 32-разрядного приложения в отладчике Visual Studio, я также получаю код возврата 0x80070002 (и указатель NULL). Выполнение того же кода, скомпилированного как 64-битный, возвращает значение S_OK и путь правильно заполнен.

Я использовал взлом реестра, как указано выше, так как я не могу найти другого обходного пути.

Другие вопросы по тегам