Как 32-разрядное приложение может найти местонахождение 64-разрядного каталога программных файлов в Windows Vista 64-бит?
-
21-09-2019 - |
Вопрос
Я борюсь с проблемой того, как определить местоположение 64-разрядного каталога программных файлов на 64-битной Windows Vista из 32-битного приложения.
Вызовы в SHGetKnownFolderPath(FOLDERID_ProgramFilesX64)
Не возвращай ничего. А MSDN статья Известно также заявляет, что этот конкретный звонок с 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-битных приложений. Нам нужно переопределить его с правильным значением.
Решение
Как вы упомянули, использование Shget KnowledFolderPath из 32-разрядного приложения не будет работать в 64-разрядной операционной системе. Это потому, что эмуляция WOW64 действует.
Вы можете использовать Regopenkeyex Переходя в флаге KEY_WOW64_64KEY
а затем прочитайте каталог программных файлов из реестра.
Место в реестре:
Hkey_local_machine Software Microsoft Windows CurrentVersion
Вы заинтересованы в значении строки:
Programfilesdir
Другие советы
Если вы внимательно прочитаете эту страницу, вы увидите, что FOLTERID_PROGRAMFILESX64 поддерживается для 32-битных приложений на 64-битной ОС. Это не поддерживается на 32-битной ОС, что имеет смысл.
FOLDERID_PROGRAMFILESX64 поддерживается ...
MSDN говорит, что это поддерживается, но документ Microsoft "WOW64" Best Practices говорится, что это не так. Видеть http://download.microsoft.com/download/a/f/7/af7777e5-7dcd-4800-8a0a-b18336565f5b/wow64_bestprac.docx
Цитировать:
• Некоторые переменные работают, только если процесс составляет 64-битный. Например, fotherid_programfilesx64 не работает для 32-разрядных вызывающих абонентов. В версиях Windows раньше, чем Windows 7, % ProgramW6432 % не работали в контексте 32-битных процессов. Приложение должно определить, работает ли он в 64-битном процессе, прежде чем использовать эти переменные.
Под Windows 7 X64, запустив 32-разрядное приложение в отладчике Visual Studio, я также получаю код возврата 0x80070002 (и нулевой указатель). Запуск того же кода, скомпилируемого как 64-битный, возвращает значение s_ok, и путь правильно заполнен.
Я использовал взлом реестра, как указано выше, так как я не могу найти другой обходной путь.
Вы также можете запросить переменную среды ProgramW6432
. Анкет Очевидно, что он существует только в 64-разрядных Windows, но он должен вернуть реальный 64-разрядный каталог программных файлов, и, похоже, определяется как для 64-битных, так и для 32-разрядных программ. По крайней мере, это сработало для меня (C#, GetEnvironmentVariable
)...