如何获取Windows环境变量

时间:2022-12-12 23:38:42


前言:为何写这篇文章,因为前段时间的工作中遇到一个很奇特的需求:运行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