目录

Windows Bat批处理 笔记

echo

echo off

@echo off 表示不显示所有命令的回显。

比如Bat脚本中有cd转移指令,开启echo on会使当前cmd的路径跳转,关闭echo off则不会跳转,留在原路径

batch echo换行

1
@echo.

Call

call 从批处理程序调用另一个批处理程序

call有几种用法

第一种用法,也就是最常用的一种,调用另一个批处理,在被调用的批处理执行完后在执行call下面的命令。如:

1
2
3
4
@echo off
call a.bat
dir c:\
pause

如果在被调用的批处理里面有参数,调用的时候需要在后面加上参数。

如:

a.bat内容:

1
2
3
4
5
6
7
@echo off
echo %0 %1
b.bat内容
@echo off
call a.bat hello
dir c:\
pause

那么,在执行b.bat的时候,会将hello赋值给%1,而%0代表a.bat自己。

(在批处理中,可以使用%*代表所有参数%1-%9代表9个参数,%0代表批处理自己,其扩展用法见call /?,在讲for的时候也会讲到)

在这里讲下goto :eof的用法,如:

a.bat内容:

1
2
3
4
5
6
7
8
@echo off
echo %0 %1
goto :eof
b.bat内容
@echo off
call a.bat hello
dir c:\
pause

这里,在显示完hello后,会执行dir c:\并暂停,如果将goto :eof改成exit,在显示完hello后就会自动退出。因为goto :eof后会转到a.bat结尾,即只退出a.bat然后会继续执行dir;由于call a.bat,在执行a.bat和b.bat是一个CMD窗口,exit的话就会直接退出这个窗口,这就是goto :eof和exit区别。

call的第二种用法,调用一个命令,如:call ping 127.1,这和直接ping 127.1看似是一样的,但还是有区别的。主要用法就是call set,在后面讲延迟环境变量的时候慢慢体会。

call的第三种用法,调用一个应用程序,call notepad.exe。call可以这么用,但一般在调用应用程序的时候会使用start,很少用call。

call的第四种用法,调用本批处理中的一个标签。如:

1
2
3
4
5
6
7
@echo off
call :no1
start notepad.exe
exit
:no1
start calc
ping /n 2 127.1>nul

在这里会先打开计算器,然后打开记事本。在call标签的时候要加上“:”。

这与goto有什么区别呢?在看一个例子:

1
2
3
4
5
6
7
@echo off
goto :no1
start notepad.exe
exit
:no1
start calc
ping /n 2 127.1>nul

这里只会打开计算器,并不打开记事本。

因为,goto :no1是转到标签:no1处运行,运行完就退出,而call是调用:no1,运行完继续执行call下面的命令

注释

::是bat里的一种注释语句,

暂停

pause 也是命令,表示暂停程序,执行pause会输出请按任意键继续…

mshta

它支持命令行参数,可以接收JS和VBS的方法。看示例(在命令行下测试):

JS:

mshta vbscript:window.execScript(“alert(‘hello world!');”,“javascript”)

VBS:

mshta javascript:window.execScript(“msgBox(‘hello world!'):window.close”,“vbs”)

调用VBS,分别使用MSGBOX函数和POPUP方法:

1
2
mshta vbscript:msgbox("该干活了,伙计!",64,"提示")(window.close) 
mshta vbscript:CreateObject("Wscript.Shell").popup("该干活了,伙计!",7,"提示",64)(window.close)

execute方法 一条语句连续弹二个信息框:

mshta vbscript:execute(“msgbox ““one BOX”":msgbox ““two BOX”":window.close”)

LZ他们弄的,调用系统的英文阅读:

mshta vbscript:createobject(“sapi.spvoice”).speak(“Good luck”)(window.close)

下面是其他网友的补充

今天在一个批处理里看到一条命令mshta,感兴趣的可以搜索一下“mshta 批处理”

1
2
echo off
start mshta javascript:if(confirm("将连接网站检测您是否安装了.net 2.0运行库,是否继续?该操作将不影响安装程序的运行!\r\n如果您确信已安装相应.net组件,请按取消,否则请按确定!"))window.open(" http://www.test.com/test.aspx");window.close();

在百度查询了一下,原来mshta.exe是微软Windows操作系统相关程序,用于执行.HTA文件,或在批处理中结合其他语言的代码;如:mshta javascript,可用于运行一个HTML网页而不会出现安全警告。

下面是摘录内容:

以下用js表示javascript,用vbs表示vbscript。

一般应用

代码:

mshta //www.jb51.net

js与vbs

有时,可以在bat中调用mshta js或vbs来实现一定的功能。如弹出对话框:

代码:

mshta “vbscript:msgbox(“内容”,0,“标题”) & window.close”

但是,并非所有的js和vbs命令都能通过mshta运行,比如wscript.sleep就不能。

代码:

rem 以下代码是错误的:

mshta “vbscript:wscript.sleep(1000) & window.close”

可见,mshta调用js或vbs也是有条件的。

基本规则

※mshta所引用的命令必须相当于一个数值或变量。

这句话是什么意思呢?学过vbs的朋友都知道,vbs中弹出对话框的命令是:

代码:

msgbox “内容”,0,“标题”

但是,如果在bat中运行mshta “msgbox “内容”,0,“标题”",就会出现错误。这是因为msgbox “内容”,0,“标题"并不相当于一个数值或变量,而是相当于一个语句。

如果还没有理解,就请看下面的vbs:

代码:

1
2
3
4
5
6
7
a=1
b=2
c=a+b
msgbox "内容"
inputbox "内容"
d=msgbox("内容")
e=inputbox("内容")

这段代码中,第一行1是数值,a是变量,a=1是一个设置变量a的值为1的语句。

第二行2是数值,b是变量,b=2是语句。

第三行a+b这个整体相当于数值,c是变量,c=a+b是语句。

至于第四行,情况有些变化:

“内容"是数值,msgbox “内容"这个整体是一个弹出对话框的的语句。

第五行,“内容"是数值,inputbox “内容"是语句。

第六行msgbox(“内容”)这个整体相当于数值(注意它与msgbox “内容"的区别),d是变量,d=msgbox(“内容”)是一个设置变量d的值为msgbox(“内容”)的语句。

同理,第七行inputbox(“内容”)相当于数值,e是变量,e=inputbox(“内容”)是语句。

因此,以下命令都是有效的(其中 & window.close 暂时不去理会):

代码:

1
2
3
4
5
6
@echo off
mshta "vbscript:1 & window.close"
mshta "vbscript:a & window.close"
mshta "vbscript:a+b & window.close"
mshta "vbscript:msgbox("内容") & window.close"
mshta "vbscript:inputbox("内容") & window.close"

而以下命令都是无效的:

代码:

1
2
3
::以下命令都是无效的
mshta "vbscript:msgbox "内容""
mshta "vbscript:inputbox "内容""

现在明白了吧?

对于js,也有类似的情况,只是js中不明显罢了。 另外,我刚刚发现vbs中execute函数可以调用语句。很复杂,自己研究吧。

连接多个命令

连接多个命令时,每个命令都必须遵守上述的基本规则。

※对于js,用分号 ; 连接多个命令。

代码:

mshta “javascript:alert(‘OK!');alert(‘1234’);window.close()”

※对于vbs,用 & 连接多个命令。

代码:

mshta “vbscript:msgbox(“内容”) & msgbox(“1234”) & window.close”

※注意&在bat中有特殊意义,所以此时mshta后面的代码必须用引号引起来!

window.close的作用

试着运行下面的代码:

代码:

mshta “vbscript:msgbox(“内容”)”

你会发现,不仅弹出了需要的对话框,还出现了一个讨厌的白框。window.close的作用就是关闭它。

为什么wscript.sleep不能用

微软最初设计mshta时是为了运行hta程序(可近似理解为HTML网页程序),而wscript在HTML网页上用不了(它只能在真正的js或vbs上用),所以调用mshta js或vbs时要避开它。

利用mshta制作图形界面

其实,利用mshta也可以在bat中制作windows图形界面,但在这里就不详细介绍了。如果有兴趣请看

http://baike.baidu.com/view/712376.htm或https://www.jb51.net/article/40060.htm。

引用解释:

※mshta所引用的命令必须相当于一个数值或变量。

这个只是针对 vbscript 协议。用其他方式运行vbs语句则可以。比如 about 协议:

代码:

mshta “about:

确切的说法应该是,用vbscript协议运行的代码中,不能包含语句,只能是表达式和函数(此时函数其实也是表达式)。这里的语句是vbs概念中的语句(statement),而不是普通的“一句话”的意思(sentence)。

msgbox “内容”,0,“标题”,这个的确是一条语句,而不是“相当于”。

e=inputbox(“内容”),在vbs脚本,它可以作为语句(赋值语句)也可以是表达式(比较变量e与函数inputbox(“内容”)的返回值)。

如果用vbscript协议运行,则它只是比较表达式。

vbscript协议运行代码可以用&连接不同的表达式,这个发现不错。其实就是表达式连接符。

但如果要运行更复杂的语句,最好是用execute。execute也很简单。

如alert方法,它不能直接在vbs脚本中运行,因为它是window对象的方法,而window对象是mshta、IE等html解释器提供的,脚本宿主WSH并没有提供。除非在vbs创建这样的对象,比如InternetExplorer.Application。

mshta运行js语句没有那样的限制。超版都说了,只是 vbscript 协议有此限制。看来vbs到底是比js要差一点。

比如下面,var a=1就是明显的赋值语句,alert方法与close方法也可以看作语句。

代码:

mshta “javascript:var a=1; alert(a); close();”

不是CreateObject(“WScript.Shell”),而是createObject(“Microsoft.XMLHTTP”)。

我一直想做一个mshta实现文件下载,但总有些问题。

Microsoft.XMLHTTP 组件自身的问题,禁止跨域操作。

setlocal/endlocal

命令 setlocal (开启本地变量) endlocal (结束本地变量) 很多新手不理解这句话是什么意思,在批处理中有什么作用。 其实在批处理中 setlocal 作用很大,配合 endlocal (结束本地变量) 它可以使你的代码更简洁,易读,且不容易出错。 举例: 假设你在批处理的开头部分有这么一句 set var=123 那么在批处理结束以前,变量 var 的值就永远是 123 除非你 运行了 set “var=” 来把它的值清空。或 set var=别的什么 把它的值改变 否则它的值永远是 123 当写某些代码时,需要把变量的值累加,如: set var=%var%567 此时var的值就是 123567 或是 set /a var+=1 (这是当var的值是有效数字时)每运行一次,var的值就会加1 但当某段代码需要重复运行时,我们有时、甚至是经常需要var的值回到原始的值,即:123 你可能会说这还不好办,一句就ok 了 set var=123或set var= 不错,确实是这样,但如果我们需要将一大堆的变量都会回到原始值呢? 比如: var num a b c d e f ……… 你难道要

1
2
3
4
5
6
set var=
set num=
set a=
set b=
........ 
........ 

这样吗? 有了setlocal 和 endlocal 就不用这么麻烦了。 看代码

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
@echo off 
set var=123 
set num=4456 
set a=ham 
setlocal 
set var=abcd 
set num=jkl 
set a=efg 
set max=1234567
::到了这一步我想不用echo你应该也都知道这三个变量的值改变了 
::并且还给一个新的变量赋了值 max 
::对于不熟悉setlocal  endlocal 命令的朋友来说要想让这 
::三个变量回到开始的值可能就只有回到开头那三句去了其实不用 
::一句就可以了看下面的
endlocal 
echo %var% %num% %a% 
echo %max% 
pause 

看到区别了吗? 不错,setlocal 和 endlocal 这两句中间的命令给所有的变量赋的值都消失了, 就好像从没有运行过它们一样。 运行 setlocal 以前变量的值是什么 在运行 endlocal 以后, 又回到了什么。如果之前是空值,即:没有赋值 如:例子中的 max 那么 echo %max% 就会显示 ECHO 处于关闭状态 以前 cn-dos 里有位版主(好像就是我们论坛的第三方软件版块的现任版主)曾经很形象的解释过这个问题, 这里借用一下 ,记得不是很清楚了,加一点我自己的描述。 他说:   批处理运行时会开辟一块地方给变量,我们可以把它想像为一块黑板, 你可以在黑板上任意写字,在批处理中这种写字,就是给变量赋值或清空或改变变量的值 如:set var=123 set num= set /a str+=1 set var=%var% %num% 等等之类的。 而 setlocal 命令就是在黑板中又划出一块方块来,你在这之后所写的字就全在这个方块中, (当然这个方块的容量、大小不会有什么限制,你或者把他理解为在这个黑板上又覆盖了一块同样大小的新的黑板,

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
更为恰当。当然这个黑板的容量大小应该要减去你在原来那块黑板上所写的内容,这个就不在这里讨论了,
知道个大概就行。)
当运行 endlocal (结束变量)后,相当于把你在原来那块黑板上划的方块擦掉了,连内容一起擦掉了。
又或者说,把这个新的黑板拿走了,你在这个新黑板上写的字也都没有了,回到你面前的又是原来的那块黑板,
当然你以前写在上面的字仍然还在。它不会擦掉你的,也不会自动给你写些新东西上去。
也就是 原来的变量还是原来的值,原来没有赋值的,仍然是空值。不管你在那块新黑板上写过什么,都过去了,
就象什么也没发生过一样。
  当新黑板上的内容与老黑板上的内容发生冲突时,则以新黑板上的内容为准,
  若老黑板上的内容没与新黑板的内容冲突时,老黑板上的内容在新黑板中仍然有效。
在提一句,新黑板最多只能连续覆盖32块,否则就会提示 “以达到最大递归层”的错误信息。
所谓 “连续覆盖”就是运行了 setlocal 而没有运行 endlocal 的情况。

enabledelayedexpansion

setlocal enabledelayedexpansion 设置本地为延迟扩展

变量延迟的启动语句是“setlocal enabledelayedexpansion”,并且变量要用一对叹号“!!”括起来(注意要用英文的叹号),否则就没有变量延迟的效果。

example:

./1.png

在这里插入图片描述批处理读取命令时是按行读取的,在处理之前要完成必要的预处理工作,这其中就包括对该行命令中的变量赋值。

./2.png

在这里插入图片描述批处理设计了变量延迟。简单来说,在读取了一条完整的语句之后,不立即对该行的变量赋值,而会在某个单条语句执行之前再进行赋值,也就是说“延迟”了对变量的赋值。

Str

拼接

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
@echo off
 
rem 两个变量拼接等号前后一定不要有空格
set str1=Hello
set str2=world
set result=%str1%, %str2%!
echo %result%
 
rem 开启延迟变量
@setlocal enableextensions enabledelayedexpansion
set words=China,Hubei,Wuhan
set result2=
for %%i in (%words%) do (
  set result2=!result2! %%i
)
 
rem 将字符串最前面的空格去掉  
set "result2=%result2:~1%"
echo %result2%

说明:如果复合语句中使用变量,一定要开启延迟变量

文件夹

创建

1
md pkgName

可以使用excel,批量拼接(&符号拼接单元格)粘贴至控制台即可

explorer

1
start