0

Suppose I am running an .vbs script to work with Excel sheet,now if somehow due to any reason any error occurs,I want to quit that .vbs script to run and besides to kill the process EXCEL.EXE from that .vbs file immedaitely.

After killing that process EXCEL.EXE, i want all the data change has been made by the script on the excel sheet should need to be ROLLBACK

Is it possible?

UPDATE:

I have a code with me, but how should I embed it with my script,I couldn't understand:

 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

SCRIPT

  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

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

TerminateCode

   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

thanks,

Community
  • 1
  • 1
arun_roy
  • 601
  • 6
  • 16
  • 42
  • 3
    As long as you haven't saved any of the changes you might have made to any files, this should be no problem. So, what have you tried, and what problems did you run into? – Tim Williams Dec 17 '12 at 17:30
  • Sometimes Scripts failed due to bad data,date formatting issues etc,and then scripts got failed with an pop up.But when I opened the **_Task Manager_**,seen that EXCEL.EXE process running.And everytime i need to go and kill that process manually.Thus I want it to be done from the script itself,whenever any error occurs. And also it would create a text file at run time,where the error detailed description should be written.The .text file should be in the Same folder where the Excel sheet will be placed. – arun_roy Dec 17 '12 at 17:37
  • 2
    So, **what have you tried**? http://mattgemmell.com/2008/12/08/what-have-you-tried/ – Tim Williams Dec 17 '12 at 17:44
  • Please see my update...and advice how would I use it in my code? – arun_roy Dec 17 '12 at 18:01
  • What does your script look like which is updating the Excel sheet? How is the sheet opened & updated? Showing that will give everyone a better idea how to answer your question. – PaulStock Dec 17 '12 at 18:37
  • The sheet is being Opend by VBScript and then their time calcualtions,new columns addition,deletion etc is being performed by several scripts on the same sheet,one at a time.I am giving you here as an reference above. – arun_roy Dec 17 '12 at 18:42
  • your code snippet loops through the current processes running on your system and names them. All you need is a line that terminates the `EXCEL.EXE` process. [This](http://msdn.microsoft.com/en-us/library/windows/desktop/aa394372(v=vs.85).aspx#methods) may help ... – Scott Holtzman Dec 17 '12 at 18:43
  • But here i need to give the script Computer name,userID,password,Domain etc. - Anyway Can we bypass such thing to terminate the desired process? Because my script will run over lots of people machines at any time as per their needs.So such UID/paas etc are impossible to collect. Please advice me how to do so? – arun_roy Dec 17 '12 at 18:58
  • Please tell me Paul,How to do that? – arun_roy Dec 17 '12 at 19:06
  • @ScottHoltzman please update me,can we ignore "Computer name,userID,password,Domain" to use this process? – arun_roy Dec 17 '12 at 19:24
  • This link http://www.vbaexpress.com/kb/getarticle.php?kb_id=811 shows how to terminate local processes by name. The snip you posted seems to be for killing processes on remote machines. The code at the link can easily be adapted for vbscript. – Tim Williams Dec 17 '12 at 19:35
  • Thanks Tim, I want to kill the process on Error,from the script.In such a case how to call this terminate process,whenever any error occur within the respective .vbs file? – arun_roy Dec 17 '12 at 19:43
  • 2
    I just killed notepad from the script based on your first script above ... `For each Process in objService.Instanceof("win32_process") If process.name = "notepad.exe" Then process.terminate() ... ` To put this into an Error statement, see [vbscript error handling](http://stackoverflow.com/questions/157747/vbscript-using-error-handling) – Scott Holtzman Dec 17 '12 at 19:44
  • But within the terminate process,we should need to pass the process ID,right? or call that method within empty paranthesis will be enough? – arun_roy Dec 17 '12 at 19:49
  • One last question is, where should I put such error statement,Is it the last block on my VBScript? – arun_roy Dec 17 '12 at 19:58
  • @ScottHoltzman there is an open question to you,according to your code,you are killing EXCEL.EXE process.That's pretty clear.But if there are multiple Excel.exe,the how would I recognize which one is opened by the script? – arun_roy Dec 18 '12 at 19:29
  • http://stackoverflow.com/questions/10614492/create-instance-for-a-classresides-in-b-vbs-from-another-vbs-file?rq=1 – arun_roy Dec 27 '12 at 04:20

2 Answers2

3

The comments show that it's a bad idea to use WMI to kill the zombie Excel.exe left over from a aborted script. The correct way is to tame VBScript's horrible error handling by putting a OERN..OEG0 around a function that contains your former top-level code:

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  

output of three runs:

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

If you open the task manager and check the sheet from time to time with Excel, you'll see that

  1. there won't be Excel.exe zombies (execpt if you use a debugger)
  2. the .xls won't be changed in case of errors

See here for a little bit of background wrt the code structure/layout/Main() function.

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

The WScript.Quit in the error handling If block will stop the script in case of this error. But consider: All other unchecked errors will stay hidden and won't abort the program, and each check will cost you about 5 lines of boilerplate code.

miken32
  • 42,008
  • 16
  • 111
  • 154
Ekkehard.Horner
  • 38,498
  • 2
  • 45
  • 96
2

Basically, how I work with Excel is to call xl.Quit() in an error handler. To make sure that no changes are saved to the book, use book.Saved = true beforehand. This prevents Excel complaining about opened workbooks that have been changed

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
  • According to you,I think its a good practice as other method then would kill all the Other `EXCEL.EXE` process which are not running and opened by the script. right? – arun_roy Dec 19 '12 at 16:09
  • Can you vote up my post if you think this discussion really heakthy for others also? :-) – arun_roy Dec 19 '12 at 16:10
  • I'm not sure - you may want to test whether `xl.Quit()` kills only the current Excel process or all Excel processes. I can't test at the moment as I'm using Linux. –  Dec 19 '12 at 16:27
  • @oraclecertifiedprofessional -1 for proposing a really dangerous mal practice. – Ekkehard.Horner Dec 19 '12 at 16:55
  • @oraclecertifiedprofessional I understood what tried to describe!your excel would quit only the excel.exe process that has been opened by the respective script,not the others.Its good! thanks – arun_roy Dec 19 '12 at 17:40
  • sorry everybody, I missed a `Quit` line; of course the Excel objects would be invalid after the call to `SbCleanUp()`. Downvote earned! –  Dec 20 '12 at 19:06