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

16

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

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

如有可能,我希望避免使用环境变量。

我想比较一些我从注册表读取的值,如果这些值指向我的应用程序的WOW版本或本机版本的路径,则执行某些操作,否则执行其他操作。为了确定我的应用程序的本机和WOW版本的预期位置,我需要获取“Program Files (x86)”和“Program Files”的路径。


你不应该依赖于程序“预期的位置”。应用程序应该放在用户想要的地方。小型固态硬盘正在变得越来越流行,它们将为许多个人电脑增加额外的安装位置。 - MSalters
完全正确,但在这种情况下,它确实将位于程序文件夹中。 - s d
对我来说,这是更新Chrome扩展列表的原因,可能在AppData、Program Files(x86)或Program Files中。(当然,Program Files的名称可能是其他内容。) - tofutim
6个回答

21

非常感谢这个帖子中提供的所有帮助和警告。不过,我确实需要这条路径,以下是我最终得到它的方式:

(为了清晰起见,已删除错误检查,使用需自负风险等)

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

谢谢!在特殊情况下,我需要这个确切的东西。 - david.healed

12
让我引用 Raymond Chen 在其优秀博客文章中对该问题的描述:
在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位注册表。

如果你仍然想这么做,我建议阅读此博客文章的评论,因为它们包含一些好的提示。


一个完全合法的获取32位程序中的64位ProgFiles的用例是当它尝试备份您的计算机但想忽略Program Files时。当然,您也希望忽略64位Program Files文件夹。 - Roman Plášil

4

2
这不是只有在Vista或更高版本才可用吗?如果代码在早期的Windows上调用它会发生什么? - paxdiablo
我刚遇到了这个问题,我需要它在XP和Server 2003 x64上也能正常工作。 - s d
2
SHGetKnownFolderPath与FOLDERID_ProgramFilesX64在32位Windows版本上无法正常工作。虽然它被记录为可以工作,但不幸的是,它实际上并不能正常工作。请参见此处的社区内容部分:http://msdn.microsoft.com/en-us/library/bb762584%28VS.85%29.aspx - Leo Davidson

1

根据臭名昭著的雷蒙德·陈最近的一篇帖子,这几乎肯定是个坏主意。详情请参见此处。总之,我认为它是可行的,但需要大量的努力,并且几乎肯定有更简单的方法。

微软构建了WOW仿真层来使您的生活更轻松。不要浪费他们所有的时间和精力去对抗它 :-)

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


1

我需要从登录脚本中获取x64程序文件夹,使用了以下代码:

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

WScript.Echo sProgramDirPath

-3

获取“Program Files”路径的最佳通用方法是从注册表中查询:

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)” HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir 选项为 KEY_WOW64_64KEY以获取“C:\Program Files”

伪代码:

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

4
你应该使用API函数来获取位置信息:SHGetFolderPath或ExpandEnvironmentStrings。 - BCran
1
如果 Windows 9 中的注册表键发生变化会怎样? - Roman Plášil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接