关于C#:如何从32位WOW进程中获取Program Files文件夹路径(而不是Program Files(x86))?

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

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

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

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

我想比较从注册表中读取的一些值,如果这些值指向我的应用程序的WOW或本机版本的路径,则我的代码执行某些操作,否则执行其他操作。
为了弄清楚应用程序的本机版本和WOW版本应该在哪里,我需要获取"程序文件(x86)"和"程序文件"的路径。


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

(为了清楚起见,已删除了错误检查,使用后果自负,等等)

1
2
3
4
WCHAR szNativeProgramFilesFolder[MAX_PATH];
ExpandEnvironmentStrings(L"%ProgramW6432%",
                       szNativeProgramFilesFolder,
                       ARRAYSIZE(szNativeProgramFilesFolder);


让我引用有关该问题的雷蒙德·陈(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.

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


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

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


我需要它来从登录脚本中获取x64程序文件夹并使用:

1
2
3
4
5
Dim oWshShell : Set oWshShell = CreateObject("WScript.Shell")
Dim sProgramDirPath : sProgramDirPath =
    oWshShell.ExpandEnvironmentStrings("%ProgramW6432%")

WScript.Echo sProgramDirPath

根据臭名昭著的雷蒙德·陈(Raymond Chen)最近发表的一篇帖子,这几乎肯定是个坏主意。有关详细信息,请参见此处。最重要的是,我认为这是可以做到的,但是这是很多艰苦的工作,而且几乎肯定有一种更简单的方法。

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

也许如果您告诉我们为什么需要非WOW程序文件目录,我们将为您提供进一步的帮助。


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

64位进程可以查询:
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位进程(Wow64)可以查询:
HKEY_LOCAL_MACHINE \\\\ SOFTWARE \\\\ Microsoft \\\\ Windows \\\\ CurrentVersion \\\\ ProgramFilesDir
获得" C:\\\\ Program Files(x86)"
带有KEY_WOW64_64KEY选项的HKEY_LOCAL_MACHINE \\\\ SOFTWARE \\\\ Microsoft \\\\ Windows \\\\ CurrentVersion \\\\ ProgramFilesDir!
获取" C:\\\\ Program Files"

伪代码:

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