前言:为何写这篇文章,因为前段时间的工作中遇到一个很奇特的需求:运行32bits的程序在x64的Windows上,在程序中
获取为获取%programfiles%的值,先后使用 SHGetSpecialFolderLocation、SHGetPathFromIDList、
SHGetSpecialFolderPath等API获取结果依然是"C:\Program Files (x86)",而非我们所期望的"C:\Program Files ",
最终是通过GetEnvironmentVariable这个API来解决。
1, 常见变量
环境变量与对应的路径:
%ALLUSERSPROFILE% C:\ProgramData %APPDATA% C:\Users\用户名\AppData\Roaming %COMMONPROGRAMFILES% C:\Program Files\Common Files %COMMONPROGRAMFILES(x86)% C:\Program Files (x86)\Common Files %COMSPEC% C:\Windows\System32\cmd.exe %HOMEDRIVE%和%SystemDrive% C:\ %HOMEPATH% C:\Users\用户名 %LOCALAPPDATA% C:\Users\用户名\AppData\Local %PROGRAMDATA% C:\ProgramData %PROGRAMFILES% C:\Program Files %PROGRAMFILES(X86)% C:\Program Files (x86) %PUBLIC% C:\UsersPublic %SystemRoot% C:\Windows %TEMP%和%TMP% C:\Users\用户名\AppData\LocalTemp %USERPROFILE% C:\Users用户名 %WINDIR% C:\Window
2, 通过 SHGetSpecialFolderLocation、SHGetPathFromIDList 函数获取常用路径
int CSIDL[] = { CSIDL_ADMINTOOLS, CSIDL_APPDATA, CSIDL_CDBURN_AREA, CSIDL_COMMON_ADMINTOOLS, CSIDL_COMMON_APPDATA, CSIDL_COMMON_DESKTOPDIRECTORY, CSIDL_COMMON_DOCUMENTS, CSIDL_COMMON_FAVORITES, CSIDL_COMMON_MUSIC, CSIDL_COMMON_PICTURES, CSIDL_COMMON_PROGRAMS, CSIDL_COMMON_STARTMENU, CSIDL_COMMON_STARTUP, CSIDL_COMMON_TEMPLATES, CSIDL_COMMON_VIDEO, CSIDL_COOKIES, CSIDL_FAVORITES, CSIDL_HISTORY, CSIDL_INTERNET_CACHE, CSIDL_LOCAL_APPDATA, CSIDL_MYDOCUMENTS, CSIDL_MYMUSIC, CSIDL_MYPICTURES, CSIDL_MYVIDEO, CSIDL_PROFILE, CSIDL_PROGRAM_FILES, CSIDL_PROGRAM_FILES_COMMON, CSIDL_PROGRAMS, CSIDL_RECENT, CSIDL_SENDTO, CSIDL_STARTMENU, CSIDL_STARTUP, CSIDL_SYSTEM, CSIDL_TEMPLATES, CSIDL_WINDOWS, 0 }; SHGetFolderPath(NULL, CSIDL[i], NULL, SHGFP_TYPE_CURRENT, szPath)
warning:
but mostly if a 32bits application use this API SHGetFolderPath to get the ' CSIDL_PROGRAM_FILES', the result is "C:\Program Files (x86)" not "C:\Program Files".
WINSHELLAPI HRESULT WINAPI SHGetSpecialFolderLocation( HWND hwndOwner, int nFolder, LPITEMIDLIST* ppidl ); BOOL SHGetSpecialFolderPath ( HWND hwndOwner, LPTSTR lpszPath, int nFolder, BOOL fCreate );
use the API SHGetSpecialFolderLocation by a 32bits application will get the "C:\Program Files (x86)" too.
3, howto get the x64 %programfiles% by a 32-bits application on x64 Windows
use below API:
DWORD WINAPI GetEnvironmentVariable( _In_opt_ LPCTSTR lpName, _Out_opt_ LPTSTR lpBuffer, _In_ DWORD nSize );
WINDIR: //系统目录 - C:\WINDOWS SYSTEMROOT: //系统目录 - C:\WINDOWS SYSTEMDRIVE: //系统根目录 - C: HOMEDRIVE: //当前用户根目录 - C: USERPROFILE: //当前用户目录 - C:\Users\Kandy HOMEPATH: //当前用户路径 - \Users\Kandy TMP: //当前用户临时文件夹 - C:\Users\Kandy\AppData\Local\Temp TEMP: //当前用户临时文件夹 - C:\Users\Kandy\AppData\Local\Temp APPDATA: //当前用户数据文件夹 - C:\Users\Kandy\AppData\Roaming PROGRAMFILES: //程序默认安装目录 - C:\Program Files (x86) COMMONPROGRAMFILES: //文件通用目录 - C:\Program Files (x86)\Common Files USERNAME: //当前用户名 - Kandy ALLUSERSPROFILE: //所有用户文件目录 - C:\ProgramData OS: //操作系统名 - Windows_NT COMPUTERNAME: //计算机名 - KANDY-PC NUMBER_OF_PROCESSORS: //处理器个数 - 4 PROCESSOR_ARCHITECTURE: //处理器芯片架构 - x86 PROCESSOR_LEVEL: //处理器型号 - 6 PROCESSOR_REVISION: //处理器修订号 - 3c03 USERDOMAIN: //包含用户帐号的域 - KANDY-PC COMSPEC: //C:\WINDOWS\system32\cmd.exe PATHEXT: //执行文件类型 - .COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC PATH: //搜索路径
eg.
GetEnvironmentVariable(L"PROGRAMFILES", buffer, MAX_PATH); std::wcout << L"PROGRAMFILES:\t\t" << buffer << std::endl;but the output still be "C:\Program Files (x86)" on a x64 Windows, what's wrong?
here we should use the arg "PROGRAMFILESW6432" to get "C:\Program Files"
on *, https://*.com/questions/2539724/wow64-get-x64-commonprogramfiles-from-32-bit-process
someone said like below:
ProgramFiles => c:\program files (x86) ProgramFiles(x86) => c:\program files (x86) ProgramW6432 => c:\program files CommonProgramFiles => c:\program files (x86)\common files CommonProgramFiles(x86) => c:\program files (x86)\common files CommonProgramW6432 => c:\program files\common files