Skip to content

Instantly share code, notes, and snippets.

@VertigoRay
Last active February 23, 2017 06:00
Show Gist options
  • Save VertigoRay/5091777 to your computer and use it in GitHub Desktop.
Save VertigoRay/5091777 to your computer and use it in GitHub Desktop.
This is a simple Install Wrapper. I use it with SCCM 2012 to allow STDOUT to be captured and sent to a log file, since STDOUT appears to be lost when deploying software as an SCCM 2012 Application.
Option Explicit
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' FIRST THINGS FIRST:
' Change this DeploymentTypeName to match the Deployment Type Name used in the Application.
' - It's just used to for the log file name.
' - For Uninstall action, append ".x" to name, such as: Application - Install.x
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dim DeploymentTypeName
DeploymentTypeName = "CAS Remote - Install"
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' NEXT:
' You need to get to the Install Steps section.
' Scroll down until you see another clump of tildy-bars, like this
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' Generic Stuff that can be reused is here.
' There's probably not much to change here.
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dim objShell, objFSO, logFolder, logFile, objLog
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Set objShell = WScript.CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Sub CreateFolderTree(strTempPath)
If Not objFSO.FolderExists(objFSO.GetParentFolderName(strTempPath)) Then
CreateFolderTree(objFSO.GetParentFolderName(strTempPath))
End If
If Not objFSO.FolderExists(strTempPath) Then
objFSO.CreateFolder(strTempPath)
End If
End Sub
logFolder = objShell.ExpandEnvironmentStrings( "%SystemRoot%\Logs\" )
CreateFolderTree(logFolder)
logFile = objShell.ExpandEnvironmentStrings( logFolder & DeploymentTypeName &".log" )
Set objLog = objFSO.OpenTextFile(logFile, ForWriting, True)
Function LogIt_action (logLine, noPrefix)
' [string] logLine is logged.
' [bool] noPrefix
' - Removes the Prefix. Default False.
' - Prefix used in Install/Uninstall steps only.
Dim t, y, m, d, h, i, s, ts, pre, logThis
t = Timer/3600
y = DatePart("yyyy",Date)
m = Right("0" & DatePart("m",Date), 2)
d = Right("0" & DatePart("d",Date), 2)
h = Right("0" & Int(t), 2)
i = Right("0" & Int((t - h) * 60), 2)
s = Right("0" & Int((((t - h) * 60 - m) * 60)*1000)/1000, 6)
ts = "["& y &"-"& m &"-"& d &" "& h &":"& i &":"& s &"] "
If noPrefix Then
pre = ""
Else
pre = "+++ "
End If
WScript.Echo(ts & pre & logLine)
objLog.WriteLine(ts & pre & logLine)
End Function
Function LogIt (logLine)
LogIt_action logLine, False
End Function
Function logItNoPrefix (logLine)
LogIt_action logLine, True
End Function
Function ExecuteIt_action (execute, quitOnFail)
' [string] execute is executed.
' [bool] quitOnFail
' - Quit if ExitCode is not 0. Default False.
logItNoPrefix "CommandRx: "& execute
execute = objShell.ExpandEnvironmentStrings(execute)
logItNoPrefix "Executing: "& execute
Dim objExec, objRegEx
Set objExec = objShell.Exec(execute)
Set objRegEx = New RegExp
objRegEx.IgnoreCase = True
objRegEx.Global = True
objRegEx.Pattern = "^msiexec|[.]msi[""]{0,1} .*/(?:i|x)(?= |$)"
If Not objRegEx.Test(execute) Then
' If we're not executing an msi ...
Do
logItNoPrefix "> "& objExec.StdOut.ReadLine()
Loop While Not objExec.StdOut.atEndOfStream
Else
' VBS has issues catching STDOUT from MSI. /shrug
logItNoPrefix "--- MSI detected. Switching to StdErr logging"
Do
logItNoPrefix "> "& objExec.StdErr.ReadLine()
Loop While Not objExec.StdErr.atEndOfStream
End If
' Should never loop here, but just in case the stream ends before we're done...
Do While objExec.Status = 0
WScript.Sleep 100
Loop
logItNoPrefix ">>> ("& objExec.ProcessID &") ExitCode: "& objExec.ExitCode
If (quitOnFail) And (objExec.ExitCode <> 0) Then
logItNoPrefix "quitOnFail detected. Evaluating Success Codes: "& SuccessCodes
Set objRegEx = New RegExp
objRegEx.IgnoreCase = True
objRegEx.Global = True
objRegEx.Pattern = "(?:^| )"& objExec.ExitCode &"(?= |$)"
If objRegEx.Test(SuccessCodes) Then
logItNoPrefix "Treating "& objExec.ExitCode &" as Success Code. Continuing ..."
Else
logItNoPrefix "Exiting : quitOnFail detected."
WScript.Quit objExec.ExitCode
End If
End If
End Function
Function ExecuteIt (execute)
ExecuteIt_action execute, False
End Function
Function ExecuteItOrQuit (execute)
ExecuteIt_action execute, True
End Function
Dim CurrentDirectory, ProcessorArchitecture, ProgramFiles, ProgramFilesX64
logItNoPrefix "~~~~~ BEGIN: "& DeploymentTypeName
logItNoPrefix "Log File: "& logFile
CurrentDirectory = objFSO.GetParentFolderName(Wscript.ScriptFullName)
logItNoPrefix "CurrentDirectory: "& CurrentDirectory
ProcessorArchitecture = objShell.ExpandEnvironmentStrings( "%PROCESSOR_ARCHITECTURE%" )
logItNoPrefix "ProcessorArchitecture: "& ProcessorArchitecture
If ProcessorArchitecture = "x86" Then
ProgramFiles = objShell.ExpandEnvironmentStrings( "%ProgramFiles%" )
ProgramFilesX64 = Null
Else
ProgramFiles = objShell.ExpandEnvironmentStrings( "%ProgramFiles(x86)%" )
ProgramFilesX64 = objShell.ExpandEnvironmentStrings( "%ProgramFiles%" )
End If
logItNoPrefix "ProgramFiles: "& ProgramFiles
logItNoPrefix "ProgramFilesX64: "& ProgramFilesX64
logItNoPrefix "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
Dim SuccessCodes
SuccessCodes = ""
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' Start Install/Uninstall steps below ...
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' Usage:
' Each step of the installation needs to be annotated, so progress can be tracked in the log.
'
' Log to File with the LogIt Function, such as:
' LogIt "Installing Software"
'
' Execute a command (outside of ComSpec) with the ExecuteIt Function, such as:
' ExecuteIt "msiexec.exe /qn /i """& CurrentDirectory &"\installer.msi"" /log """& Replace(logFile, ".log", ".msi.log") &""""
'
' If your want to Quit the installer with the same non-zero ExitCode that is returned by the execute command, do this:
' ExecuteItOrQuit "msiexec.exe /qn /i """& CurrentDirectory &"\installer.msi"" /log """& Replace(logFile, ".log", ".msi.log") &""""
'
' Add more Success Codes before running ExecuteItOrQuit, 0 is always success:
' SuccessCodes = "1603 1605"
' ExecuteItOrQuit "msiexec.exe /qn /i """& CurrentDirectory &"\installer.msi"" /log """& Replace(logFile, ".log", ".msi.log") &""""
'
' Note:
' - ExecuteIt will handle Environment Varibles (EnvVar), but you may need to wrap the EnvVar in quotes if you suspect a space.
' - Multiple SuccessCodes can be separated by a space. Reset
'
' Variables:
' CurrentDirectory The current directory of this VBS file.
' ProcessorArchitecture x86 or AMD64, respectively.
' ProgramFiles On x86: %ProgramFiles%; On x64: %ProgramFiles(x86)%
' ProgramFilesX64 On x86: Null; On x64: %ProgramFiles%
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' Below this line is the Install/Uninstall steps.
' Can't set exe logs to use logFile - Open Handle.
' - VBS Create Shortcut: http://bit.ly/WervHB
' - Special Folders: http://bit.ly/WpBZhP
' ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LogIt "Installing Software"
ExecuteItOrQuit "msiexec.exe /qn /i """& CurrentDirectory &"\CASRemote.msi"" /log """& Replace(logFile, ".log", ".msi.log") &""""
LogIt "Copying CAS Remote Program"
ExecuteIt "xcopy /herickyz """& CurrentDirectory &"\CAS-Remote.exe"" """& ProgramFiles &"\CAS Remote (ScreenConnect)"""
LogIt "Create Shortcut"
Dim objLnk
Set objLnk = objShell.CreateShortcut(objShell.SpecialFolders("AllUsersPrograms") & "\CAS Remote (ScreenConnect).lnk")
objLnk.TargetPath = ProgramFiles & "CAS Remote (ScreenConnect)\CAS-Remote.exe"
objLnk.Save
LogIt "Creating Admin Shortcuts"
ExecuteIt CurrentDirectory &"CAS-RemoteShortcuts.exe"
LogIt "Set Service Permissions"
ExecuteIt CurrentDirectory &"subinacl.exe /SERVICE ""CAS Remote (ScreenConnect)"" /GRANT=Users=TOC"
LogIt "Set Service to Manual"
ExecuteIt "sc config ""CAS Remote (ScreenConnect)"" start= demand"
LogIt "Stopping Service"
ExecuteIt "sc stop ""CAS Remote (ScreenConnect)"""
LogIt "Stop CAS Remote Program"
ExecuteIt "taskkill /f /im cas-remote.exe"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment