0

假设我正在运行一个 .vbs 脚本来处理 Excel 工作表,现在如果由于某种原因发生任何错误,我想退出该 .vbs 脚本以运行,并且立即从该 .vbs 文件中终止进程 EXCEL.EXE .

杀死该进程 EXCEL.EXE 后,我希望所有数据更改都由 excel 表上的脚本进行,应该需要回滚

可能吗?

更新:

我有一个代码,但我应该如何将它嵌入到我的脚本中,我不明白:

 Option Explicit
 Dim objService,Process
 set objService = getobject("winmgmts:")

 for each Process in objService.InstancesOf("Win32_process")
  WScript.echo Process.Name & vbTab & Process.processid
 Next

脚本

  Option Explicit



  Set objExcel1 = CreateObject("Excel.Application")'Object for Condition Dump

  strPathExcel1 = "D:\VB\Copy of Original Scripts\CopyofGEWingtoWing_latest_dump_21112012.xls"
  objExcel1.Workbooks.open strPathExcel1
  Set objSheet1 = objExcel1.ActiveWorkbook.Worksheets(1)
  Set objSheet2 = objExcel1.ActiveWorkbook.Worksheets("Bad Data")

 objExcel1.ScreenUpdating = False
 objExcel1.Calculation = -4135  'xlCalculationManual

 IntRow2=2
 IntRow1=4
  Do Until IntRow1 > objSheet1.UsedRange.Rows.Count

  ColStart = objExcel1.Application.WorksheetFunction.Match("Parent Business Process ID", objSheet1.Rows(3), 0) + 1 

Do Until ColStart > objSheet1.UsedRange.Columns.Count And objSheet1.Cells(IntRow1,ColStart) = ""

    If objSheet1.Cells(IntRow1,ColStart + 1) > objSheet1.Cells(IntRow1,ColStart + 5) And objSheet1.Cells(IntRow1,ColStart + 5) <> "" Then

    objSheet1.Range(objSheet1.Cells(IntRow1,1),objSheet1.Cells(IntRow1,objSheet1.UsedRange.Columns.Count)).Copy
    objSheet2.Range(objSheet2.Cells(IntRow2,1),objSheet2.Cells(IntRow2,objSheet1.UsedRange.Columns.Count)).PasteSpecial
    IntRow2=IntRow2+1
    Exit Do

    End If

ColStart=ColStart+4
Loop

IntRow1=IntRow1+1
Loop

objExcel1.ScreenUpdating = True
objExcel1.Calculation = -4105   'xlCalculationAutomatic

'=======================
objExcel1.ActiveWorkbook.SaveAs strPathExcel1
objExcel1.Workbooks.close
objExcel1.Application.Quit

'=======================

终止代码

   strComputer = "FullComputerName" 
   strDomain = "DOMAIN" 
   strUser = InputBox("Enter user name") 
   strPassword = InputBox("Enter password") 
   Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator") 
   Set objWMIService = objSWbemLocator.ConnectServer(strComputer, _ 
   "root\CIMV2", _ 
   strUser, _ 
   strPassword, _ 
   "MS_409", _ 
   "ntlmdomain:" + strDomain) 
   Set colProcessList = objWMIService.ExecQuery _
   ("SELECT * FROM Win32_Process WHERE Name = 'notepad.exe'")
 For Each objProcess in colProcessList
  objProcess.Terminate()
 Next

谢谢,

4

2 回答 2

3

评论表明,使用 WMI 杀死从已终止脚本中遗留下来的僵尸 Excel.exe 是一个坏主意。正确的方法是通过在包含您以前的顶级代码的函数周围放置 OERN..OEG0 来驯服 VBScript 可怕的错误处理:

Option Explicit

Dim goFS    : Set goFS    = CreateObject("Scripting.FileSystemObject")
Dim goWAN   : Set goWAN   = WScript.Arguments.Named
Dim goExcel : Set goExcel = Nothing
Dim goWBook : Set goWBook = Nothing
Dim gnRet   : gnRet       = 1
Dim gaErr   : gaErr       = Array(0, "", "")

On Error Resume Next
gnRet = Main()
gaErr = Array(Err.Number, Err.Source, Err.Description)
On Error GoTo 0
If 0 = gaErr(0) Then
   If goWBook Is Nothing Then
      WScript.Echo "surprise: no oWBook, won't save"
   Else
      WScript.Echo "will save"
      goWBook.Save
   End If
Else
   WScript.Echo Join(gaErr, " - ")
   If goWBook Is Nothing Then
      WScript.Echo "surprise: no oWBook, won't close"
   Else
      WScript.Echo "will close False"
      goWBook.Close False
   End If
End If
If goExcel Is Nothing Then
   WScript.Echo "surprise: no oExcel, won't quit"
else
   WScript.Echo "will quit"
   goExcel.Quit
End If
WScript.Quit gnRet

Function Main()
  Main = 1
  If goWAN.Exists("alpha") Then Err.Raise vbObjectError + 2, "Main()", "before CO(Excel)"
  Set goExcel = CreateObject("Excel.Application")
  Set goWBook = goExcel.Workbooks.Open(goFS.GetAbsolutePathName("..\data\savexcel.xls"))
  Dim oRngA1 : Set oRngA1 = goWBook.Worksheets(1).Range("$A1")
  oRngA1.Value = oRngA1.Value + 1
  Dim oRngA2 : Set oRngA2 = goWBook.Worksheets(1).Range("$A2")
  If goWAN.Exists("beta") Then
     oRngA2.Value = oRngA1.Value / 0
  Else
     oRngA2.Value = oRngA1.Value / 2
  End If
  Main = 0
End Function ' Main  

三个运行的输出:

cscript savexcel.vbs
will save
will quit

cscript savexcel.vbs /alpha
-2147221502 - Main() - before CO(Excel)
surprise: no oWBook, won't close
surprise: no oExcel, won't quit

cscript savexcel.vbs /beta
11 - Microsoft VBScript runtime error - Division by zero
will close False
will quit

如果您打开任务管理器并不时使用 Excel 检查工作表,您会看到

  1. 不会有 Excel.exe 僵尸(如果您使用调试器则执行)
  2. 如果出现错误,.xls 不会更改

有关代码结构/布局/Main() 函数的一些背景信息,请参见此处。

更新 - 解释我对@oracle 回答的反对票:

option explicit
--  A must
on error resume next
--  Global OERN - a short way to desaster

dim xl: set xl = CreateObject("Excel.Application")
--  Unchecked - script will continue, even if "ActiveX component can't create object"

dim book: set book = xl.WorkBooks.Open("...")
--  Unchecked - script will continue, even if "File not found"

' manipulate book etc
' whenever there is a chance of error, or at the end of the script
' check the err object and clean up if necessary

book.worksheets(1).range("whatever") = interesting computation which fails
if err.Number <> 0 then
    SbCleanUp xl
    WScript.echo err.Description
    err.clear
--  SbCleanUp has quit Excel!
end if

-- now repeat those lines for each action you think of as risky
-- (and forget it for all those actions which really are dangerous)

' update changes, close Excel
book.Save
--  How? SbCleanUp has quit Excel!
--  What about error checking? Forgot it? Can't be bothered?

SbCleanUp xl
--  Why? SbCleanUp has quit Excel!

--  As we have no indication of trouble, let's
--  save the data based on wrong computations
--  in a .txt file and delete the .xls we don't
--  need anymore.
--- **OOOPS**

Sub SbCleanUp(byref xl)
    if not (xl Is Nothing) then
        dim book
        for each book in xl.WorkBooks
            book.Saved = true
        next 'book
        xl.Quit
    end if
End Sub

更新二:

我撤销了对@oracle 答案的反对票,因为错误处理 If 块中的 WScript.Quit 将在出现错误时停止脚本。但请考虑:所有其他未检查的错误将保持隐藏并且不会中止程序,并且每次检查将花费您大约 5 行样板代码。

于 2012-12-17T20:34:46.683 回答
2

基本上,我使用 Excel 的方式是调用xl.Quit()错误处理程序。要确保没有更改保存到书中,请book.Saved = true预先使用。这可以防止 Excel 抱怨打开的工作簿已更改

option explicit
on error resume next

dim xl: set xl = CreateObject("Excel.Application") 

dim book: set book = xl.WorkBooks.Open("...")
' manipulate book etc
' whenever there is a chance of error, or at the end of the script
' check the err object and clean up if necessary
if err.Number <> 0 then
    SbCleanUp xl
    WScript.echo err.Description
    err.clear
    WScript.Quit 1
end if

' update changes, close Excel
book.Save
SbCleanUp xl

Sub SbCleanUp(byref xl)
    if not (xl Is Nothing) then
        dim book
        for each book in xl.WorkBooks
            book.Saved = true
        next 'book
        xl.Quit
    end if
End Sub
于 2012-12-19T16:01:50.490 回答