模块调用
1.
如何在一个脚本的执行中调用另外一个脚本文件?
利用
Call
命令的两种用法来实现该功能:
l
调用另外一个脚本文件:
CALL [[<Drive>:]<Path>]<batch-file-name> [<parameters>]
注意
:
(1)
如果直接在脚本文件直接调用另外脚本,则子脚本正常或异常退出
(exit /b
语句
)
都会导致父脚本的退出。直接写脚本或可执行文件相当于将子脚本的命令展开在父脚本中。
(2)
Call
命令则是执行脚本,获得子脚本的退出代码,设置
errorlevel
,然后返回父脚本继续执行。
(3)
Call
命令不会启动命令解释器的新的子进程,还是在执行父脚本的进程中执行子脚本,
因此子脚本中对环境变量的改变也会影响父脚本的执行。
(4)
另外
Call
命令还有隔离环境变量,在子脚本中定义的环境变量,即使是全局的环境变量,也不能影响父脚本的环境变量定义。而父脚本中的环境变量可以传递到子模块中。这样便于模块化构建脚本程序。
(5)
Call
命令不影响当前目录。
l
从自身的某一行号开始执行:
CALL :<label> [<parameters>]
相当于使用自身脚本文件作为子脚本的递归调用。
2.
如何打开一个子进程来运行命令解释器?
使用
CMD
命令,执行命令解释器:
CMD [{/c|/k}] [/s] [/q] [/d] [{/a|/u}] [/t:<f><g>] [/e:{on|off}] [/f:{on|off}] [/v:{on|off}] [<string>]
其中的选项(大小写不敏感)解释如下:
(1)
[{/c|/k}] [/s]:
/k
执行完
<string>
命令后不退出命令解释器,等待用户输入;
/c
执行完
<stirng>
命令立即返回;
/s
修饰以上两者:
如果指定了
/C
或
/K
,命令选项后的命令行其余部分将作为命令行处理;在这种情况下,会使用下列逻辑处理引号字符
("):
1.
如果符合下列所有条件,那么在命令行上的引号字符将被保留
:
-
不带
/S
命令选项
-
整整两个引号字符
-
在两个引号字符之间没有特殊字符,特殊字符为下列中的一个
:
& < > [ ] { } ^ = ; ! ' + , ` ~ [white space]
-
在两个引号字符之间有至少一个空白字符
-
在两个引号字符之间有至少一个可执行文件的名称。
2.
否则,老办法是,看第一个字符是否是一个引号字符,如果是,舍去开头的字符并删除命令行上的最后一个引号字符,保留最后一个引号字符之后的文字。
(2)
/q:
关闭回显,默认打开
(3)
/d:
关闭在执行命令前自动执行的脚本命令,默认执行,这些命令在注册表中的一下路径指定:
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\AutoRun\REG_SZ
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\AutoRun \REG_EXPAND_SZ
(4)
[{/a|/u}]
:
以
ascii
码或
unicode
标准向管道或者文件输出
(5)
[/t:<f><g>]:
指定前景色和背景色,默认黑地白字:
(6)
[/e:{on|off}]
:
打开或关闭命令扩展,
默认打开
(7)
[/f:{on|off}]
:
打开或关闭文件或目录名自动完成,自动完成的键设置在注册表中:
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\CompletionChar\REG_DWORD
HKEY_LOCAL_MACHINE\Software\Microsoft\Command Processor\PathCompletionChar\REG_DWORD
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\CompletionChar\REG_DWORD
HKEY_CURRENT_USER\Software\Microsoft\Command Processor\PathCompletionChar\REG_DWORD
键值格式为:
0xNN, NN
是十六进制的
ASCII
码。
(8)
<string>:
命令字符串
注意:
打开一个子
shell
进程,返回时不影响父
shell
的环境变量
外部的调用
shell
传递进来的环境变量(无论在父进程中是局部变量还是全局变量)
在子
shell
中都是全局初始化变量。
[ZT]
命令的延迟扩展:
From:
中国的
DOS
联盟
在许多可见的官方文档中,均将使用一对百分号闭合环境变量以完成对其值的替换行为称之为
“
扩展(
expansion
)
”
,这其实是一个第一方的概念,是从命令解释器的角度进行称谓的,而从我们使用者的角度来看,则可以将它看作是引用(
Reference
)、调用(
Call
)或者获取(
Get
)。
而命令解释器是扩展环境变量的行为大致如下:首先读取命令行的一条完整语句,在进行一些先期的预处理之后,命令被解释执行之前,会对其中用百分号闭合的字符串进行匹配,如果在环境空间中找到了与字符串相匹配的环境变量,则用其值替换掉原字符串及百分号本身,如果未得到匹配,则用一个空串替换,这个过程就是环境变量的
“
扩展
”
,它仍然属于命令行的预处理范畴。
而一条
“
完整的语句
”
,在
NT
的命令解释器
CMD
中被解释为
“for if else”
等含有语句块的语句和用
“& | && ||”
等连接起来的复合语句。
因此,当
CMD
读取
for
语句时,其后用一对圆扩号闭合的所有语句将一同读取,并完成必要的预处理工作,这其中就包括环境变量的扩展,所以在
for
中的所有语句执行之前,所有的环境变量都已经被替换为
for
之前所设定的值,从而成为一个字符串常量,而不再是变量。无论在
for
中将那些环境变量如何修改,真正受到影响的只是环境变量空间,而非
for
语句内部。
而为了能够在
for
语句内部感知环境变量的动态变化,
CMD
设计了延迟的环境变量扩展特性,也就是说,当
CMD
读取了一条完整的语句之后,它不会立即执行变量的扩展行为,而会在某个单条语句执行之前再进行扩展,也就是说,这个扩展行为被
“
延迟
”
了。
延迟环境变量扩展特性在
CMD
中缺省是关闭的,开启它的方法目前有两个:一是
CMD /v:on
,它会打开一个新的命令行外壳,在使用
exit
退出这个外壳之前,扩展特性始终有效,常用于命令行环境中;二是
setlocal EnableDelayedExpansion
,它会使环境变量的修改限制到局部空间中,在
endlocal
之后,扩展特性和之前对环境变量的修改将一同消失,常用于批处理语句中。
3.
如何调用子进程来执行其他程序(当然也包括
CMD.exe
)或者通过文件关联来打开文件?
Start
命令可以用来执行该操作,利用文件关联来启动相应的程序打开文件:
START [/d<path>] [/separate|/shared]
[“<title>”] [/i] [/b] [{/min|/max}] [{/low|/high|/normal|/abovenormal|/belownormal|/realtime}]
[/wait] [/b] <command>
其中选项为:
(1)
<title>:
新建窗口的题目
(2)
<path>:
初始路径
(3)
[{/min|/max}]
:
启动窗口大小
(4)
[{/low|/high|/normal|/abovenormal|/belownormal|/realtime}]:
制定运行级别
(5)
/wait:
父进程等待子进程执行结束,如果子进程启动的是
GUI
程序,同样等待。
(6)
[/separate|/shared]:
在共享或独立空间运行
16
位程序
(7)
<command>:
要执行的命令行,如果是
CMD
将被
CMDSPEC
环境变量替换,防止从当前目录执行
CMD
(8)
/i:
新环境是传递
cmd
的原始环境,而不是当前环境
(9)
/b:
见下面说明
说明:
Start
命令打开一个新窗口并启动子进程执行命令解释器,在命令解释器中执行
<command>
。对于非
GUI
程序,执行完毕后不返回主程序,而是等待用户继续输入,直到
exit
。对于
GUI
程序,启动界面后立即返回,并关闭解释器窗口(和脚本中的行为不同,在脚本中是等待
GUI
程序退出,继续执行后续命令)。如果父进程在等待,则直到该
GUI
程序退出,父进程才返回(或者父进程被
Ctrl+C
中止等待,但不影响
GUI
程序的执行)。
但是如果指定
/b
选项,
start
并不启动一个新的窗口和进程,而是在当前窗口执行。这时如果没有指定
/wait
选项,只有通过
Ctrl+Break
方法中止该程序,而
Ctrl+C
由父进程解释器处理,因而不能中止该程序,但解释器启动的程序可以得到
Ctrl+C
的输入来自行处理该事件。
Start
命令定义了一些扩展名作为搜索可执行程序的范围,这些扩展名在
PATHEXT
变量中被定义,一般是:
如果给出的是文件名,则利用文件关联来打开;如果是目录,则用
explorer.exe
打开。
Start
命令是在系统
”
启动
”
对话框中被用来启动应用程序。
4.
如何退出脚本
?
可以利用
EXIT
来退出脚本或命令解释器
:
/b
选项打开,表示如果是在执行脚本程序,则退出脚本程序,否则退出命令解释器。如果没有指定
/b,
则总是退出命令解释器。
<n>
是退出代码,如果只是退出脚本程序,命令解释器设置
ERRORLEVEL
为
<n>;
如果退出命令解释器,则进程的退出代码被设置为
<n>
。
<n>
默认值是
0
,当脚本执行到末尾,其退出代码也是
0
。
5.
如何理解
Error level
?
Error level
用来表示命令或程序执行结果的状态,
0
表示正常退出,其它值表示异常退出,一般异常值越大表示错误越严重,但也可用来表示错误的类型。
Error level
可以通过设置环境变量
ERRORLEVEL
来设定:
也可通过在脚本退出时设定:
当命令解释器执行一个可执行程序或内部命令时,获取该进程的退出代码作为
Error level
。
在执行
CHOICE
命令时也会改变
errorlevel
的值。
注意:
Errorlevel
是整数值(正负均可)。通过设置环境变量,虽然可以将
ERRORLEVEL
设置为非整数值字符串,在使用的时候会自动转化为
0
。虽然在
EXIT
退出时也可以用字符串作返回值,但
errorlevel
会被命令解释器自动转化为
0
。
6.
如何在局部范围内指定命令扩展和变量扩展?
SETLOCAL
[{enableextension | disableextensions}] [{enabledelayedexpansion | disabledelayedexpansion}]
该命令可以嵌套,如果设置成功其中任意一个选项,
ERRORLEVEL
变量被设置为
0
,否则为
1
,可以用这个来判断命令解释器是否具有上述开关功能。