Board logo

标题: [其他] [研究]新一代外部命令?VBS强化批处理? [打印本页]

作者: defanive    时间: 2009-2-21 21:28     标题: [研究]新一代外部命令?VBS强化批处理?

给出代码一则:
  1. @echo off
  2. set /p a=Type:
  3. set "a=%a:"=""%"
  4. setlocal enabledelayedexpansion
  5. echo wscript.echo len("!a!")>a.vbs
  6. for /f %%a in ('cscript /nologo a.vbs') do set alength=%%a
  7. del /f /q a.vbs
  8. echo 长度为%alength%
  9. pause
复制代码
好了,这个例子给出的结果还比较理想:没有臃肿的代码,核心部分不到5行,强大乎~




当然,这个不是我最先提出来的。。。

这里是运用了VBS中的WScript.Echo方法,就是向脚本宿主发送消息。。。

当直接双击运行VBS的时候,脚本宿主是WScript,但是在CMD中用CScript来调用的话脚本宿主就是CMD了,实现了结果的输出。。。

那么接下来就只需要通过For,读取结果并赋值就可以了。。。
  1. 创建VBS —> VBS计算结果 —> VBS返回结果 —> 通过For获取结果 —> 删除VBS
复制代码
当然,可行性不高。每次都这样做的话,也算是很麻烦的,代码也变长很多,临时文件多。。。



改造方案一:Mshta调用

这样做的最大好处是,没有临时文件,无论怎么做都可以,只要在一行只内,是很理想的方案。。。
  1. mshta vbscript:WScript.Echo(Len("123"))(window.close)
复制代码
很可惜的是,执行失败,提示缺少WScript对象。。。

分析下原因:

缺少WScript对象,就是没有脚本宿主,怎么听都像扯谈,既然都能执行了,怎么会没有脚本宿主呢?

其实我们看看命令本身,我们就会知道答案:mshta?!

没看出来?正常,因为这个命令是缩写,但是这样写你就能看出来:MS-HTA!!

对,实际上,我们所编写的VBS代码都是在一个HTA上面运行的,HTA实际上就是一个网页。。。

是网页调用脚本,并不是脚本被脚本宿主解析并执行!

所以,mshta调用是没有脚本宿主的。。。

方案一无效。。。



改造方案二:外部命令化

我们常用的内部命令,外部命令,不外乎都是EXE和COM,能实现一定的功能,多为高级语言所编写。。。

借助命令的思想,可以把编写好的VBS作为一个外部的命令。。。

例子一个:

Example.vbs
  1. @Echo Off
  2. SetLocal EnableDelayedExpansion
  3. Set /p a=Type:
  4. Call :Functions "aLength" "StrLen" "!a!"
  5. Call :Functions "pButton" "MsgBox" "字串符!a!的长度为!aLength!" "64" "CMD"
  6. Call :Functions "pButton" "MsgBox" "继续测试?" "68" "CMD"
  7. If %pButton%==6 (%0) else (Goto :EOF)
  8. :Functions
  9. Setlocal EnableExtensions
  10. For /f "tokens=1*" %%a in (""%*"") Do (For /f %%d in ('CScript /NoLogo Functions.vbs %%b') Do (set ret=%%d))
  11. Endlocal&Set "%~1=%ret%"
  12. Goto :EOF
复制代码
Functions.vbs
  1. Set objArgs = WScript.Arguments
  2. If objArgs.Count<=0 Then WScript.quit
  3. Select Case objArgs(0)
  4. Case "StrLen"
  5. If objArgs.Count<2 Then WScript.quit
  6. WScript.Echo Len(objArgs(1))
  7. Case "MsgBox"
  8. If objArgs.Count<4 Then WScript.quit
  9. WScript.Echo MsgBox(objArgs(1),objArgs(2),objArgs(3))
  10. End Select
复制代码
测试效果很好。。。

可能有人会说,获取长度的话,完全可以自己写一个,消息框的话完全可以用mshta代替。。。

但是,这样虽然多了一个VBS文件,但是可拓充性很强。。。

如果你想获得一个字符的ASCII码值呢?如果你想实现浮点运算呢?如果你想小数开方、自然对数等等呢?

这样做,你完全可以马上写出来一个自己需要的伪劣“第三方命令行工具”!

至于消息框,用mshta你是不可能知道用户按下了哪个按钮,而这样做完全可以。。。




说说方案二的缺点:

测试环境:Window Vista Home Basic

在测试环境下,执行前需要花费0.3秒左右,能感受到明显的停顿,这是VBS的问题,启动慢

其次,并不能保证每台机器都有装上VBS,还是有部分用户没有装VBS的

第三,在VBS执行期间会增加两个进程(cmd.exe和cscript.exe),可以用任务管理器杀掉,导致返回值为空,或出错退出

第四,VBS损坏等直接导致执行失败,同命令行工具一样,少一个批处理都无法完成任务



好了,这个所谓的命令行工具,前途还是有的。。。

[ 本帖最后由 defanive 于 2009-2-22 17:14 编辑 ]
作者: defanive    时间: 2009-2-21 21:29     标题: 自写VBS第三方工具

自己写的一个VBS,里面有很多功能

功能:


StrLen:字符串长度
MsgBox:多样式消息框
InputBox:输入框
Math:Set /a 的拓展,支持输入任意表达式,表达式中可使用数学函数(Abs等)
DataAdd:为给定日期推移任意单位时间
DataDiff:计算两个日期单位时间差
GetLocale:获得当前区域ID
VBSFunction:执行VBS命令并返回值
VBScript:执行VBS命令但不返回值

当然,功能还可以拓展,不过我觉得没有必要了,有了VBScript和VBSFunction就可以实现调用VBS了。。。

使用方法:

将Functions.vbs放到批处理同一目录下,在批处理最后增加函数代码(见下文)

然后随时需要调用VBS中的函数就这样:


Call :Functions "储存返回结果的变量" "函数名" "参数一" "参数二" "参数三" ……

例如,调用StrLen函数则这样写:

Call :Functions "aRes" "StrLen" "%a%"

则变量a内容的长度就被保存在了aRes变量里面

VBS和示例批处理在附件下载:




Functions.vbs
  1. Set objArgs = WScript.Arguments
  2. If objArgs.Count<=0 Then WScript.quit
  3. Select Case objArgs(0)
  4. Case "StrLen"
  5. If objArgs.Count<2 Then WScript.quit
  6. WScript.Echo Len(objArgs(1))
  7. Case "MsgBox"
  8. If objArgs.Count<4 Then WScript.quit
  9. WScript.Echo MsgBox(objArgs(1),objArgs(2),objArgs(3))
  10. Case "Math"
  11. If objArgs.Count<2 Then WScript.quit
  12. WScript.Echo CDbl(Eval(objArgs(1)))
  13. Case "InputBox"
  14. If objArgs.Count<4 Then WScript.quit
  15. WScript.Echo InputBox(objArgs(1),objArgs(2),objArgs(3))
  16. Case "DateAdd"
  17. If objArgs.Count<4 Then WScript.quit
  18. WScript.Echo DateAdd(objArgs(1),objArgs(2),objArgs(3))
  19. Case "DateDiff"
  20. If objArgs.Count<4 Then WScript.quit
  21. WScript.Echo DateDiff(objArgs(1),objArgs(2),objArgs(3))
  22. Case "GetLocale"
  23. WScript.Echo GetLocale()
  24. Case "VBSFunction"
  25. If objArgs.Count<2 Then WScript.quit
  26. WScript.Echo Eval(objArgs(1))
  27. Case "VBScript"
  28. If objArgs.Count<2 Then WScript.quit
  29. Execute(objArgs(1))
  30. End Select
复制代码
使用这个VBS需要在批处理尾部加上函数代码:
  1. Goto :EOF
  2. :Functions
  3. Setlocal EnableExtensions
  4. For /f "tokens=1*" %%a in (""%*"") Do (For /f %%d in ('CScript /NoLogo Functions.vbs %%b') Do (set "ret=%%d"))
  5. Endlocal&Set "%~1=%ret%"
  6. Goto :EOF
复制代码

作者: Batcher    时间: 2009-2-21 22:37

其次,并不能保证每台机器都有装上VBS,还是有部分用户没有装VBS的

能否举个例说明一下哪些系统没有装VBS呢?
作者: defanive    时间: 2009-2-21 22:47

一般只要支持VBS的系统安装时都会安装,但是部分精简版,或者某些无聊人士会手动把VBS的解释关联给取消掉。。。
作者: BBCC    时间: 2009-2-21 23:33

的确如此,通过VBS来做成 bat难以完成的东西会是很方便.

但好像方案2的例子报错的说...

F:\Test>F:\Test\example.bat
Type:153
F:\Test\Functions.vbs(1, 1) Microsoft VBScript compilation error: Invalid charac
ter

F:\Test\Functions.vbs(1, 1) Microsoft VBScript compilation error: Invalid charac
ter

此时不应有 &。


另外有点小笔误.
作者: everest79    时间: 2009-2-22 01:17

脚本是解释性语言,可以这么理解,在常规的windows桌面环境下,它的解释器是WSH,也就是windows 脚本宿主,如果在IE中执行,那他的解释器就是IE,在MSHTA中执行,那么解释器就是MSHTA
而WScript对象,是属于WSH,并不是一个VBScript自带的内部对象所以不能在其它解释器中直接使用

WSH是windows系统自带的一个功能,不存在安装的问题
作者: defanive    时间: 2009-2-22 17:41

7L,WSH的确不需要安装,但是用户可以破坏CScript.exe和WScript.exe,或者没有注册vbsXXXX.dll
作者: zqz0012005    时间: 2009-2-22 18:39

这个标题起得,那个啥。。。

早已不是“新一代”了,只是玩bat的很多,而玩vbs的较少,vbs的应用往往没有bat广。而实际上对于bat难以解决的或不方便解决的,高手往往会借助于vbs。
如果在网吧上网,我一般会运行一下
  1. regsvr32 /s wshom.ocx scrrun.dll vbscript.dll jscript.dll
复制代码

作者: Batcher    时间: 2009-2-22 18:42     标题: 回复 9楼 的帖子

其实在实际工作中,VBS的用处也挺多的。
我做过的项目中有用VBS监控硬盘空间变化并自动发邮件的,还有监控网络状态的等等。
作者: defanive    时间: 2009-2-27 18:10

VBS是很强大的。。。
作者: youxi01    时间: 2009-3-29 12:12

想法非常不错
不过个人建议:我们需要去开发那些批处理不能完成或者不好完成的vbs功能块,如:日期计算、字符串长度计算等。

而且要么就不做,要做就做好,应该给一些各“命令”使用说明....
作者: ejzhang    时间: 2010-8-2 12:36

在服务器端完全可以用VBS的,因为服务器端的环境都比较可控,能保证VBS的正常运行,而且VBS要比BAT强大得多。




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