' File Name: deployEXE.VBS
' Script Name: deployEXE.VBS
' Created: 2008.03.12
' Author: Rob Durkin, STuladhar, Talen
' E-mail:
' ------------------------------------------------------------------------------
' ARGUMENTS :
' None
' ------------------------------------------------------------------------------
' ------------------------------------------------------------------------------
' PURPOSE :
' Runs an executable on a remote workstation from a network share and logs the
' result to an Excel spreadsheet.
' - The main script will copy the EXE file and one other VBS script to the
' target machine.
' - The main script will execute SOON.EXE (available via download from
' Microsoft) to schedule the second VBS script on the target machine.
' - The second script will execute the EXE and make an entry in the
' application log based on success or failure.
' - The main script will then follow up and parse through the application log
' and check the result of the EXE.
' * NOTE: Excel must be installed on the workstation the script is run from.
' ------------------------------------------------------------------------------
'
' ------------------------------------------------------------------------------
' REVISION HISTORY :
' Date: 2008.03.28
' Time:
' Issue: Needed error handling in the event of unreachable workstations or
' other issues that would cause a workstation not to respond.
' Solution: Added workstation availability checks using ping as well as an On
' Error trap around the call to the Functions using WMI queries.
'
' ------------------------------------------------------------------------------
Option Explicit
' ------------------------------------------------------------------------------
' FUNCTION LISTINGS
' ------------------------------------------------------------------------------
' Function: getInstallStatus
' Created: 2007.12.26
' Author: STuladhar
' Arguments: strSuccess & strFailed, defined in verifyInstall subroutine.
' ------------------------------------------------------------------------------
' Purpose:
' Checks the installation status in the remote workstation Application log.
' ------------------------------------------------------------------------------
Function getInstallStatus(strSuccess, strFailed, strComputer)
Dim intCount, intFailed
intCount = getEventLogCount(strSuccess, strComputer)
If intCount > 0 Then
getInstallStatus = "P"
Else
intFailed = getEventLogCount(strFailed, strComputer)
If intFailed > 0 Then
getInstallStatus = "F"
Else
getInstallStatus = "U"
End If
End If
End Function
' ------------------------------------------------------------------------------
' Function: getEventLogCount
' Created: 2007.12.26
' Author: STuladhar
' Arguments: strWQL, success or failure WQL defined in verifyInstall subroutine.
' ------------------------------------------------------------------------------
' Purpose:
' Counts the number of events in an event log matching specific criteria
' defined via WQL query (see subVerifyInstall).
' ------------------------------------------------------------------------------
Function getEventLogCount(strWQL, strComputer)
Dim colLoggedEvents
Dim objWMISvc
Set objWMISvc = GetObject("winmgmts:" & "{(Security)}\\" & strComputer & _
"\root\cimv2")
Set colLoggedEvents = objWMISvc.ExecQuery(strWQL)
getEventLogCount = colLoggedEvents.Count
End Function
' ------------------------------------------------------------------------------
' Function: getEventLogMsg
' Created: 2007.12.26
' Author: STuladhar
' Arguments: strWQL, success or failure WQL defined in verifyInstall subroutine.
' ------------------------------------------------------------------------------
' Purpose:
' Collects the event log descriptions for each event log entry collected
' according to the WQL query in Function getEventLogCount.
' ------------------------------------------------------------------------------
Function getEventLogMsg(strWQL, strComputer)
Dim colLoggedEvents
Dim objEvent, objWMISvc
Dim strMsg
Set objWMISvc = GetObject("winmgmts:" & "{(Security)}\\" & strComputer & _
"\root\cimv2")
Set colLoggedEvents = objWMISvc.ExecQuery(strWQL)
For Each objEvent In colLoggedEvents
strMsg = strMsg & chr(13) & objEvent.Message
Next
' This is the length of the event log description. Change the length as
' necessary (the event log descriptions are defined in runEXE.VBS)
' *** CHANGE TO SUIT NEEDS AS NECESSARY ***
getEventLogMsg = Left(strMsg, 255)
End Function
' ==============================================================================
' SCRIPT BODY
' ==============================================================================
Dim a, b, DD, MM, YYYY, vDy, vMo
Dim errReturn, FileName, intProcessID
Dim strExcelFile, strCmd, strComputer, strDest01, strDest02, strFile01
Dim strFile02, strList, strPing, strText, strVBS, strWkstn
Dim objExcel, objExecObject, objFileCopy, objFSO, objSheet, objShell, objTxtFile
Const ForReading = 1, ForWriting = 2, ForAppending = 8
' Bind to the file system object
Set objFSO = CreateObject("Scripting.FileSystemObject")
' Bind to the shell object
Set objShell = CreateObject("WScript.Shell")
' Call the subroutines in the correct order (they're listed in alphabetical
' in the script body)
subGetDate
subCreateExcelWorkbook
subMain
' Pause the script for two and a half minutes (unnecessary if deploying to a
' large number of workstations)
WScript.Echo "Pausing script for 2 minutes and 30 seconds at " & Now
WScript.Sleep 150000
subVerifyInstall
subCleanUp
Sub subCleanUp
WScript.Echo "Beginning clean up..."
' Save the spreadsheet and close the workbook
objExcel.ActiveWorkbook.SaveAs strExcelFile
objExcel.ActiveWorkbook.Close
objExcel.Application.Quit
WScript.Echo "Clean up and script complete."
End Sub
Sub subCreateExcelWorkbook
' Define the filename for the Excel file, change to .XLSX if using Excel 2007
strExcelFile = YYYY & vMo & vDy & "deployEXE.XLS"
' Bind to the Excel application object
Set objExcel = CreateObject("Excel.Application")
' If Excel not found, exit script
If (Err.Number <> 0) Then
WScript.Echo "Excel application not found."
WScript.Quit
End If
' Create a new workbook
objExcel.Workbooks.Add
' Bind to and name the first worksheet in the workbook
Set objSheet = objExcel.ActiveWorkbook.Worksheets(1)
' *** CHANGE TO SUIT NEEDS AS NECESSARY ***
objSheet.Name = "Worksheet Name"
' Populate spreadsheet cells (column headings) with user-defined attributes
' *** CHANGE TO SUIT NEEDS AS NECESSARY ***
objSheet.Cells(1, 1).Value = "Target Computer"
objSheet.Cells(1, 2).Value = "Time"
objSheet.Cells(1, 3).Value = "Ping"
objSheet.Cells(1, 4).Value = "SOON Execution"
objSheet.Cells(1, 5).Value = "Utility Execution"
End Sub
' This subroutine gets the year, month and day for the purposes of building the
' Excel filename in the subroutine subCreateExcelWorkbook
Sub subGetDate
YYYY = Year(Now)
MM = Month(Now)
DD = Day(Now)
If MM < 10 Then
vMo = "0" & MM
Else
vMo = MM
End If
If DD < 10 Then
vDy = "0" & DD
Else
vDy = DD
End If
End Sub
Sub subMain
WScript.Echo "Deploying software..."
' Variable containing UNC path to workstation list text file
' *** CHANGE TO SUIT NEEDS AS NECESSARY ***
strList = "\\SERVER\Share" & _
"\workstationList.TXT"
' Variable containing UNC path to executable that needs to be copied to
' remote machine
' *** CHANGE TO SUIT NEEDS AS NECESSARY ***
strFile01 = "\\SERVER\Share" & _
"\Utility.EXE"
' Variable containing UNC path to script that needs to be copied to remote
' machine
' *** CHANGE TO SUIT NEEDS AS NECESSARY ***
strFile02 = "\\SERVER\Share" & _
"\runEXE.VBS"
' Variable containing script that will launch executable on remote machine
strVBS = "runEXE.VBS"
' Open the text file containing the list of workstation names for reading
Set objTxtFile = objFSO.OpenTextFile(strList, ForReading)
' Set the Excel row variable to start on the second row
a = 2
' Begin looping through workstations
Do Until objTxtFile.AtEndOfStream
' Get machine name from text file (and remove any whitespaces)
strWkstn = Trim(objTxtFile.ReadLine())
' Ping the workstation, skipping it if it is unreachable on the network
strPing = "%comspec% /c ping -n 3 -w 1000 " & strWkstn & ""
Set objExecObject = objShell.Exec(strPing)
Do While Not objExecObject.StdOut.AtEndOfStream
strText = objExecObject.StdOut.ReadAll()
If InStr(strText, "Reply") > 0 Then
WScript.Echo "Starting on " & strWkstn & "..."
' UNC path to destination where executable and script needs to be
' copied to on the remote machine
' *** CHANGE TO SUIT NEEDS AS NECESSARY ***
strDest01 = "\\" & strWkstn & "\C$" & _
"\Utility.EXE"
strDest02 = "\\" & strWkstn & "\C$" & _
"\runEXE.VBS"
' Copy the executable package to the target PC
Set objFileCopy = objFSO.GetFile(strFile01)
objFileCopy.Copy(strDest01), True
' Copy the VBScript to the target PC
Set objFileCopy = objFSO.GetFile(strFile02)
objFileCopy.Copy(strDest02), True
' Variable to hold the construction of the SOON command
' *** CHANGE TO SUIT NEEDS AS NECESSARY ***
strCmd = """\\SERVER\Share\SOON.EXE"" \\" & _
strWkstn & " 120 ""cscript C:\" & strVBS & """"
' Variable to hold the error return code of the SOON command
errReturn = objShell.Run(strCmd)
' Time stamp the spreadsheet
objSheet.Cells(a, 2).Value = Now
' Evaluate the error return code of the SOON command and write
' results to Excel spreadsheet
If errReturn = 0 Then
objSheet.Cells(a, 1).Value = strWkstn
objSheet.Cells(a, 4).Value = "Success"
Else
objSheet.Cells(a, 1).Value = strWkstn
objSheet.Cells(a, 4).Value = "Failure"
End If
Else
WScript.Echo vbTab & strWkstn & " unreachable on network."
objSheet.Cells(a, 1).Value = strWkstn
objSheet.Cells(a, 2).Value = Now
objSheet.Cells(a, 3).Value = "Unreachable on network."
objSheet.Cells(a, 4).Value = "Failure"
End If
Loop
' Increment the Excel row variable to move to the next row down
a = a + 1
Loop
' Close the text file
objTxtFile.Close
WScript.Echo "Deployment complete."
End Sub
Sub subVerifyInstall
WScript.Echo "Verifying execution..."
Dim strEvtMsg, strFailed, strStatus, strSource, strSuccess
Dim intEvtCode01, intEvtCode02
' Define the Source being looked for in the Application log
' *** CHANGE TO SUIT NEEDS AS NECESSARY ***
strSource = "Utility"
' Define the Event IDs being looked for in the Application log
' *** CHANGE TO SUIT NEEDS AS NECESSARY ***
intEvtCode01 = 990 ' Success
intEvtCode02 = 991 ' Failure
' WQL query definition to look for any entries from a specific source with a
' specific event code
strFailed = "Select * From Win32_NTLogEvent Where Logfile = 'Application'" _
& " and SourceName = '" & strSource & "' and EventCode = " & intEvtCode02
strSuccess = "Select * From Win32_NTLogEvent Where Logfile = 'Application'" _
& " and SourceName = '" & strSource & "' and EventCode = " & intEvtCode01
' Set the Excel row variable to start on the second row
b = 2
Do While objSheet.Cells(b, 1).Value <> ""
strComputer = objSheet.Cells(b, 1).Value
' Ping the workstation, skipping it if it is unreachable on the network
strPing = "%comspec% /c ping -n 3 -w 1000 " & strComputer & ""
Set objExecObject = objShell.Exec(strPing)
Do While Not objExecObject.StdOut.AtEndOfStream
strText = objExecObject.StdOut.ReadAll()
If InStr(strText, "Reply") > 0 Then
' Parse the application log based upon the value of the cell in the
' fourth column of the spreadsheet
Select Case objSheet.Cells(b, 4).Value
Case "Success"
WScript.Echo "Verifying execution on " & strComputer & "..."
On Error Resume Next
strStatus = getInstallStatus _
(strSuccess, strFailed, strComputer)
If strStatus = "F" Then
strEvtMsg = getEventLogMsg(strFailed, strComputer)
'objSheet.Cells(b, 5).Value = strEvtMsg
Else
strEvtMsg = getEventLogMsg(strSuccess, strComputer)
'objSheet.Cells(b, 5).Value = strEvtMsg
End If
objSheet.Cells(b, 5).Value = strEvtMsg
On Error Goto 0
Case Else
End Select
Else
WScript.Echo vbTab & strComputer & " unreachable on network."
End If
Loop
b = b + 1
Loop
WScript.Echo "Verification complete."
End Sub
' ==============================================================================
' END OF SCRIPT: deployEXE.VBS
' ==============================================================================