当前位置: 首页 > 知识库问答 >
问题:

为什么我无法在Windows 7上访问名为__CD__的变量?

谭翔
2023-03-14

注意——这个问题基于在Windows 7上观察到的行为。我相信这种行为适用于Vista以后的所有其他版本。根据MC ND的回答和Foxidrive的评论,它不适用于XP。

有人知道这个%\uuuuu CD\uuuu%机制是如何工作的吗(为什么它不同于任何其他动态变量)?

有人能想出一种方法来访问我的__CD__变量,只使用标准批处理命令(不解析set__CD__的输出)?

这更像是一个学术问题,而不是一个实践问题。任何人都不应该用与动态变量匹配的名称来定义变量。

我不想要一个解析set\uuuu CD\uuuu结果的例程的原因是,值中可以有换行符。有人可以定义两个变量,\uuuuuuCD\uuu\uuCD\uuu2,或者他们可以定义一个\uuuCD\uu值,该值包含一个换行符,后跟\uuCD\uu2= 。要区分这两种情况是不可能的。(正如我所说,这是一个学术问题,而不是一个实践问题!)


共有3个答案

刁瀚昂
2023-03-14

我看不出用户定义的__cd__与用户定义的cd变量不同的原因。
但是我做了一些测试。

setlocal EnableDelayedExpansion
echo #0 %__cd__%
if defined __cd__ echo #1 It's defined
set __cd__=1234
echo #2 %__cd__%
echo #3 !__cd__!
call echo #4 %%__cd__%%
echo #5 %__cd__:x=y%
echo #6 !__cd__:x=y!
if defined __cd__ echo #7 It's defined
set __cd__
set /a result=__cd__
echo #7 %result%

所以有三个有趣的点。

  1. 如果定义了测试总是阳性的
袁奇逸
2023-03-14

“这应该是一个评论,但会是一个很大的评论!”

@echo off

echo Original: %CD%
setlocal
md newdir
cd newdir
echo In newdir: %CD%
endlocal
echo After endlocal: %CD%
祁远
2023-03-14

我有一个理论,可以解释\uuuucd\uuuu的行为如何以及为什么与其他任何伪环境变量的行为如此不同。

我写了一个简单的ENV。用于探测流程环境的JS脚本。

var env=WScript.CreateObject("WScript.Shell").Environment("Process");
WScript.echo(env(WScript.Arguments.Item(0)));

ENV. JS期望环境变量名称作为唯一的参数,并简单地打印变量的值。我在Windows 7机器上进行了测试。该脚本可以从CMD. EXE控制台中运行,也可以直接通过定义参数的快捷方式运行。

我将对各种动态变量进行分类,显示对比的行为,以及关于它们工作机制的理论。

有许多动态变量可以分为三类:

1) 没有任何前缀或后缀的普通“变量”

CD              current directory
DATE            current date
TIME            current time
ERRORLEVEL      current errorlevel
RANDOM          random integer between 0 and 32767
CMDEXTVERSION   current extension level (only available if extensions are enabled)
CMDCMDLINE      the command line that invoked the current CMD.EXE level

动态值只能通过CMD中的扩展来获得。EXE,并且仅当命令扩展被启用时。它们无法通过SET或ENV获得。JS。可以通过使用SET显式定义静态值来覆盖动态值。覆盖值可通过SET和ENV获得。JS。

C:\test>echo %cmdcmdline%
"C:\Windows\system32\cmd.exe"

C:\test>set cmdcmdline
Environment variable cmdcmdline not defined

C:\test>cscript //nologo env.js cmdcmdline
cmdcmdline=

C:\test>set cmdcmdline=override

C:\test>echo %cmdcmdline%
override

C:\test>set cmdcmdline
cmdcmdline=override

C:\test>cscript //nologo env.js cmdcmdline
cmdcmdline=override

C:\test>cmd /e:off
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\test>echo %cmdcmdline%
%cmdcmdline%

动态值实际上根本不是环境变量,这就是为什么SET命令或ENV无法访问它们的原因。JS。CMD中的变量扩展代码。EXE首先检查流程环境变量中的变量,只有在未找到时,才会将名称与特殊动态名称列表进行比较。特别指令。每个动态“变量”必须存在EXE代码,才能从相应的源中导出值。

微软的Raymond Chen在他的博客The Old New Thing中描述了这类动态变量的行为

2) 以=

=ExitCode
=ExitCodeAscii
=C:
=D:
...
=Z:

这些动态值中的每一个在执行定义它的命令之前都是未定义的。例如,一个全新的CMD. EXE控制台会话以=ExitCode未定义开头。一旦执行设置返回代码的外部命令,它就会被定义。

有一个例外是,与当前目录相对应的={driveLetter}:变量将始终被定义,即使在CMD时也是如此。EXE首先启动。

不可能使用SET来定义这些变量中的任何一个,因为SET不允许=在变量名中。但是底层流程环境变量空间确实允许=在变量名中。它必须在CMD. EXE上下文之外完成。

我写了一个附加测试。JS帮助测试这些变量:

var shell=WScript.CreateObject("WScript.Shell");
var env=shell.Environment("Process");
WScript.echo('Within JScript: ExitCode='+env("=ExitCode"));
env("=ExitCode") = "override";
WScript.echo('Within JScript after override: ExitCode='+env("=ExitCode"));
WScript.echo('Within JScript test.bat return code = '+shell.run("cmd /c test.bat",10,1));
WScript.echo('Within JScript after test.bat: ExitCode='+env("=ExitCode"));

反过来,测试。JS调用TEST。蝙蝠:

@echo off
echo Within test.bat: ExitCode=%=ExitCode%
cmd /c exit 10
echo =Within test.bat: ExitCode=%=ExitCode%
pause
exit %errorlevel%

以下是使用=ExitCode的一些测试结果,从全新的CMD. EXE会话开始:

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\test>echo %=ExitCode%
%=ExitCode%

C:\test>set "=ExitCode=override"
The syntax of the command is incorrect.

C:\test>cscript //nologo env.js =ExitCode
=ExitCode=

C:\test>REM cscript is an external command that set the value!

C:\test>echo %=ExitCode%
00000000

C:\test>set =
The syntax of the command is incorrect.

C:\test>set ""|findstr /b =ExitCode
=ExitCode=00000000

C:\test>cscript //nologo env.js =ExitCode
=ExitCode=00000000

C:\test>cscript //nologo test.js
Within JScript: ExitCode=00000000
Within JScript after override: ExitCode=override
Within JScript test.bat return code = 10
Within JScript after test.bat: ExitCode=override

C:\test>

以下是Test. JS在新窗口中启动的Test. BAT的结果:

Within test.bat: ExitCode=override
Within test.bat: ExitCode=0000000A
Press any key to continue . . .

我相信这些动态变量是真正的环境变量,这就是为什么SET和JScript都可以访问它们。(SET只能使用特殊的SET”“语法访问该值。)这些变量由CMD动态定义(或更新)。每次执行relavent命令时。环境。JS和测试。JS可以看到调用CMD设置的值。EXE会话。测试。BAT cmd会话可以看到该测试继承的覆盖值。JS集。但JScript在测试后继续获得覆盖值。蝙蝠因为CMD而退出。EXE无法使用返回代码更新值。

无论是启用还是禁用命令扩展,此类动态变量都可用。即使禁用扩展,动态值也会保持不变,如下所示:

C:\test>cmd /e:off
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\test>echo %=c:%
C:\test

C:\test>cd test

C:\test\test>echo %=c:%
C:\test\test

3) ______; CD___________
编辑-实际上,APPDIR的工作方式是一样的

此动态变量始终对CMD和CMD都可用。EXE和JScript。可以定义覆盖值,但不能定义CMD。EXE或JScript都可以看到覆盖值,但SET命令可以列出覆盖值。(也未显示,但jeb发现集/A可以读取覆盖值(如果是数字)。

我写了另一个TEST2。JS来探测这个变量。

var shell=WScript.CreateObject("WScript.Shell");
var env=shell.Environment("Process");
WScript.echo('Within JScript: __CD__='+env("__CD__"));
env("__CD__") = "JS override";
WScript.echo('Within JScript after override: __CD__='+env("__CD__"));
shell.run('cmd /c "set __CD__&pause",1,0');

以下是一些测试的结果:

Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\test>echo %__CD__%
C:\test\

C:\test>set __CD__
Environment variable __CD__ not defined

C:\test>set "__CD__=Batch override"

C:\test>echo %__CD__%
C:\test\

C:\test>set __CD__
__CD__=Batch override

C:\test>cscript //nologo test2.js
Within JScript: __CD__=C:\test\
Within JScript after override: __CD__=C:\test\

C:\test>

下面是CMD的结果。EXE窗口显示TEST2。JS开放了:

__CD__=JS override
Press any key to continue . . .

如果我定义了ENV的快捷方式。具体如下:

Target:   C:\test\env.js __CD__
Start in: C:\test\xyz

然后当我点击它时,我会得到一个警报框,上面写着:

__CD__=C:\test\xyz\

我觉得这些结果很有趣。动态值不能是真实的环境变量。大概有一个低级操作系统环境变量访问例程,每当要求进程返回\uuuuuucd\uuuuu的值时,它就会自动返回进程的当前目录。即使定义了名为\uuuu CD\uuuu的真正静态环境变量,它也会这样做。

CMD。EXE SET命令必须以与大多数其他上下文不同的方式访问环境变量。我设想,可以编写一个C程序来获取指向进程环境内存的指针,并解析任何真正的用户定义的\uuuucd\uuuuu值,就像SET命令一样。

考虑到提供此值的是一个低操作系统例程,所以即使在命令扩展被禁用时,%\uuuuu CD%仍然可用也就不足为奇了。

C:\test>cmd /e:off
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

C:\test>echo %__cd__%
C:\test\

C:\test>cd test

C:\test\test>echo %__cd__%
C:\test\test\

我想从操作系统的角度来看,当前目录的概念对每个进程都至关重要,MS决定通过动态虚拟环境变量让进程访问该值。XP操作系统允许扩展任何用户定义的__CD__覆盖值。也许这给某些应用程序带来了问题,MS决定修改环境访问例程(也许从Vista开始?)始终返回真正的当前目录,而不管任何用户定义的__CD__变量。

因此,基于返回当前目录是一个低级例程的理论,我现在认为不可能使用本机批处理命令来可靠地获取用户定义的\uuuuuuCD\uuu值。

 类似资料:
  • 我想计算两个点之间的距离,但是当我使用函数时,程序有错误,并说android.location.位置与同一文件中定义的类型冲突。我通过数学规则计算距离,但是当我给出我的位置的纬度和经度时,当程序运行时,程序已经停止。为什么?我很困惑。 日志猫: 谢谢干杯

  • 问题内容: 在这里只能是最终的。为什么?如何在不保留为私有成员的情况下重新分配方法? 单击该如何返回? 问题答案: 如注释中所述,其中一些在Java 8中变得无关紧要,在Java 8中final可以隐式使用。但是,只能在匿名内部类或lambda表达式中使用有效的最终变量。 这基本上是由于Java管理闭包的方式。 创建匿名内部类的实例时,该类中使用的任何变量都将通过自动生成的构造函数复制其值。这样避

  • 我正在做下面这样的事情,但它不起作用。为什么?又是如何做到的呢?

  • 问题内容: 大家好!我有一个简单的问题。…为什么我可以从main方法中获得一个私有变量?我知道,我在包含类中,但这是主要的。我相信主体不是包含它的类的一部分……那么我不会去找私人成员,但是我可以……为什么?请帮助… thx 问题答案: Main是您的类的一部分,您已经在类中声明了它:) main不是您的对象的一部分,它不会是您从该类创建的对象的任何部分,但它仍然是该类的一部分。这对于任何静态函数都

  • 问题内容: 在这里只能是最终的。为什么?如何在不保留为私有成员的情况下重新分配方法? 单击该如何返回?我的意思是, 问题答案: 如注释中所述,其中一些在Java 8中变得无关紧要,在Java 8中final可以隐式使用。但是,只能在匿名内部类或lambda表达式中使用有效的最终变量。 这基本上是由于Java管理闭包的方式。 创建匿名内部类的实例时,该类中使用的任何变量都将通过自动生成的构造函数复制

  • 问题内容: 在某些地方,我看到了语法,其中用名称初始化变量,有时不使用名称初始化。例如: 命名变量有 什么意义? 问题答案: 该参数是可选的(可以创建带有或不带有它的变量和常量),并且在程序中使用的变量不依赖于它。名称在两个地方可能会有所帮助: 当您想要保存或还原变量时 (可以在计算后将它们保存到二进制文件中)。从文档: 默认情况下,它为每个变量使用Variable.name属性的值 但是你有变量