VBScript关闭应用程序不起作用

时间:2016-12-15 17:14:21

标签: vbscript

我目前正在学习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

1 个答案:

答案 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的额外复杂性。