Board logo

标题: [原创] WINDOWS中的脚本教程(No.03) [打印本页]

作者: Spring    时间: 2010-6-1 23:57     标题: WINDOWS中的脚本教程(No.03)

WINDOWS中的脚本 No.03

    最近由于被外派了,每天要差不多九十点才回来,早上七点又出门,累的要死,连周末玩的时间都被培训剥夺了一天,没时间写,但是我要写很轻松,因为我只是想写自己的经验感受,所以不用管它是不是对的(尽管大多数时候的确是对的),也不用参考别人的,有心情了随手就能写下来。这篇是我打算写的最后一篇关于VBS基础概念的了,我试图达到的效果是,看完这篇以及之前的几篇,你的思维方式能够适应VBS编程,并且在不会编的时候知道怎么样去求助或者网上搜索。

    这篇要说的就是VBS与BAT最关键的不同的地方,虽然很多功能可能是达到相同的效果,但是实现的编程方式不一样,根据我自己的理解,用一种比较通俗的方式说出来,就是,BAT的代码看起来就像是一个皇帝在发号施令,而VBS的代码像是一个太监总管在安排工作。稍微举个例子,比如皇帝要开个晚会,按照BAT的方式,他下令“要有美酒佳肴,把所有的大官都请来,边聊天边欣赏美女的舞蹈”,他没必要具体这些事是谁干的,
而按照VBS的方式,太监总管下的令是“御膳房去准备美酒佳肴,小太监一到N号每个去分别大官的家里请,年龄小于二十五的漂亮的宫女们等开饭的时候去食堂跳舞”。

    这里面有什么差别呢?我们都知道每个人都不是全能的,必然有的事情你会做别人不会,有的别人会而你不会,而到了程序里面,为了更精简,就更突出了,往往是某个功能只有一个组件能完成,比如一个具体的例子,要显示一串字符,在批处理里面用 echo “你好呀”,而VBS里面的是wscript.echo “你好呀”,明白了吗,VBS里面要干一件事,你必须知道是谁能干这件事,然后指定他用他的功能去干!那我怎么才能知道都谁能干什么呢?查资料!资料没有呢?那我就不知道了,说不定哪天忽然就知道了。。。

    按照比较正规的说法就是,VBS是基于对象的,上面说的御膳房、御膳房里面做臭豆腐的厨子、小太监、宫女等等都是一个“对象”,厨子能够做吃的、宫女能跳舞,这叫做这些对象的“功能”或者“方法”,这些都是他们特殊的方法,也有相同的方法,比如“睡觉”,而长得漂亮就是宫女的“属性”了,太监不可能长的漂亮,但是跟宫女一样都有“名字”,不管是叫“春春”还是“如花”,这是他们共有的属性。为什么他们都有名字这个属性呢,因为他们都是人,而人都是有名字的,卷心菜上面那只青虫没有名字,因为他不是人,但是他会“睡觉”,因为它是动物,而一滴水不会睡觉,因为他不是生物,但是它是“存在的”,因为它存在,但是哲学意义上的存在不是属性。
    我这么说的意思是一些“对象”如果都是一类的,一般都把最普通的那种叫做“父类”,比如“男人”是一个对象,“女人”也是一个对象,“人”也是对象,男人女人都是人,因此“人”是“男人”和“女人”的父类(为什么不叫母类呢?),是人都有名字能睡觉,但是正常情况下(在程序中则为“绝对的任何情况下”)男人不能生孩子,女人没有xjj,这是子类的方法和属性的差异
    多说也说不清楚,你自己慢慢体会吧,我们来说说怎么用VBS中的对象。之前我们已经接触过一个对象了,它叫做 WScript ,我猜它的意思是W(indows)Script,这个东西在WScript.exe或CScript.exe用运行脚本的时候系统自动创建的,就像这个世界生来就有上帝或者女娲,你要问他们是怎么降生的,那谁知道去,但是大家都知道上帝能创造物种,女娲也是能造人的,于是后来的对象就有了。按照我们刚才的说法,就是说 WScript 这个对象有创造对象的功能或方法,之前我们知道它有说话的功能 echo ,表示出来是 WScript.Echo ,哦,原来对象和他的方法之间是用一个dot点连接起来的,查资料知道创造对象的方法名诗 CreateObject ,于是又有了 WScript.CreateObject ,等等,要说明的是方法或者功能都是 Function ,都是有参数的,也可能有返回值,下面来看看我们的第一个自己创造的,也是以后经常要用到的对象怎么降生:
  1. set Spring = WScript.CreateObject("WScript.Shell")
复制代码
我们可以看到,是我们指挥 WScript 对象,给他一个参数是我们要创建的对象的名字(查资料知道的),叫它用 CreateObject 方法(一个函数)把这个对象创建出来,但是怎么用呢?我们用 set 把它放到一个叫做 Spring 的变量里,于是 Spring 就是一个对象,可以使用了。
还记得变量怎么定义的么? var = *** ,而定义一个对象的是 set var = *** ,这里必须要说明,不是定义对象一定不能用 set ,而定义对象一定要 set !
WScript 是不是 WScript.Shell 的父类呢?不是,因为资料上没这么说过,你不能看着样子像就说他们又关系,要有证明的,比如日本爱情动作教育片演员“老毕”和“周杰伦”,其实跟老毕和周杰伦没有任何关系。因此 Spring 没有 WScript 的 Echo 方法。那么有什么呢?自己去查关键字 “WScript.Shell 方法 属性”。一般这种有个点的关系可以理解为“父对象”,就是说“父对象”拥有“子对象”,其实他们没有功能或者属性的相似性,只是可能他们是看起来都是干某一类事情,为了整理方便,我们就这样命名了,比如说“gov”和“城管部队”,他们都是维持国家运作的对象,但是一般都是gov管着城管,于是我们可以叫做 “gov.城管部队”,虽然KTV也是不可缺少的一部分,但是我们不会说“gov.KTV”。

这里再说一个会经常用到的对象 Scripting.FileSystemObject ,对文件的读写等操作都可以用它,今天暂时不演示怎么用,因为它的方法太多,以后实际应用中慢慢熟悉。
(我们在VBS初级阶段的很长一段时间之内常用的对象可能都只有他们三个和与他们相关的。。。)

说一说前两个经常用到的方法和属性(以及BAT中类似的功能)。
WScript 的:
方法:
Echo 显示一些文字(echo)
Sleep 睡会儿,什么都不干(不知道ping 127.0.0.1 有什么用?)
CreateObject 创建对象(这个真没有)
Quit 彻底退出(Exit,某些工具比如FTP也有Quit)
属性:
Argumengs (%*,等下会给例子看看怎么用)
FullName (类似 CMD 的 %comspec% )
ScriptFullName (%0)
------
WScript.Shell 的:
方法:
AppActivate 激活一个窗口
CreateShortcut 创建一个快捷方式
RegReadRegWriteRegDelete 注册表读、写、删(REG命令)
SendKeys 就像是你按了键盘上某些键一样的效果
Run、Exec 运行一个命令(call、start、cmd /c)
ExpandEnvironmentStrings (可以转换 %windir% 等为当前绝对路径)
属性:
CurrentDirectory 当前路径(%cd%)
SpecialFolders 某些特定文件夹的当前绝对路径(VBS中的 %路径环境变量% )
用到对象的地方经常也要用到条件判断语句和循环语句,我们先来看看最基本的 if 和 for 吧。
条件判断
  1. a = inputbox("输入一个数字","输入")
  2. ' 如果不是数字就退出
  3. if not isNumeric(a) then
  4.   msgbox "你输入的不是数字,程序已退出!", vbCritical, "错误"
  5.   wscript.quit
  6. end if
  7. ' 如果是数字再进行下面的判断
  8. if a > 0 then
  9.   msgbox "大于零的"
  10. elseif a = 0 then                   '这个 elseif 可以进行很多次的哦
  11.   wscript.echo "你输入的是 0 "
  12. else
  13.   msgbox "剩下的只可能是小于零的数了。", vbInfomation
  14. end if
复制代码
最简单的循环
  1. for i = 1 to 8 step 2
  2. msgbox i
  3. next
复制代码
来看一些例子便于理解。
如下一个批处理程序 a.bat,是以两个整数为参数,每隔大约一秒从 num1 增加 1 并显示,直到 num2 为止,如果少于两个参数会退出。
可以在 CMD 窗口中用这条命令运行它:
a.bat 1 9
  1. @echo off
  2. set "num1=%1"
  3. set "num2=%2"
  4. if not defined num2 (
  5.   echo 你输入的参数少于两个!
  6.   goto EOF 2>nul
  7. )
  8. set "host=%comspec%"
  9. set "self=%0"
  10. echo 运行我的程序是 %host%
  11. echo 脚本的全路径是 %self%
  12. echo 第一、二个参数分别是 %num1% 和 %num2%
  13. for /l %%i in (%num1%, 1, %num2%) do (
  14.   ping 127.1 -n 2 >nul
  15.   echo %%i
  16. )
  17. pause
复制代码
可以写一个类似的VBS脚本  a.vbs ,可以看到 WScript 对象的一些用法
  1. ' wscript 的属性 wscript.arguments 仍然是一个对象,因此要用 set
  2. set args = wscript.arguments
  3. ' wscript.arguments 的 count(个数)属性是一个数字,不是对象
  4. count = args.count
  5. ' if ... then ... end if ,不要忘了 then 和 end if !
  6. if count < 2 then
  7.   wscript.echo "你输入的参数少于两个!"
  8.   wscript.quit
  9. end if
  10. ' 第一个和第二个参数,是从 0 开始的,对应 0 和 1
  11. num1 = args(0)
  12. num2 = args(1)
  13. host = wscript.fullname
  14. self = wscript.scriptfullname
  15. wscript.echo "运行我的程序是 " & host
  16. wscript.echo "脚本的全路径是 " & self
  17. wscript.echo "第一、二个参数分别是 " & num1 & " 和 " & num2
  18. ' for ... next ,不要忘了写 next !
  19. for i = num1 to num2 step 1
  20.   wscript.echo i
  21.   wscript.sleep 1000 '单位是毫秒, 1秒 = 1000毫秒
  22. next
  23. msgbox "按“确定”退出。。。"
复制代码
可以在 CMD 窗口中分别用下面两条条命令运行,看看有什么不同:
wscript a.vbs 1 9
cscript a.vbs 1 9

关于 WScript.Shell,先只说说他的 Run 方法,其实在我学 VBS 的最初的很长一段时间,我也只会用这个方法。。。
下面三个VBS代码:
b1.vbs
  1. set Spring = WScript.CreateObject("WScript.Shell")
  2. Spring.run "notepad", 1, false
  3. msgbox "在我之前的是启动记事本的代码。", vbSystemModal
复制代码
b2.vbs
  1. set Spring = WScript.CreateObject("WScript.Shell")
  2. Spring.run "notepad", 1, true
  3. msgbox "在我之前的是启动记事本的代码。", vbSystemModal
复制代码
b3.vbs
  1. set Spring = WScript.CreateObject("WScript.Shell")
  2. Spring.run "notepad", 0, true
  3. msgbox "在我之前的是启动记事本的代码。", vbSystemModal
复制代码
可以看出这个方法有三个参数,第一个是要运行的命令,第二个和第三个光是看看不出来。
但你运行一下试试,或者查资料可以知道,第二个控制运行的程序的窗口的状态,第三个是表示VBS是不是要等这条命令执行完了之后再接着执行下面的代码,三个脚本运行的结果分别是:
第一个看到记事本窗口紧接着就弹出一个提示框;
第二个看到记事本窗口但是没有提示框,直到关闭记事本之后提示框才出来;
第三个看不到记事本也没有提示框,但是打开任务管理器发现进程里面有 notepad.exe,将其结束后弹出提示框;
这个方法对我们最有用的可能就是它隐藏运行程序的功能了,而另一个就是是否等待上一句执行完毕之后再执行下面的,下面是我初学时非常激动的作品,不释放任何临时BAT文件哦。
“隐藏运行批处理”
原来的批处理文件:
  1. echo ======== 我的电脑相关信息 ========= > computer.txt
  2. echo 用户名:%username% >> computer.txt
  3. echo 此用户名的相关信息:>> computer.txt
  4. net user %username% >> computer.txt
  5. echo ----------------------------------- >> computer.txt
  6. echo 当前所有进程名字: >> computer.txt
  7. for /f "skip=3" %%i in ('tasklist') do (echo %%i >> computer.txt)
  8. echo ----------------------------------- >> computer.txt
  9. echo 软硬件详细资料:>> computer.txt
  10. systeminfo >> computer.txt
  11. echo ===================================>> computer.txt
复制代码
将它放到VBS中执行,如果把VBS做成EXE的话,由于不产生临时文件直接执行,就达到了加密BAT代码的作用,哈哈哈哈:
  1. set Spring = WScript.CreateObject("WScript.Shell")
  2. Spring.run "cmd /c echo ======== 我的电脑相关信息 ========= > computer.txt", 0, true
  3. Spring.run "cmd /c echo 用户名:%username% >> computer.txt", 0, true
  4. Spring.run "cmd /c echo 此用户名的相关信息:>> computer.txt", 0, true
  5. Spring.run "cmd /c net user %username% >> computer.txt", 0, true
  6. Spring.run "cmd /c echo ----------------------------------- >> computer.txt", 0, true
  7. Spring.run "cmd /c echo 当前所有进程名字: >> computer.txt", 0, true
  8. Spring.run "cmd /c for /f ""skip=3"" %i in ('tasklist') do (echo %i >> computer.txt)", 0, true
  9. Spring.run "cmd /c echo ----------------------------------- >> computer.txt", 0, true
  10. Spring.run "cmd /c echo 软硬件详细资料:>> computer.txt", 0, true
  11. Spring.run "cmd /c systeminfo >> computer.txt", 0, true
  12. Spring.run "cmd /c echo ===================================>> computer.txt", 0, true
  13. msgbox "批处理运行完成,请查看 computer.txt !", 64, "完成"
复制代码
注意上面的代码是怎么转换的,尤其是 for 那一行。
    好了,关于VBS的基本概念我能说的就差不多了,可能对于语法大家还不熟悉,但这是练习的问题,不是认知的问题,自己查资料就能搞定的事情。写了这么长的四篇,可是没看出来VBS能干什么实用的东西,就是谈谈窗口,弄个输入框,唬小朋友还可以,真正实用性还没体现出来。
    从以后的开始就是针对某些特定的功能了,也就是给出一些常用的“对象”的使用示例,对于单个功能的例子到处都有了,我主要想给一些启发思维的,使养成灵活编码的习惯,我以前还没学懂多少的时候,很多功能实现不了,于是想到了上面那个无敌的 run 方法,调用一些命令行来解决,实在是很爽啊,最后,开始出个思考题吧,上面给出的例子中的方法真的能将所有的BAT批处理处理成VBS代码达到加密隐藏运行的效果吗?

----------
参考资料:

面向对象、基于对象
搜索引擎搜索关键字“基于对象 与 面向对象”

WScript 对象
mk:@MSITStore:D:\vbjs.chm::/html/wsobjwscript.htm

WshShell 对象(WScript.Shell)
mk:@MSITStore:D:\vbjs.chm::/html/wsobjwshshell.htm

使用条件语句控制程序执行
mk:@MSITStore:D:\vbjs.chm::/html/vbsConditional.htm

使用循环语句
mk:@MSITStore:D:\vbjs.chm::/html/vbsLooping.htm

Run 方法
mk:@MSITStore:D:\vbjs.chm::/html/wsmthrun.htm
=== No.02 End ===

[ 本帖最后由 Spring 于 2010-6-1 23:59 编辑 ]
作者: siwmm    时间: 2010-6-23 22:15

WScript WScript.CreateObject("WScript.Shell").sendkeys "{NUMLOCK}"
在cmd 下直接输入上面的, 回显:
没有文件扩展“.sendkeys”的脚本引擎
我是想直接在P中直接用,不想另外建.VBS

-------------------
WScript 对象
mkMSITStore:\vbjs.chm::/html/wsobjwscript.htm
下面有CreateObject 方法,
而且
WshShell 对象(WScript.Shell)
mk:@MSITStore:D:\vbjs.chm::/html/wsobjwshshell.htm
左上角的图标  
好像说明  WScript  是WScript.Shell   的父对象关系,
不知道对不对, 刚开始探索VBS,没什么基础。
作者: Spring    时间: 2010-6-23 22:59

VBS脚本代码不能直接运行,你可以用吧代码输出到临时文件,然后通过命令行调用 wscript 或者 cscript 运行它
比如
  1. @echo off
  2. > temp.vbs echo WScript.CreateObject("WScript.Shell").sendkeys "{NUMLOCK}"
  3. cscript.exe -nologo -e:vbs temp.vbs
复制代码
或者通过 mshta 执行能在浏览器环境中能正确运行的脚本,而浏览器中没有了 WScript 对象,但vbs脚本可以使用裸的 CreateObject 方法来创建对象,而经过试验代码中不能有空格,所以变成这样:
  1. mshta vbscript:CreateObject("WScript.Shell").sendkeys("{NUMLOCK}")
复制代码
一半用这个办法时都会在最后加上关闭弹出网页的代码:
  1. mshta vbscript:CreateObject("WScript.Shell").sendkeys("{NUMLOCK}")(window.close)
复制代码
至于后面我也不太清楚,你可以去找专业的教程来看看。
我认为不是,因为wscript.shell不是对象,它只是一类对象的名称,要真是对象的话代码里面应该能直接使用,而实际上我们都是将它作为创建对象方法的参数而已。




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2