Installing Packages Automatically

by John Loomes

This script is in effect a 'poor mans SMS' in such that it allows you to distribute a packaged application, produced say, with SMS Installer, to a number of target machines. The Command Scheduler is then employed to kick off the package after a predetermined time period. This script checks the status of the Command Scheduler before and after the job to ensure that the service is not left running on a machine on which it was previously stopped, or not stopped or a machine on which it was previously started.

This script is in effect a 'poor mans SMS' in such that it allows you to distribute a packaged application, produced say, with SMS Installer, to a number of target machines. The Command Scheduler is then employed to kick off the package after a predetermined time period.

This is a somewhat crude replacement for the Package Distribution part of SMS, and doesn't provide much in the way of status reporting or error checking. But if you don't use SMS at your site and want to get a patch out to a large number of machines in a short period of time, then this is going to be much quicker than sending and engineer out with a CD!

This script requires WSH and ADSI to be installed on the machine running it, it will also need to run under and account with Administrator rights over all the target machines.

It contains quite a few usefull code snippets you might want to use elsewhere, such as querying NT Services on Remote Machines, writing to log files, asking for user input etc etc.

Continue on any runtime errors (comment this line out whilst troubleshooting)

On Error Resume Next

Setup all the main variables to be used in the script, Ive allocated an array large enough for 1000 machines, expand/reduce this as necessary

Dim strServerName(1000)

Dim ErrMsg

Dim StrGroupToAdd

Dim strServer

Dim Result

Dim strInputFile

Dim LogFile

Dim strLocalGroup

Dim szPathtoexe

Dim szSMSexe

Dim iPathLen, iExeLen

Create a new File System Object so we can start working with the various control files the script uses

Set objFS = CreateObject("Scripting.FileSystemObject")

Prompt the user of a file containing a list of machines to send the package to. This section could be modified to pull this list from a spreadsheet, or an SQL database even

strInputFile = InputBox("Enter name of file containing machines to modify (Including full path)",,"TestServer.Txt")

Check that the file supplied exists by trying to open it, if we find any errors here then quit the script.

Set ServerList = objFS.OpenTextFile (strInputFile)

If strInputFile = "" Then

MsgBox ("Operation Cancelled, no input file supplied")


ElseIf Err Then

ErrMsg = AdsiErr(strInputFile)

MsgBox ("Error: "& ErrMsg)


End if

Ask the user for the name/path of a file to log the results of the script to. Again, check that the file exists and can be written to. If any error occur, then quit the script.

LogFile = InputBox("Enter name of Installation Package (Including full path)",,"H:\log.txt")

If LogFile = "" Then

MsgBox ("Operation Cancelled, no log file supplied")


End if

ErrMsg = "Logging Started"

Result = WriteLog(,LogFile,ErrMsg)

If Err Then

    ErrMsg = AdsiErr(LogFile)

    MsgBox ("Error: " & ErrMsg)


End if

Ask the user for the Path/Name of the package to be distributed, this should be a single .exe file that requires no user intervention when launched. Check that the file exists, quit if any errors are found.

szPathtoexe = InputBox("Enter name of Log File (Including full path)",,"\\eulon-appw1\swlibrary$\")

If szPathtoexe = "" Then

MsgBox ("Operation Cancelled, no Executable file supplied")


End if

If Err Then

ErrMsg = AdsiErr(LogFile)

MsgBox ("Error: " & ErrMsg)


End if

Separate the actual name of the .exe from the rest of the path

iPathLen = Len(szPathtoexe)

iExeLen = iPathLen - InstrRev(szPathtoexe,"\")

szSMSexe = Right(szPathtoexe,iExeLen)

Extract the machine names from the input file supplied earlier, copy the .exe to each machine and call the routine to schedule the installation (LAUNCHINSTALL(StrServer)). Attempt to trap any errors, and pass the results to the log file supplied earlier.

do while ServerList.AtEndOfStream <> True

strServerName(xCounter) = ServerList.ReadLine

If not Isblank(strServerName(xCounter)) then

StrServer = StrServerName(xCounter)

' Reset Errors

Err = ""

ErrMsg = ""

' setup the installation on this server

Result = LaunchInstall(strServer)

' If not successfully then try to find out why

If Err Then

    ErrMsg = AdsiErr(strServerName(xCounter))


    ErrMsg = strServerName(xCounter) & " has been updated successfully"

end if

' Write results to the log

Result = WriteLog(strServerName(xCounter),LogFile,ErrMsg)

xCounter = xCounter + 1

End if


This function is used to trim leading and trailing spaces from the machine names in the input file.

Function IsBlank(strInput)

    IsBlank = not CBool(Len(trim(strInput)))

End Function

This function writes the results of each installation attempt to a log file supplied by the user.

Function WriteLog(ServerName,strLogFile,strMsg)

Dim strTextStream

Set strTextStream = objFS.OpenTextFile(strLogFile, 8, true)


strTextStream.WriteLine("Time: " & Time)

strTextStream.WriteLine("Date: " & Date)



End Function

This function compares any errors to a list of known error codes, and then uses this information to write more meaningful error messages to the log file.

Function AdsiErr(ServerName)

Dim e

If Err.Number = &H80070562 Then

    AdsiErr = ServerName & " has already been updated."

ElseIf Err.Number = &H80070005 Then

    AdsiErr = "Access Denied to " & ServerName

ElseIf Err.Number = &H1A8 Then

    AdsiErr = "Couldnt Connect to " & ServerName

ElseIf Err.Number = &H800708B2 Then

    AdsiErr = ServerName & " is a Domain Controller, cant update"

ElseIf Err.Number = &H8007056B Then

    AdsiErr = "Group " & ServerName & " Doesnt Exist"

ElseIf Err.Number = 53 Then

    AdsiErr = "File " & ServerName & " Doesnt Exist"

ElseIf Err.Number = 70 Then

    AdsiErr = "Cant Write to " & ServerName


    e = Hex(Err.Number)

AdsiErr = "Unexpected Error on " & ServerName

End If

End Function

This function handles the distribution of the package to the server(s) in the input file. It also controls the Command Schedule Service on the remote machines.

Function LaunchInstall(strServer)

    Dim RunTime, Comp, svc, fso

    Set fso = CreateObject("Scripting.FileSystemObject")

        Copy the SMSInstaller .exe to the root of C: on the machine

    fso.CopyFile szPathtoexe, "\\"&StrServer&"\c$\"

         Use ADSI to query the ADSI accessible objects on the remote server

   Set Comp = GetObject("WinNT://DOMAIN/" & strServer & ",Computer") Set Shell=wscript.createobject("wscript.shell")

Filter out all the NT Services from the list of objects on the remote machine

Comp.Filter = Array("Service")

For Each svc in Comp

Query the Command Scheduler Service. If the service is currently stopped, then start it.

If svc.Name = "Schedule" AND svc.Status = "1" Then


If we started the service up, then add a scheduled command to stop the service again in 6 minutes time.

RunTime = Time + (6/1440)

      Shell.Run "cmd /c at \\"&strServer&" "&RunTime&" net stop Schedule",0 ,false

     end if


Set Comp = Nothing

RunTime = Time + (2/1440)

Now add a scheduled command to run the SMSInstaller .exe silently (/S) in 2 minutes time.

Shell.Run "cmd /c at \\"&strServer&" "&RunTime&" c:\"&szSMSexe&" /s",0 ,false

Add another scheduled command to delete the SMSInstaller .exe in 4 minutes.

This assumes that the install will only take 2 minutes maximum to complete. For larger packages, increase this time accordingly.

RunTime = Time + (4/1440)

Shell.Run "cmd /c at \\"&strServer&" "&RunTime&" cmd.exe /c del c:\"&szSMSexe,0 ,false

Set Shell = Nothing

End Function

As I said at the beginning, some aspects of this script are somewhat 'crude' and could do with improvement - such as using a simply time delay to determine when the source files should be removed from the target machine, for example. I didn't spend any more time making this more elaborate because I wanted a quick solution to the problem. And it works! We sucessfully rolled out backup software agents to several hundred NT4 servers using this very script, and it only took about half and hour!

Some of you might want to improve on this script to include better error checking and reporting.

Please let me know how you get on! And if you've any suggestions for features you think would be useful additions to this, then let me know too! But bear in mind that this script isn't intended to replace SMS, that would be a pointless 'reinventing the wheel' exercise.

This article was originally published on Jun 15, 2000
Page 1 of 1

Thanks for your registration, follow us on our social networks to keep up-to-date