如何从32位WOW进程获取Program Files文件夹路径(不是Program Files(x86))?

时间:2020-11-29 16:03:15

I need to get the path to the native (rather than the WOW) program files directory from a 32bit WOW process.

我需要从32位WOW进程获取本机(而不是WOW)程序文件目录的路径。

When I pass CSIDL_PROGRAM_FILES (or CSIDL_PROGRAM_FILESX86) into SHGetSpecialFolderPath it returns the WOW (Program Files (x86)) folder path.

当我将CSIDL_PROGRAM_FILES(或CSIDL_PROGRAM_FILESX86)传递给SHGetSpecialFolderPath时,它返回WOW(Program Files(x86))文件夹路径。

I'd prefer to avoid using an environment variable if possible.

如果可能的话,我宁愿避免使用环境变量。

I want to compare some values I read from the registry, if the values point to the path of either the WOW or native version of my app then my code does something, if not it does something else. To figure out where the native and WOW versions of my app are expected to be I need to get the paths to "Program Files (x86)" and "Program Files".

我想比较一下我从注册表中读取的一些值,如果值指向我的应用程序的WOW或本机版本的路径,那么我的代码会执行某些操作,否则它会执行其他操作。要弄清楚应用程序的原生和WOW版本应该在哪里,我需要获得“Program Files(x86)”和“Program Files”的路径。

6 个解决方案

#1


I appreciate all the help and, especially, the warnings in this thread. However, I really do need this path and this is how I got it in the end:

我感谢所有的帮助,尤其是这个帖子中的警告。但是,我确实需要这条路径,这就是我最终得到它的方式:

(error checking removed for clarity, use at your own risk, etc)

(为清楚起见,删除了错误检查,使用风险等)

WCHAR szNativeProgramFilesFolder[MAX_PATH];
ExpandEnvironmentStrings(L"%ProgramW6432%", 
                       szNativeProgramFilesFolder, 
                       ARRAYSIZE(szNativeProgramFilesFolder);

#2


Let me quote Raymond Chen's excellent blogpost on the issue:

让我引用Raymond Chen关于这个问题的优秀博文:

On 64-bit Windows, 32-bit programs run in an emulation layer. This emulation layer simulates the x86 architecture, virtualizing the CPU, the file system, the registry, the environment variables, the system information functions, all that stuff. If a 32-bit program tries to look at the system, it will see a 32-bit system. For example, if the program calls the GetSystemInfo function to see what processor is running, it will be told that it's running on a 32-bit processor, with a 32-bit address space, in a world with a 32-bit sky and 32-bit birds in the 32-bit trees.

在64位Windows上,32位程序在仿真层中运行。此仿真层模拟x86体系结构,虚拟化CPU,文件系统,注册表,环境变量,系统信息功能,以及所有这些功能。如果32位程序试图查看系统,它将看到一个32位系统。例如,如果程序调用GetSystemInfo函数来查看正在运行的处理器,它将被告知它运行在具有32位地址空间的32位处理器上,在具有32位天空和32位的世界中32位树中的鸟类。

And that's the point of the emulation: To keep the 32-bit program happy by simulating a 32-bit execution environment.

这就是仿真的重点:通过模拟32位执行环境来保持32位程序的快乐。

...

The question is "What is the way of finding the x64 Program Files directory from a 32-bit application?"

问题是“从32位应用程序中查找x64 Program Files目录的方法是什么?”

The answer is "It is better to work with the system than against it." If you're a 32-bit program, then you're going to be fighting against the emulator each time you try to interact with the outside world. Instead, just recompile your installer as a 64-bit program. Have the 32-bit installer detect that it's running on a 64-bit system and launch the 64-bit installer instead. The 64-bit installer will not run in the 32-bit emulation layer, so when it tries to copy a file or update a registry key, it will see the real 64-bit file system and the real 64-bit registry.

答案是“与系统合作比使用系统更好。”如果你是一个32位程序,那么每次你尝试与外界交互时,你都会与模拟器作斗争。相反,只需将安装程序重新编译为64位程序即可。让32位安装程序检测到它在64位系统上运行并启动64位安装程序。 64位安装程序不会在32位仿真层中运行,因此当它尝试复制文件或更新注册表项时,它将看到真正的64位文件系统和真正的64位注册表。

If you still want to do this, I recommend reading the comments on this blogpost as they contain some good hints.

如果你仍然想这样做,我建议阅读这篇博文中的评论,因为它们包含一些很好的提示。

#3


You're on the right path - Use the KNOWNFOLDERID of FOLDERID_ProgramFilesX64

你在正确的道路上 - 使用FOLDERID_ProgramFilesX64的KNOWNFOLDERID

The SHGetKnownFolderPath function can be used to retrieve the full path of a given KnownFolder.

SHGetKnownFolderPath函数可用于检索给定KnownFolder的完整路径。

#4


This is almost certainly a bad idea, according to a recent-ish post by the infamous Raymond Chen. See here for details. Bottom line, I think it can be done, but it's a lot of hard work and there's almost certainly an easier way.

据臭名昭着的雷蒙德·陈(Raymond Chen)最近发布的帖子显示,这几乎肯定是一个坏主意。详情请见此处。最重要的是,我认为可以做到,但这是一项艰苦的工作,几乎可以肯定是一种更简单的方法。

Microsoft built the WOW emulation layer to make your life easier. Don't waste all their time and effort by fighting it :-).

Microsoft构建了WOW仿真层,让您的生活更轻松。不要浪费所有的时间和精力来打击它:-)。

Perhaps if you told us why you need the non-WOW Program Files directory, we could assist further.

也许如果你告诉我们为什么你需要非WOW Program Files目录,我们可以进一步提供帮助。

#5


I needed it to get the x64 Program Folder from a Logonscript and used:

我需要它从Logonscript获取x64程序文件夹并使用:

Dim oWshShell : Set oWshShell = CreateObject("WScript.Shell")
Dim sProgramDirPath : sProgramDirPath = 
    oWshShell.ExpandEnvironmentStrings("%ProgramW6432%")

WScript.Echo sProgramDirPath

#6


The best and universal way to get path to "Program Files", is to query it from the registry:

获取“程序文件”路径的最佳和通用方法是从注册表中查询它:

64-Bit-Process can query: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir to get "C:\Program Files" HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\ProgramFilesDir to get "C:\Program Files (x86)"

64位进程可以查询:HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ ProgramFilesDir获取“C:\ Program Files”HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ ProgramFilesDir获取“C:\ Program Files( 86)”

32-Bit-Process (Wow64) can query: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir to get "C:\Program Files (x86)" HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir with KEY_WOW64_64KEY option! to get "C:\Program Files"

32位进程(Wow64)可以查询:HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ ProgramFilesDir以获取“C:\ Program Files(x86)”HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ ProgramFilesDir以及KEY_WOW64_64KEY选项!得到“C:\ Program Files”

Pseudo-code:

OpenKey(hKey, HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", KEY_READ | KEY_WOW64_64KEY);
QueryStringValue(hKey, L"ProgramFilesDir", sValue);

#1


I appreciate all the help and, especially, the warnings in this thread. However, I really do need this path and this is how I got it in the end:

我感谢所有的帮助,尤其是这个帖子中的警告。但是,我确实需要这条路径,这就是我最终得到它的方式:

(error checking removed for clarity, use at your own risk, etc)

(为清楚起见,删除了错误检查,使用风险等)

WCHAR szNativeProgramFilesFolder[MAX_PATH];
ExpandEnvironmentStrings(L"%ProgramW6432%", 
                       szNativeProgramFilesFolder, 
                       ARRAYSIZE(szNativeProgramFilesFolder);

#2


Let me quote Raymond Chen's excellent blogpost on the issue:

让我引用Raymond Chen关于这个问题的优秀博文:

On 64-bit Windows, 32-bit programs run in an emulation layer. This emulation layer simulates the x86 architecture, virtualizing the CPU, the file system, the registry, the environment variables, the system information functions, all that stuff. If a 32-bit program tries to look at the system, it will see a 32-bit system. For example, if the program calls the GetSystemInfo function to see what processor is running, it will be told that it's running on a 32-bit processor, with a 32-bit address space, in a world with a 32-bit sky and 32-bit birds in the 32-bit trees.

在64位Windows上,32位程序在仿真层中运行。此仿真层模拟x86体系结构,虚拟化CPU,文件系统,注册表,环境变量,系统信息功能,以及所有这些功能。如果32位程序试图查看系统,它将看到一个32位系统。例如,如果程序调用GetSystemInfo函数来查看正在运行的处理器,它将被告知它运行在具有32位地址空间的32位处理器上,在具有32位天空和32位的世界中32位树中的鸟类。

And that's the point of the emulation: To keep the 32-bit program happy by simulating a 32-bit execution environment.

这就是仿真的重点:通过模拟32位执行环境来保持32位程序的快乐。

...

The question is "What is the way of finding the x64 Program Files directory from a 32-bit application?"

问题是“从32位应用程序中查找x64 Program Files目录的方法是什么?”

The answer is "It is better to work with the system than against it." If you're a 32-bit program, then you're going to be fighting against the emulator each time you try to interact with the outside world. Instead, just recompile your installer as a 64-bit program. Have the 32-bit installer detect that it's running on a 64-bit system and launch the 64-bit installer instead. The 64-bit installer will not run in the 32-bit emulation layer, so when it tries to copy a file or update a registry key, it will see the real 64-bit file system and the real 64-bit registry.

答案是“与系统合作比使用系统更好。”如果你是一个32位程序,那么每次你尝试与外界交互时,你都会与模拟器作斗争。相反,只需将安装程序重新编译为64位程序即可。让32位安装程序检测到它在64位系统上运行并启动64位安装程序。 64位安装程序不会在32位仿真层中运行,因此当它尝试复制文件或更新注册表项时,它将看到真正的64位文件系统和真正的64位注册表。

If you still want to do this, I recommend reading the comments on this blogpost as they contain some good hints.

如果你仍然想这样做,我建议阅读这篇博文中的评论,因为它们包含一些很好的提示。

#3


You're on the right path - Use the KNOWNFOLDERID of FOLDERID_ProgramFilesX64

你在正确的道路上 - 使用FOLDERID_ProgramFilesX64的KNOWNFOLDERID

The SHGetKnownFolderPath function can be used to retrieve the full path of a given KnownFolder.

SHGetKnownFolderPath函数可用于检索给定KnownFolder的完整路径。

#4


This is almost certainly a bad idea, according to a recent-ish post by the infamous Raymond Chen. See here for details. Bottom line, I think it can be done, but it's a lot of hard work and there's almost certainly an easier way.

据臭名昭着的雷蒙德·陈(Raymond Chen)最近发布的帖子显示,这几乎肯定是一个坏主意。详情请见此处。最重要的是,我认为可以做到,但这是一项艰苦的工作,几乎可以肯定是一种更简单的方法。

Microsoft built the WOW emulation layer to make your life easier. Don't waste all their time and effort by fighting it :-).

Microsoft构建了WOW仿真层,让您的生活更轻松。不要浪费所有的时间和精力来打击它:-)。

Perhaps if you told us why you need the non-WOW Program Files directory, we could assist further.

也许如果你告诉我们为什么你需要非WOW Program Files目录,我们可以进一步提供帮助。

#5


I needed it to get the x64 Program Folder from a Logonscript and used:

我需要它从Logonscript获取x64程序文件夹并使用:

Dim oWshShell : Set oWshShell = CreateObject("WScript.Shell")
Dim sProgramDirPath : sProgramDirPath = 
    oWshShell.ExpandEnvironmentStrings("%ProgramW6432%")

WScript.Echo sProgramDirPath

#6


The best and universal way to get path to "Program Files", is to query it from the registry:

获取“程序文件”路径的最佳和通用方法是从注册表中查询它:

64-Bit-Process can query: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir to get "C:\Program Files" HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\ProgramFilesDir to get "C:\Program Files (x86)"

64位进程可以查询:HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ ProgramFilesDir获取“C:\ Program Files”HKEY_LOCAL_MACHINE \ SOFTWARE \ Wow6432Node \ Microsoft \ Windows \ CurrentVersion \ ProgramFilesDir获取“C:\ Program Files( 86)”

32-Bit-Process (Wow64) can query: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir to get "C:\Program Files (x86)" HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir with KEY_WOW64_64KEY option! to get "C:\Program Files"

32位进程(Wow64)可以查询:HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ ProgramFilesDir以获取“C:\ Program Files(x86)”HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ ProgramFilesDir以及KEY_WOW64_64KEY选项!得到“C:\ Program Files”

Pseudo-code:

OpenKey(hKey, HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", KEY_READ | KEY_WOW64_64KEY);
QueryStringValue(hKey, L"ProgramFilesDir", sValue);