创建多个环境变量时引用不会被扩展

When creating multiple environment variables references are not being expanded

当使用 VBS 依次创建多个环境变量时,较早的变量在后面的变量中引用时永远不会展开。

Set wshUserEnv = objShell.Environment( "USER" )
wshUserEnv("A") = "a"
wshUserEnv("b") = "%A%\b"

然后,

objShell.ExpandEnvironmentStrings(GetEnvVariable("b"))

不给出 a\b 的值,而是保持为 %A%\b

此外,从命令行列出值会打印相同的值。但是,一旦从“系统属性”对话框编辑了变量(如添加分号这样的小编辑),变量就会被扩展。

GetEnvVariable 是一个辅助函数:

Function GetEnvVariable (EnvVariable)
    Dim wshUserEnv
    Set wshUserEnv = objShell.Environment( "USER" )
    GetEnvVariable=wshUserEnv(EnvVariable)
End Function

关于 .ExpandEnvironmentStrings() 行为:

运行下面第一个脚本:

Set objShell = CreateObject("WScript.Shell")

' set values to variables
objShell.Environment("user")("user___var") = "user___value"
objShell.Environment("process")("process___var") = "process___value"
objShell.Environment("system")("system___var") = "system___value"
objShell.Environment("volatile")("volatile___var") = "volatile___value"

s = "check accessibility within running script process" & vbCrLf
s = s & objShell.ExpandEnvironmentStrings("%user___var%") & vbCrLf
s = s & objShell.ExpandEnvironmentStrings("%process___var%") & vbCrLf
s = s & objShell.ExpandEnvironmentStrings("%system___var%") & vbCrLf
s = s & objShell.ExpandEnvironmentStrings("%volatile___var%") & vbCrLf
WScript.Echo(s)

objShell.Run "cmd.exe /k echo check accessibility within child process & echo %user___var% & echo %process___var% & echo %system___var% & echo %volatile___var%"

WScript.Echocmd.exe /k echo 的输出相同:

%user___var%
process___value
%system___var%
%volatile___var%

之后运行第二个脚本:

Set objShell = CreateObject("WScript.Shell")

s = "check accessibility via another script process" & vbCrLf
s = s & objShell.ExpandEnvironmentStrings("%user___var%") & vbCrLf
s = s & objShell.ExpandEnvironmentStrings("%process___var%") & vbCrLf
s = s & objShell.ExpandEnvironmentStrings("%system___var%") & vbCrLf
s = s & objShell.ExpandEnvironmentStrings("%volatile___var%") & vbCrLf
WScript.Echo(s)

objShell.Run "cmd.exe /k echo check accessibility via another script process & echo %user___var% & echo %process___var% & echo %system___var% & echo %volatile___var%"

输出将是:

user___value
%process___var%
system___value
volatile___value

我检查了 Win7 x64 和 VirtualBox WinXP 上的行为。如您所见,process 环境仅供 .ExpandEnvironmentStrings() 在 运行ning 进程内或通过第一个脚本显示的子进程访问。在 运行ning 脚本(其中设置了变量)完成之前,.ExpandEnvironmentStrings() 无法访问其他环境。当您 运行 第二个脚本时,您可以通过 .ExpandEnvironmentStrings() 读取所有环境变量,进程除外。

我希望这个解释能帮助你的代码工作。

你显示的代码 objShell.ExpandEnvironmentStrings(GetEnvVariable("b")) 给你 %A%\b 因为 GetEnvVariable("b") returns %A%\b (.Environment() 函数中实现的方法可以访问user 环境和所有其他环境,但它不处理包含 %A% 作为变量语句,如 .ExpandEnvironmentStrings() 那样),然后 .ExpandEnvironmentStrings("%A%\b") returns没有任何变化的值(该方法无法访问 user 环境中的 A 变量,直到脚本终止)。