ProgramFiles、ProgramW6432Dir、ProgramFilesDir (x86)、CommonProgramFiles 环境变量的数据来源是什么?

What is the source of the data for the ProgramFiles, ProgramW6432Dir, ProgramFilesDir (x86), CommonProgramFiles environment variables?

环境变量 ProgramFilesProgramW6432DirProgramFilesDir (x86)CommonProgramFilesProgramData 从哪里获取数据?

为什么无法使用 _putenv() 更改这些环境变量的值? 例如:

_putenv( "ProgramFiles=D:\MyProgs" );

在64位Windows系统上,各种环境变量和一些Windows注册表项的读取是redirected到不同的来源,取决于进行读取的进程是 64 位还是 32 位。

下面的 table 列出了这些数据源:

X = HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion
Y = HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion
Z = HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
     
READING ENVIRONMENT VARIABLES:    Source for 64-bit process               Source for 32-bit process
-------------------------------|----------------------------------------|--------------------------------------------------------------
                %ProgramFiles% :  X\ProgramW6432Dir                       X\ProgramFilesDir (x86)
           %ProgramFiles(x86)% :  X\ProgramFilesDir (x86)                 X\ProgramFilesDir (x86)
                %ProgramW6432% :  X\ProgramW6432Dir                       X\ProgramW6432Dir
     
          %CommonProgramFiles% :  X\CommonW6432Dir                        X\CommonFilesDir (x86)
     %CommonProgramFiles(x86)% :  X\CommonFilesDir (x86)                  X\CommonFilesDir (x86)
          %CommonProgramW6432% :  X\CommonW6432Dir                        X\CommonW6432Dir
     
                 %ProgramData% :  Z\ProgramData                           Z\ProgramData


      READING REGISTRY VALUES:    Source for 64-bit process               Source for 32-bit process
-------------------------------|----------------------------------------|--------------------------------------------------------------
             X\ProgramFilesDir :  X\ProgramFilesDir                       Y\ProgramFilesDir
       X\ProgramFilesDir (x86) :  X\ProgramFilesDir (x86)                 Y\ProgramFilesDir (x86)
            X\ProgramFilesPath :  X\ProgramFilesPath = %ProgramFiles%     Y\ProgramFilesPath = %ProgramFiles(x86)%
             X\ProgramW6432Dir :  X\ProgramW6432Dir                       Y\ProgramW6432Dir
     
              X\CommonFilesDir :  X\CommonFilesDir                        Y\CommonFilesDir
        X\CommonFilesDir (x86) :  X\CommonFilesDir (x86)                  Y\CommonFilesDir (x86)
              X\CommonW6432Dir :  X\CommonW6432Dir                        Y\CommonW6432Dir
     

例如,对于 32 位进程,%ProgramFiles%%ProgramFiles(x86)% 环境变量的数据源是注册表值 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir (x86).

但是,对于 64 位进程,%ProgramFiles% 环境变量的数据源是注册表值 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramW6432Dir ...以及 %ProgramFiles(x86)%环境变量是注册表值HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir (x86)

大多数默认 Windows 安装将 C:\Program Files (x86) 之类的字符串放入注册表值 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesDir (x86) 中,但这可以更改(以及其他设置)。

以下是这些环境变量和注册表值中的典型数据:

 READING ENVIRONMENT VARIABLES:   Typical data for 64-bit process         Typical data for 32-bit process
-------------------------------|----------------------------------------|-----------------------------------------------                                                                        
                %ProgramFiles% = C:\Program Files                        C:\Program Files (x86)
           %ProgramFiles(x86)% = C:\Program Files (x86)                  C:\Program Files (x86) 
                %ProgramW6432% = C:\Program Files                        C:\Program Files

          %CommonProgramFiles% = C:\Program Files\Common Files           C:\Program Files (x86)\Common Files
     %CommonProgramFiles(x86)% = C:\Program Files (x86)\Common Files     C:\Program Files (x86)\Common Files
          %CommonProgramW6432% = C:\Program Files\Common Files           C:\Program Files\Common Files

                 %ProgramData% = C:\ProgramData                          C:\ProgramData
 
 
       READING REGISTRY VALUES:  Typical data for 64-bit process         Typical data for 32-bit process
 ------------------------------|----------------------------------------|-----------------------------------------------
             X\ProgramFilesDir = C:\Program Files                        C:\Program Files (x86)
       X\ProgramFilesDir (x86) = C:\Program Files (x86)                  C:\Program Files (x86)
            X\ProgramFilesPath = %ProgramFiles% => C:\Program Files      %ProgramFiles(x86)% => C:\Program Files (x86)
             X\ProgramW6432Dir = C:\Program Files                        C:\Program Files

              X\CommonFilesDir = C:\Program Files\Common Files           C:\Program Files (x86)\Common Files
        X\CommonFilesDir (x86) = C:\Program Files (x86)\Common Files     C:\Program Files (x86)\Common Files
              X\CommonW6432Dir = C:\Program Files\Common Files           C:\Program Files\Common Files
 
 X = HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion

最终,Windows 注册表值中输入的任何内容都将在登录时被 Windows Explorer 读取到相应的环境变量中,然后复制到它随后生成的任何子进程。子进程可以使用 _putenv()

更改自己的环境变量

注册表值 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramFilesPath 特别值得注意,因为大多数 Windows 安装将字符串 %ProgramFiles% 放入其中,以供 64 位进程读取。此字符串引用环境变量 %ProgramFiles%,后者又从注册表值 HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\ProgramW6432Dir 中获取数据 ...除非某些程序先验更改此环境变量的值。

我编写了一个小实用程序,它显示 64 位和 32 位进程的这些环境变量。可以下载here.
包含 VisualStudio 2017 的源代码,编译后的 64 位和 32 位二进制 executables 分别位于目录 ..\x64\Release..\x86\Release 中。