我目前正在学习VBScript,我编写这个脚本只是为了练习而我在一个脚本中关闭多个应用程序(记事本和计算)时遇到了麻烦。当我在一个单独的脚本中单独运行应用程序时,它们会关闭。但是当我在这个剧本中将所有内容组合在一起时,他们就不会关闭。我是否在使用WMI服务做错了什么?
'*** calc.vbs ***
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "calc"
WScript.Sleep 1500
WshShell.AppActivate "Calculator"
WScript.Sleep 1500
WshShell.SendKeys "5"
WScript.Sleep 1000
WshShell.SendKeys "{+}"
WScript.Sleep 1000
WshShell.SendKeys "10{+}"
WScript.Sleep 1000
WshShell.SendKeys "12"
WScript.Sleep 1000
WshShell.SendKeys "{=}"
WScript.Sleep 5000
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery("SELECT * FROM Win32_Process
Where Name = 'calc.exe'")
For Each objProcess In colProcessList
objProcess.Terminate
Next
'*** notepad.vbs ***
WScript.Sleep 5000
WshShell.Run "notepad"
WshShell.AppActivate "Untitled - Notepad"
WScript.Sleep 1000
WshShell.SendKeys "This is the first line "
WScript.Sleep 1000
WshShell.SendKeys "~" ' same as {Enter}
WScript.Sleep 1000
WshShell.SendKeys "This is the second line"
WScript.Sleep 1000
WshShell.SendKeys "{Enter}"
WScript.Sleep 1000
WshShell.SendKeys "This is the third line"
WScript.Sleep 5000
Set colProcessListt = objWMIService.ExecQuery("SELECT * FROM Win32_Process
Where Name = 'notepad.exe'")
For Each objProcesss In colProcessListt
objProcesss.Terminate
Next
答案 0 :(得分:1)
你的问题是由一个好的(Option Explicit
)和一些非常糟糕的(全局的On Error Resume Next
组合而成的,它们在远离它们实际使用的长列表中变暗变量,以及疯狂变量名称(objProcess,objProcesss,...))的东西。为了表明这一点,我将使用一种非常简单的技术在一个文件中保留许多不同的有趣代码片段。
Option Explicit
' global consts and variables (not needed here)
' poor man's dispatch; use re-order or comments to choose current piece of work
WScript.Quit Literals()
WScript.Quit CloseCalcBad()
WScript.Quit CloseCalc()
WScript.Quit BadVars()
' can do literals; even date literals; have thought about Locale
Function Literals()
Literals = 1
Dim literalNumeric : literalNumeric = 20
Dim literalString : literalString = "BeachBall"
Dim literalDate : literalDate = #1/2/3#
WScript.Echo "literalNumeric 20:", literalNumeric
literalNumeric = 12.34
WScript.Echo "literalNumeric 12.34:", literalNumeric, GetLocale()
WScript.Echo "literalString: ""BeachBall""", literalString
WScript.Echo "literalDate #1/2/3#:", literalDate, GetLocale()
Literals = 0
End Function
' can't work with undefined vars like strComputer etc.
Function CloseCalcBad()
CloseCalcBad = 1
WScript.Echo "CloseCalcBad()"
Dim WshShell : Set WshShell = CreateObject("WScript.Shell")
WScript.Echo "start calc"
WshShell.Run "calc"
WScript.Echo "waiting"
WScript.Sleep 5000
WScript.Echo "trying to close"
On Error Resume Next
' if you comment out the (evil) OERN, you'll get
' Microsoft VBScript runtime error: Variable is undefined: 'strComputer'
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery("SELECT * FROM Win32_Process Where Name = 'calc.exe'")
For Each objProcess In colProcessList
WScript.Echo "in loop"
WScript.Echo TypeName(objProcess)
objProcess.Terminate
Next
WScript.Echo "done"
CloseCalcBad = 0
End Function
' no OERN, no undefined vars, IT WORKS!
Function CloseCalc()
CloseCalc = 1
WScript.Echo "CloseCalc()"
Dim WshShell : Set WshShell = CreateObject("WScript.Shell")
WScript.Echo "start calc"
WshShell.Run "calc"
WScript.Echo "waiting"
WScript.Sleep 5000
WScript.Echo "trying to close"
Dim strComputer : strComputer = "."
Dim objWMIService : Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Dim colProcessList : Set colProcessList = objWMIService.ExecQuery("SELECT * FROM Win32_Process Where Name = 'calc.exe'")
Dim objProcess
For Each objProcess In colProcessList
WScript.Echo "in loop"
WScript.Echo TypeName(objProcess)
objProcess.Terminate
Next
WScript.Echo "done"
CloseCalc = 0
End Function
' it's difficult to keep track of bad vars (undefined vars hidden by OERN)
Function BadVars()
BadVars = 1
Dim s1 : s1 = "Prefix"
On Error Resume Next
s2 = "Suffix"
WScript.Echo "s1:", s1
WScript.Echo "s2:", s2 ' statement/line skipped, because s2 can't be accessed
WScript.Echo "where did s2 output go?"
BadVars = 0
End Function
这样的脚本处理(短)函数中的不同主题/问题,这些函数将1(失败)或0(成功)返回到顶级代码(并从那里返回到OS)。通过重新订购或评论,您可以选择您当前正在处理的特殊功能/主题/问题。如果问题导致另一个问题,您可以添加一个函数,开发一个解决方案,测试它,然后返回到您启动的函数。
因为函数可能很简单,所以我们鼓励你使用局部变量并在使用前调暗它们;不需要有趣的名字。
Literals()函数从你的代码开始;我添加了日期文字,以演示如果你学到新东西,你可以如何重构/改进/增强功能。
CloseCalcBad() - 及其输出:
cscript 41169790.vbs
CloseCalcBad()
start calc
waiting
trying to close
in loop
done
显示OERN隐藏了未定义的" var"错误,跳过使用坏变量的语句/行(WScript.Echo TypeName(objProcess)
),但自豪地提供诊断输出,例如"已完成"。
CloseCalc()使用的变量变暗,因此关闭Calc - 输出:
cscript 41169790.vbs
CloseCalc()
start calc
waiting
trying to close
in loop
SWbemObjectEx <-- have something to terminate!
done
我包括BadVars() -
cscript 41169790.vbs
s1: Prefix
where did s2 output go?
显示邪恶的全球OERN而没有WMI的额外复杂性。