'AltNSClientPush.vbs. v1.2.5 1/11/2011 Joe VanHollebeke ' Used to install the NS client to machines that are not in a domain or in an untrusted domain that do not have the ability to resolve the NS server name. ' This script was designed for use on Altiris Notification Server 6.x. It has not been tested on 7.x. ' ' This script requires the following files to reside in the same directory ' - machines.txt text file with list of machine names or IP addresses to deploy the agent to. One item per line. ' - psexec.exe Sysinternals tool used to remotely execute commands. Available as free download from Microsoft. ' ' Basic instructions: ' - Modify the =-= Script variables -=-= section (~line 103 of this script) and enter the appropriate account and NS information ' - Decide if you want an entry added to the client HOSTS file. If not, be sure to comment out the command that adds this (~line 166) ' - Be sure to run this script in a location where additional files can be generated. Additional files that will be generated include: ' + a detailed LOG file ' + a list of machines where the agent install failed ' + a backup list of machines that were attempted. ' - REM out all Msgbox lines and the final command to launch notepad if you plan to run this script via a schedule. it works well this way ' because machines are automaticlaly removed from machines.txt when the agent is installed succesfully. ' Allow script to handle errors On Error Resume Next If GetScriptAlreadyRunning Then Msgbox "Another instance of this script is already running. Terminated.",16,"ERROR" Wscript.quit End If ' ### DECLARE VARIABLES ### Dim strWorkDir ' holds the working directory Dim strLogFile ' holds named of log file to use Dim objWshShell ' used for working with windows script host shell object Dim objFso ' used for working with FileSystemObject object ' ### DEFINE PRIMARY WORKER OBJECTS ### Set objWshShell = CreateObject("WScript.Shell") Set objFso = CreateObject("Scripting.FileSystemObject") Set objNetwork = CreateObject("WScript.Network") ' ### DEFINE PRIMARY WORKING VARIABLES ### strWorkDir = GetEnvironVar("[SCRIPTDIR]") 'Log file path and name matches the Script path and name with a .log extension strLogFile = Left(WScript.ScriptFullName, Len(WScript.ScriptFullName)-4) & ".log" strTrackingKey = "" strMachineListFile="machines.txt" strFailureListFile="failed.txt" ' Initialize the log file with starting message Call WriteLogFile(strLogFile, "---------- Start of " & WScript.ScriptName & " execution. ----------") 'Check for machine list file If NOT objFSO.FileExists(strMachineListFile) Then Call WriteLogFile(strLogFile, "ERROR: File '" & strMachineListFile & "' not Found.") Msgbox "ERROR: File '" & strMachineListFile & "' not Found.",16,"ERROR" Wscript.Quit(1) End If Set objMachineListFile = objFSO.OpenTextFile(strMachineListFile, 1, False, -2) 'Read list of machines into an array intMachineCount=0 do while objMachineListFile.atendofstream <> true 'Remove Spaces strLine = Replace(objMachineListFile.ReadLine," ","") If strLine <> "" Then 'skip blank lines ReDim Preserve arrMachineList(intMachineCount) arrMachineList(intMachineCount)=LCase(strLine) intMachineCount=intMachineCount+1 End If loop objMachineListFile.close Call WriteLogFile(strLogFile, "Read list of " & intMachineCount & " computers from '" & strMachineListFile & "'") 'If no machines in the list, nothing to do If intMachineCount = 0 Then Call WriteLogFile(strLogFile, "No Work to do") Call WriteLogFile(strLogFile, "---------- End of " & WScript.ScriptName & " execution. ----------") Wscript.quit End If 'determine a file name to store backup copies of machine list and error file intFileCounter = 1 Do strFileParts = split(strMachineListFile,".") strMachineListFileNew = strFileParts(0) & "_" & intFileCounter & "." & strFileParts(1) If objFSO.FileExists(strMachineListFileNew) = False Then 'found an available name, rename the machine list file to the new name Call WriteLogFile(strLogFile, "Saving Machine list as: " & strMachineListFileNew) objFSO.MoveFile strMachineListFile, strMachineListFileNew 'Create a new blank file to avoid error next run if no machines are added automatically Call AddLineToFile("", strMachineListFile, strLogFile) 'construct a new failure list file name using the same number strFileParts = split(strFailureListFile,".") strFailureListFile = strFileParts(0) & "_" & intFileCounter & "." & strFileParts(1) Call WriteLogFile(strLogFile, "Saving Error list as: " & strFailureListFile) Exit Do End If intFileCounter = intFileCounter + 1 loop until intFileCounter > 10000 'max loops If intFileCounter > 10000 Then Call WriteLogFile(strLogFile, "CRITICAL ERROR: Unable to generate a name to backup the machine list file. Clean up old files and try again.") Wscript.Quit End If ' -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Script variables -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= strWGID = "Administrator" 'local account strWGPW = "putpasswordhere" strDomainID = "DOMAINNAME\AdministrativeServiceAccount" 'domain account. The script tries this if the local account doesn't work strDomainPW = "putpasswordhere" strNSName = "10.1.2.3" 'IP Address of the NS strNSName1 = "NSSERVER" 'Name of your NS server if you are using the option to add an entry to the client HOSTS file strNSID = "DOMAIN\Userid" 'App Identity strNSPW = "ENCRYPTEDPASSWORD==" ' you can get this out of the log file on a trusted domain machine where the agent was pushed successfully ' -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= For Each strComputer in arrMachineList On Error Resume Next strID = strWGID strPW = strWGPW Call WriteLogFile(strLogFile, "### Starting " & strComputer) Err.Clear 'Map drive to the admin$ share objNetwork.MapNetworkDrive "L:" , "\\" & strComputer & "\Admin$", False, strID, strPW If Err.Number = -2147024811 Then 'drive already mapped (could be from previous failed run) 'unmap drive then try again Err.Clear Call WriteLogFile(strLogFile, " - Error: L: Already mapped, removing") objNetwork.RemoveNetworkDrive "L:" objNetwork.MapNetworkDrive "L:" , "\\" & strComputer & "\Admin$", False, strID, strPW End If If Err.Number = -2147024891 or Err.Number = -2147023570 Then 'Access is denied or login failure - try domain account. Call WriteLogFile(strLogFile, " - Login with " & strID & " failed. Trying Domain account. ") strID = strDomainID strPW = strDomainPW Err.Clear objNetwork.MapNetworkDrive "L:" , "\\" & strComputer & "\Admin$", False, strID, strPW End If If Err.Number <> 0 Then strError = Err.Description If Right(strError,2) = vbCrLf Then strError = left(strError,len(strError)-2) 'remove crlf for logging purposes Call WriteLogFile(strLogFile, " - Error Mapping drive to " & strComputer & ". " & Err.Number & " - " & strError) Call AddLineToFile(strComputer & ",map:" & strError, strFailureListFile, strLogFile) 'write entry to new machine list file for next install attempt Call AddLineToFile(strComputer, strMachineListFile, strLogFile) Err.Clear Else Call WriteLogFile(strLogFile, " - L: Mapped to " & strComputer) 'copy exe to admin$ Err.Clear objFSO.CopyFile "\\" & strNSName & "\nscap\bin\win32\x86\AeXSWDInstSvc.exe", "L:\",True If Err.Number <> 0 Then strError = Err.Description If Right(strError,2) = vbCrLf Then strError = left(strError,len(strError)-2) 'remove crlf for logging purposes Call WriteLogFile(strLogFile, " - Error copying client to admin$ on " & strComputer & ". " & Err.Number & " - " & strError) 'write entry to list of machines with errors Call AddLineToFile(strComputer & ",Failed to copy file to admin$ share:" & strError & "(" & Err.Number & ")", strFailureListFile, strLogFile) 'write entry to new machine list file for next install attempt Call AddLineToFile(strComputer, strMachineListFile, strLogFile) Err.Clear Else Call WriteLogFile(strLogFile, " - Copied AeXSWDInstSvc.exe to admin$ on " & strComputer) 'remotely execute command Call WriteLogFile(strLogFile, " - Launching Install remotely") strCommand = "AeXSWDInstSvc.exe -u ""http://" & strNSName & "/Altiris/NS/NSCap/Bin/Win32/X86/NS Client Package/AeXNSC.exe"" -s " & strNSName & " -w http://" & strNSName & "/Altiris/ -nostartmenu -accUserName " & strNSID & " -accUserPassword " & strNSPW & " -n ""Altiris Agent Installation Service""" intrestult = RunCommand("[001]|""[SCRIPTDIR]\psexec.exe"" -accepteula \\" & strComputer & " -u " & strID & " -p " & strPW & " " & strCommand, "", "", strLogFile) 'Add entry for server to HOSTS file on client if neccesary 'IF YOU DO NOT WANT THE HOSTS FILE MODIFIED, REMark out the next line 'Call AddLineToFile(strNSName1 & " " & strNSName1 & " # Altiris NS","L:\system32\drivers\etc\hosts",strLogFile) objNetwork.RemoveNetworkDrive "L:" End If End If Next Call WriteLogFile(strLogFile, "---------- End of " & WScript.ScriptName & " execution. ----------") RunCommand "[100]|notepad.exe " & strLogFile,"","", "" ' ### START OF COMMON SCRIPT PROCEDURE LIBRARY ### Function GetEnvironVar(ByVal strKeyWord) ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Name: GetEnvironVar(), v3.0.3086 ' Description: Returns the value an environment variable string based on predefined keywords. ' Arguments: strKeyWord - key word used to look for a replace value ' Dependencies: None ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Declare constants Const WindowsFolder = 0 ' the windows folder constains files installed by the windows operating system Const SystemFolder = 1 ' the system folder constains libraries, fonts, and device drivers Const TemporaryFolder = 2 ' the temp folder is used to store temporary files ' Declare variables Dim objWshShell ' used to work with windows shell object Dim objFso ' used to work with the FileSystemObject object Dim objScriptFile ' used to work with script file object Dim objScriptFolder ' used to work with script folder object Dim strAllUsersProfile ' used to hold the location of the all users profile Dim strPublic ' used to hold the location of the all users profile *vista only* Dim strAllUsers ' used to hold which all users profile folder to use Dim intAllUsersStartPosition ' used to hold the starting position the all users folder in the path string Dim strReturn ' used to hold the string returned by this function ' Get a reference to the Windows Shell object Set objWshShell = CreateObject("WScript.Shell") ' Get a reference to the FileSystemObject object Set objFso = CreateObject("Scripting.FileSystemObject") ' Get a reference to the script file Set objScriptFile = objFso.GetFile(Wscript.ScriptFullName) ' Get a reference to the script folder Set objScriptFolder = objFso.GetFolder(objFso.GetParentFolderName(objScriptFile)) ' Get the location of the all users profile which is used to derive many other folder locations strAllUsersProfile = objWshShell.ExpandEnvironmentStrings("%AllUsersProfile%") ' For vista compatibility, need to calculate how to handle AllUsersProfile since the path of that variable has changed. strPublic = objWshShell.ExpandEnvironmentStrings("%Public%") If strPublic <> "%Public%" Then strAllUsers = strPublic intAllUsersStartPosition = InStr(strPublic,"Public") Else strAllUsers = strAllUsersProfile intAllUsersStartPosition = InStr(strAllUsersProfile,"All Users") End If ' Look for replacement values for strKeyWord, otherwise return the unchanged strLookup value Select Case strKeyWord Case "[ALLUSERSPROFILE]" strReturn = strAllUsers Case "[COMMONAPPDATA]" strReturn = strAllUsers & "\Application Data" Case "[COMMONDOCUMENTS]" strReturn = strAllUsers & "\Documents" Case "[COMMONFAVORITES]" strReturn = strAllUsers & "\Favorites" Case "[COMMONTEMPLATES]" strReturn = strAllUsers & "\Templates" Case "[COMMONDESKTOP]" strReturn = objWshShell.SpecialFolders("AllUsersDesktop") Case "[COMMONSTARTMENU]" strReturn = objWshShell.SpecialFolders("AllUsersStartMenu") Case "[COMMONPROGRAMS]" strReturn = objWshShell.SpecialFolders("AllUsersPrograms") Case "[COMMONSTARTUP]" strReturn = objWshShell.SpecialFolders("AllUsersStartup") Case "[COMPUTERNAME]" strReturn = objWshShell.ExpandEnvironmentStrings("%ComputerName%") Case "[COMMONPROGRAMFILES]" strReturn = objWshShell.ExpandEnvironmentStrings("%CommonProgramFiles%") Case "[DEFAULTUSERPROFILE]" strReturn = Left(strAllUsers,intAllUsersStartPosition-2) & "\Default User" Case "[PROFILESDIRECTORY]" strReturn = Left(strAllUsers,intAllUsersStartPosition-2) Case "[PROGRAMFILES]" strReturn = objWshShell.ExpandEnvironmentStrings("%ProgramFiles%") Case "[SCRIPTDIR]" strReturn = objScriptFolder.Path Case "[SCRIPTDIR83]" strReturn = objScriptFolder.ShortPath Case "[SYSTEMDRIVE]" strReturn = objWshShell.ExpandEnvironmentStrings("%SystemDrive%") Case "[SYSTEMROOT]" strReturn = objWshShell.ExpandEnvironmentStrings("%SystemRoot%") Case "[TEMP]" strReturn = objFso.GetSpecialFolder(TemporaryFolder) Case "[WINDIR]" strReturn = objFso.GetSpecialFolder(WindowsFolder) Case "[WINSYS16DIR]" strReturn = objFso.GetSpecialFolder(WindowsFolder) & "\System" Case "[WINSYSDIR]" strReturn = objFso.GetSpecialFolder(SystemFolder) Case Else strReturn = strKeyWord End Select ' Return the processed strValue GetEnvironVar = strReturn End Function Function GetRunParameters(ByVal strCmdSpec) ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Name: GetRunParameters(), v3.0.3086 ' Description: Returns an array of run parameters for strCmdSpec ' Arguments: strCmdSpec - command to parse run parameters from ' Dependencies: GetEnvironVar() ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Declare variables Dim objScriptFile ' used to work with script file object Dim intWindowStyle ' used to hold default windows style Dim blnWaitOnReturn ' used to hold default wait on return value Dim strSwitches ' used to hold switches passed to function ' Set default run method parameters intWindowStyle = 1 ' By default activate and display a window blnWaitOnReturn = True ' By default halt script execution until program is finished ' Check for prefix pattern to see if strCmdSpec should be parsed for run parameters If (Left(strCmdSpec, 1) = "[") and (Mid(strCmdSpec, 5, 2) = "]|") Then ' Get the switches which control execution of strCmdSpec strSwitches = Left(strCmdSpec, 5) ' Strip off switches from strCmdSpec strCmdSpec = Right(strCmdSpec, Len(strCmdSpec)-6) ' Check what the window style should be used when running strCmdSpec [X,y,y]| If CInt(Mid(strSwitches, 2, 1)) >= 0 and CInt(Mid(strSwitches, 2, 1)) <= 9 Then intWindowStyle = CInt(Mid(strSwitches, 2, 1)) ' Use any valid value that is passed ' Check if run method should return immediately after starting strCmdSpec [y,X,y]| If CInt(Mid(strSwitches, 3, 1)) = "0" Then blnWaitOnReturn = False ' Anything other than 0, assume run method should wait ' Check if keywords should be replaced with environment variables in strCmdSpec string [y,y,X]| If CInt(Mid(strSwitches, 4, 1)) = "1" Then ' Anything other than 1, assume no keywords in the string should be replaced ' Only replace supported key words. strCmdSpec = Replace(strCmdSpec, "[PROFILESDIRECTORY]", GetEnvironVar("[PROFILESDIRECTORY]")) strCmdSpec = Replace(strCmdSpec, "[DEFAULTUSERPROFILE]", GetEnvironVar("[DEFAULTUSERPROFILE]")) strCmdSpec = Replace(strCmdSpec, "[ALLUSERSPROFILE]", GetEnvironVar("[ALLUSERSPROFILE]")) strCmdSpec = Replace(strCmdSpec, "[COMMONAPPDATA]", GetEnvironVar("[COMMONAPPDATA]")) strCmdSpec = Replace(strCmdSpec, "[COMMONDESKTOP]", GetEnvironVar("[COMMONDESKTOP]")) strCmdSpec = Replace(strCmdSpec, "[COMMONDOCUMENTS]", GetEnvironVar("[COMMONDOCUMENTS]")) strCmdSpec = Replace(strCmdSpec, "[COMMONFAVORITES]", GetEnvironVar("[COMMONFAVORITES]")) strCmdSpec = Replace(strCmdSpec, "[COMMONSTARTMENU]", GetEnvironVar("[COMMONSTARTMENU]")) strCmdSpec = Replace(strCmdSpec, "[COMMONPROGRAMS]", GetEnvironVar("[COMMONPROGRAMS]")) strCmdSpec = Replace(strCmdSpec, "[COMMONSTARTUP]", GetEnvironVar("[COMMONSTARTUP]")) strCmdSpec = Replace(strCmdSpec, "[COMMONTEMPLATES]", GetEnvironVar("[COMMONTEMPLATES]")) strCmdSpec = Replace(strCmdSpec, "[COMPUTERNAME]", GetEnvironVar("[COMPUTERNAME]")) strCmdSpec = Replace(strCmdSpec, "[COMMONPROGRAMFILES]", GetEnvironVar("[COMMONPROGRAMFILES]")) strCmdSpec = Replace(strCmdSpec, "[PROGRAMFILES]", GetEnvironVar("[PROGRAMFILES]")) strCmdSpec = Replace(strCmdSpec, "[SCRIPTDIR]", GetEnvironVar("[SCRIPTDIR]")) strCmdSpec = Replace(strCmdSpec, "[SCRIPTDIR83]", GetEnvironVar("[SCRIPTDIR83]")) strCmdSpec = Replace(strCmdSpec, "[SYSTEMDRIVE]", GetEnvironVar("[SYSTEMDRIVE]")) strCmdSpec = Replace(strCmdSpec, "[SYSTEMROOT]", GetEnvironVar("[SYSTEMROOT]")) strCmdSpec = Replace(strCmdSpec, "[TEMP]", GetEnvironVar("[TEMP]")) strCmdSpec = Replace(strCmdSpec, "[WINDIR]", GetEnvironVar("[WINDIR]")) strCmdSpec = Replace(strCmdSpec, "[WINSYS16DIR]", GetEnvironVar("[WINSYS16DIR]")) strCmdSpec = Replace(strCmdSpec, "[WINSYSDIR]", GetEnvironVar("[WINSYSDIR]")) End If End If ' Return an array of command spec parameters GetRunParameters = Array(strCmdSpec, intWindowStyle, blnWaitOnReturn) End Function Function GetScriptAlreadyRunning() ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Name: GetScriptAlreadyRunning(), v3.0.3808 ' Description: Checks to see if this script is running via Wscript or Cscript in more than one instance. This function can be used to prevent accidental launch of the same script more than once. ' Arguments: None ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Declare variables Dim objSWbemServices 'used for working with the SWbemServices object Dim colWin32Process, objWin32Process ' used to work with instances of the Win32_Service class Dim intInstanceCount 'count of instances of this script running 'initialize instance counter intInstanceCount = 0 Set objSWbemServices = GetObject("winmgmts:\\.\root\cimv2") Set colWin32Process = objSWbemServices.ExecQuery ("SELECT * FROM Win32_Process WHERE Name = 'Wscript.exe' OR Name = 'Cscript.exe'") If colWin32Process.Count > 1 Then 'more than one script is running (not necessarily instances of this script) ' Check script names For Each objWin32Process in colWin32Process If InStr(lcase(objWin32Process.CommandLine), lcase(Wscript.ScriptFullName)) > 0 Then 'Found instance of THIS script running intInstanceCount = intInstanceCount + 1 End If Next End If ' Check instance count and return true or false If intInstanceCount > 1 Then GetScriptAlreadyRunning = True Else GetScriptAlreadyRunning = False End Function Function RunCommand(ByVal strCmdSpec, ByVal arrExceptions, ByVal strTrackingKey, ByVal strLogFile) ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Name: RunCommand(), v3.0.3086 CUSTOM OUTPUT FORMAT ' Description: Execute a command and write results to log and registry. Returns the value of good and exception exit codes. ' Arguments: ' - strCmdSpec - The command to be executed with optional launch parameters ' - arrExceptions - array of exception codes (either good or bad) that should not be returned from function without an exit ' - strTrackingKey - registry value used to write tracking information, pass "" if tracking key not used ' - strLogFile - path and filename to write log file information, pass "" if log file not used ' Dependencies: GetRunParameters(), WriteLogFile(), WriteTrackingKey() ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Allow function to handle errors On Error Resume Next ' Declare variables Dim objWshShell ' used for working with the windows shell object Dim intReturn ' return code for the commands that are executed Dim arrRunParameters ' holds array of parsed cmdspec Dim intException ' used to step through array of exception codes ' Get a reference to the windows shell object Set objWshShell = CreateObject("WScript.Shell") ' Get run parameters for the command specification arrRunParameters = GetRunParameters(strCmdSpec) ' Clear the err object Err.Clear ' Execute command specification intReturn = objWshShell.Run(arrRunParameters(0), arrRunParameters(1), arrRunParameters(2)) ' There was an invald command specified If Err.Number <> 0 Then ' Update tracking key and log file Call WriteTrackingKey(strTrackingKey, "CmdError") Call WriteLogFile(strLogFile, " - RunCommand Error. Invalid command specified (Error:" & Err.Number & ", """ & arrRunParameters(0) & """).") ' Quit script with exit code 99 WScript.Quit(99) End If 'Set Return Code for this function RunCommand = intReturn ' Check return code against array of exception codes If IsArray(arrExceptions) Then For each intException in arrExceptions ' Check if return code is one of the predefined exception code If intReturn = intException Then Exit Function ' do nothing with exception codes Next End If ' Check return code against known good codes; quit script if not a good return code Select Case intReturn Case 0 ' ERROR_SUCCESS ' Update tracking key and log file Call WriteTrackingKey(strTrackingKey, "True") Call WriteLogFile(strLogFile, " - RunCommand Good. Command executed. (Returned:" & intReturn & ", """ & arrRunParameters(0) & """).") Case 1641 'ERROR_SUCCESS_REBOOT_INITIATED ' Update tracking key and log file Call WriteTrackingKey(strTrackingKey, "CmdRestarted") Call WriteLogFile(strLogFile, " - RunCommand Good. Command executed however restart initiated so changes can take effect (Returned:" & intReturn & ", """ & arrRunParameters(0) & """).") Case 3010, 3011 'ERROR_SUCCESS_REBOOT_REQUIRED, ERROR_SUCCESS_RESTART_REQUIRED ' Update tracking key and log file Call WriteTrackingKey(strTrackingKey, "CmdRestarted") Call WriteLogFile(strLogFile, " - RunCommand Good. Command executed however a restart is required for changes to take effect (Returned:" & intReturn & ", """ & arrRunParameters(0) & """).") Case Else ' Failure Error Codes ' Update tracking key and log file Call WriteTrackingKey(strTrackingKey, "CmdError") Call WriteLogFile(strLogFile, " - RunCommand Error. Command could not be executed (Returned:" & intReturn & ", """ & arrRunParameters(0) & """).") ' Quit script with exit code of the return code WScript.Quit(intReturn) End Select End Function Sub WriteLogFile(ByVal strLogFile, ByVal strMessage) ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Name: WriteLogFile(), v3.0.3086 ' Description: Write a time and date stamped message to a text file. Does nothing if strFile is and empty string. ' Arguments: ' - strLogFile - Name of log file to append or create ' - strMessage - Message to add to the log file ' Dependencies: None ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Exit the sub if strLogFile is not set If strLogFile = "" Then Exit Sub ' Declare Constants Const ForWriting = 2 Const ForAppending = 8 ' Declare variables Dim objFso ' used to work with the FileSystemObject object Dim objFile ' used to work with a file object ' Get a reference to the FileSystemObject object Set objFso = CreateObject("Scripting.FileSystemObject") ' Check for existance of strFile If objFso.FileExists(strLogFile) Then ' Add message to the existing file ' Open strLogFile for appending Set objFile = objFso.OpenTextFile(strLogFile, ForAppending, True) Else ' Add message to a new file ' Open strLogFile for writing Set objFile = objFso.OpenTextFile(strLogFile, ForWriting, True) End If ' Write strMessage to strLogFile. objFile.WriteLine Date & "|" & Time & "|" & strMessage ' Close strLogFile. objFile.Close End Sub Sub WriteTrackingKey(ByVal strTrackingValueName, ByVal strTrackingValueData) ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Name : WriteTrackingKey(), v3.0.3086 ' Description : Write specified data to the specified tracking key with no success or error checking. ' Arguments: ' - strTrackingValueName - value-name used for tracking status ' - strTrackingValueData - data to write to value-name used for tracking status ' Dependencies: None ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Exit the sub if strTrackingValueName is not set If strTrackingValueName = "" Then Exit Sub ' Declare variables Dim objWshShell ' used for working with the windows shell object ' Get a reference to the windows shell object Set objWshShell = CreateObject("WScript.Shell") ' Write strTrackingValueData to strTrackingValueName objWshShell.RegWrite strTrackingValueName, strTrackingValueData, "REG_SZ" End Sub ' ### END OF COMMON SCRIPT PROCEDURE LIBRARY ### ' ### START OF CUSTOM PROCEDURES ### Sub AddLineToFile(strLine, strFilePath, strLogFile) ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ' Name: AddLineToFile(), v1.0 ' Description: Adds a line to specified file if it does not already exist ' Arguments: ' strLine - Line to add ' strFilePath - Path to file to modify ' strLogFile - Log file for results ' Dependencies: WriteLogFile() ' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ On Error Resume Next ' Declare variables Dim objFso ' used to work with the FileSystemObject object ' Get a reference to the FileSystemObject object Set objFso = CreateObject("Scripting.FileSystemObject") ' Return the contents of strFileSpec GetFileContents = objFso.OpenTextFile(strFilePath,1,False,-2).ReadAll If InStr(GetFileContents, strLine) > 0 Then Call WriteLogFile(strLogFile, " - WARNING: Skipping file modification - Entry already exists") Else Call WriteLogFile(strLogFile, " - Adding Entry to " & strFilePath & ": " & strLine) Err.Clear Set objFile = objFso.OpenTextFile(strFilePath,8,True,-2) 'Append & create if doesn't exist 'If file does not end with CrLf, add If GetFileContents <> "" AND Right(GetFileContents,2) <> vbCrLf Then objFile.Write vbcrlf objFile.Write strLine & vbcrlf If Err.Number <> 0 Then Call WriteLogFile(strLogFile, " - ERROR Updating file: " & strFilePath & ". " & Err.Number & " - " & Err.Description) Err.Clear End If objFile.Close End If End Sub ' ### END OF CUSTOM PROCEDURES ###