I'm struggling with a problem of how to determine the location of the 64-bit Program Files directory on 64-bit Windows Vista from a 32-bit application.
我正在努力解决如何从32位应用程序确定64位Windows Vista上64位Program Files目录的位置的问题。
Calls to SHGetKnownFolderPath(FOLDERID_ProgramFilesX64)
do not return anything. The MSDN article KNOWNFOLDERID also states that this particular call with FOLDERID_ProgramFilesX64
is not supported for a 32-bit application.
调用SHGetKnownFolderPath(FOLDERID_ProgramFilesX64)不返回任何内容。 MSDN文章KNOWNFOLDERID还声明32位应用程序不支持使用FOLDERID_ProgramFilesX64进行此特定调用。
I would like to avoid as much as possible hardcoding the path to "C:\Program Files". Doing something like GetWindowsDirectory()
, extracting the drive from the return value and adding "\Program Files" to it is not appealing either.
我想尽可能避免硬编码“C:\ Program Files”的路径。执行类似GetWindowsDirectory()的操作,从返回值中提取驱动器并向其添加“\ Program Files”也不具吸引力。
How can a 32-bit application properly get the location of the folder from 64-bit Windows Vista?
32位应用程序如何从64位Windows Vista正确获取文件夹的位置?
Background
Our application has a service component which is supposed to launch other processes based on requests from user-session-specific component. The applications launched can be 32-bit or 64-bit. We do this is via CreateProcessAsUser()
by passing in a token from initiating user-session process. For call to CreateProcessAsUser
, we create an environment block via the CreateEnvironmentBlock()
API. The problem is that CreateEnvironmentBlock()
, using the token of the user-session application, creates a block with ProgramW6432="C:\Program Files (x86)", which is a problem for 64-bit applications. We need to override it with the proper value.
我们的应用程序有一个服务组件,它应该根据来自用户会话的组件的请求启动其他进程。启动的应用程序可以是32位或64位。我们通过从启动用户会话进程传入令牌来通过CreateProcessAsUser()执行此操作。为了调用CreateProcessAsUser,我们通过CreateEnvironmentBlock()API创建一个环境块。问题是CreateEnvironmentBlock()使用用户会话应用程序的标记创建一个ProgramW6432 =“C:\ Program Files(x86)”的块,这是64位应用程序的问题。我们需要用适当的值覆盖它。
4 个解决方案
#1
8
As you mentioned, using SHGetKnownFolderPath from a 32-bit application will not work on a 64-bit operating system. This is because Wow64 emulation is in effect.
如前所述,使用32位应用程序中的SHGetKnownFolderPath将无法在64位操作系统上运行。这是因为Wow64仿真生效。
You can however use RegOpenKeyEx passing in the flag KEY_WOW64_64KEY
and then read the program files directory from registry.
但是,您可以使用RegOpenKeyEx传入标志KEY_WOW64_64KEY,然后从注册表中读取程序文件目录。
The location in registry:
注册表中的位置:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
HKEY_LOCAL_MACHINE \ SOFTWARE \微软\的Windows \ CurrentVersion
You are interested in the string value:
您对字符串值感兴趣:
ProgramFilesDir
ProgramFilesDir的
#2
1
If you read that page carefully you will see that FOLDERID_ProgramFilesX64 is supported for 32 bits applications on a 64-bit OS. It's NOT supported on a 32-bit OS, which makes complete sense.
如果仔细阅读该页面,您将看到64位操作系统上的32位应用程序支持FOLDERID_ProgramFilesX64。它在32位操作系统上不受支持,这完全合理。
#3
0
FOLDERID_ProgramFilesX64 is supported...
支持FOLDERID_ProgramFilesX64 ...
MSDN says it is supported, but Microsoft's "WOW64" best practices document says it is not. See http://download.microsoft.com/download/A/F/7/AF7777E5-7DCD-4800-8A0A-B18336565F5B/wow64_bestprac.docx
MSDN表示支持它,但微软的“WOW64”最佳实践文档表明它不支持。请参阅http://download.microsoft.com/download/A/F/7/AF7777E5-7DCD-4800-8A0A-B18336565F5B/wow64_bestprac.docx
To quote:
去引用:
• Some variables work only if the process is 64-bit. For example, FOLDERID_ProgramFilesX64 does not work for 32-bit callers. In versions of Windows earlier than Windows 7, %ProgramW6432% did not work in the context of 32-bit processes. An application must determine whether it is running in a 64-bit process before it uses these variables.
•某些变量仅在进程为64位时有效。例如,FOLDERID_ProgramFilesX64不适用于32位调用者。在早于Windows 7的Windows版本中,%ProgramW6432%在32位进程的上下文中不起作用。应用程序必须在使用这些变量之前确定它是否在64位进程中运行。
Under Windows 7 x64, running a 32-bit app in the Visual Studio debugger, I also get a return code of 0x80070002 (and a NULL pointer). Running the same code compiled as 64-bit returns the value S_OK and the path is properly filled in.
在Windows 7 x64下,在Visual Studio调试器中运行32位应用程序,我还得到返回代码0x80070002(和一个NULL指针)。运行编译为64位的相同代码将返回值S_OK并正确填充路径。
I've used the registry hack as listed above since I can't find any other workaround.
我已经使用了上面列出的注册表黑客,因为我找不到任何其他解决方法。
#4
0
You can also query the environment variable ProgramW6432
. It obviously exists only in 64-bit Windows, but it should return the real 64-bit Program Files directory, and it seems to be defined for both 64-bit and 32-bit programs. At least it worked for me (C#, GetEnvironmentVariable
)...
您还可以查询环境变量ProgramW6432。它显然只存在于64位Windows中,但它应该返回真正的64位Program Files目录,它似乎是为64位和32位程序定义的。至少它对我有用(C#,GetEnvironmentVariable)......
#1
8
As you mentioned, using SHGetKnownFolderPath from a 32-bit application will not work on a 64-bit operating system. This is because Wow64 emulation is in effect.
如前所述,使用32位应用程序中的SHGetKnownFolderPath将无法在64位操作系统上运行。这是因为Wow64仿真生效。
You can however use RegOpenKeyEx passing in the flag KEY_WOW64_64KEY
and then read the program files directory from registry.
但是,您可以使用RegOpenKeyEx传入标志KEY_WOW64_64KEY,然后从注册表中读取程序文件目录。
The location in registry:
注册表中的位置:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion
HKEY_LOCAL_MACHINE \ SOFTWARE \微软\的Windows \ CurrentVersion
You are interested in the string value:
您对字符串值感兴趣:
ProgramFilesDir
ProgramFilesDir的
#2
1
If you read that page carefully you will see that FOLDERID_ProgramFilesX64 is supported for 32 bits applications on a 64-bit OS. It's NOT supported on a 32-bit OS, which makes complete sense.
如果仔细阅读该页面,您将看到64位操作系统上的32位应用程序支持FOLDERID_ProgramFilesX64。它在32位操作系统上不受支持,这完全合理。
#3
0
FOLDERID_ProgramFilesX64 is supported...
支持FOLDERID_ProgramFilesX64 ...
MSDN says it is supported, but Microsoft's "WOW64" best practices document says it is not. See http://download.microsoft.com/download/A/F/7/AF7777E5-7DCD-4800-8A0A-B18336565F5B/wow64_bestprac.docx
MSDN表示支持它,但微软的“WOW64”最佳实践文档表明它不支持。请参阅http://download.microsoft.com/download/A/F/7/AF7777E5-7DCD-4800-8A0A-B18336565F5B/wow64_bestprac.docx
To quote:
去引用:
• Some variables work only if the process is 64-bit. For example, FOLDERID_ProgramFilesX64 does not work for 32-bit callers. In versions of Windows earlier than Windows 7, %ProgramW6432% did not work in the context of 32-bit processes. An application must determine whether it is running in a 64-bit process before it uses these variables.
•某些变量仅在进程为64位时有效。例如,FOLDERID_ProgramFilesX64不适用于32位调用者。在早于Windows 7的Windows版本中,%ProgramW6432%在32位进程的上下文中不起作用。应用程序必须在使用这些变量之前确定它是否在64位进程中运行。
Under Windows 7 x64, running a 32-bit app in the Visual Studio debugger, I also get a return code of 0x80070002 (and a NULL pointer). Running the same code compiled as 64-bit returns the value S_OK and the path is properly filled in.
在Windows 7 x64下,在Visual Studio调试器中运行32位应用程序,我还得到返回代码0x80070002(和一个NULL指针)。运行编译为64位的相同代码将返回值S_OK并正确填充路径。
I've used the registry hack as listed above since I can't find any other workaround.
我已经使用了上面列出的注册表黑客,因为我找不到任何其他解决方法。
#4
0
You can also query the environment variable ProgramW6432
. It obviously exists only in 64-bit Windows, but it should return the real 64-bit Program Files directory, and it seems to be defined for both 64-bit and 32-bit programs. At least it worked for me (C#, GetEnvironmentVariable
)...
您还可以查询环境变量ProgramW6432。它显然只存在于64位Windows中,但它应该返回真正的64位Program Files目录,它似乎是为64位和32位程序定义的。至少它对我有用(C#,GetEnvironmentVariable)......