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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/445139/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 15:23:10  来源:igfitidea点击:

How to get Program Files folder path (not Program Files (x86)) from 32bit WOW process?

c++windows64-bit

提问by s d

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(程序文件(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”的路径。

回答by s d

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);

回答by Tamas Czinege

Let me quote Raymond Chen's excellent blogposton 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.

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

...

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

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.

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

这就是模拟的重点:通过模拟 32 位执行环境来保持 32 位程序满意。

...

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

答案是“与系统一起工作比对抗它更好。”如果你是一个 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.

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

回答by Bevan

You're on the right path - Use the KNOWNFOLDERIDof FOLDERID_ProgramFilesX64

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

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

SHGetKnownFolderPath功能可用于检索给定KnownFolder的完整路径。

回答by paxdiablo

This is almost certainly a bad idea, according to a recent-ish post by the infamous Raymond Chen. See herefor 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 whyyou need the non-WOW Program Files directory, we could assist further.

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

回答by Peter

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

回答by Stanislav Povolotsky

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\ProgramFilesDirto get "C:\Program Files"HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\ProgramFilesDirto get "C:\Program Files (x86)"

64-Bit-Process 可以查询: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir得到“C:\Program Files” HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\ProgramFilesDir得到“C:\Program Files ( x86)"

32-Bit-Process (Wow64) can query: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDirto get "C:\Program Files (x86)"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDirwith KEY_WOW64_64KEYoption! to get "C:\Program Files"

32-Bit-Process (Wow64) 可以查询: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir得到“C:\Program Files (x86)” HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDirKEY_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);