Hello Everyone!!!

Before I begin, let me tell you that I am not a programming expert. As with most of us, I am looking to work with my fellow professionals in learning what I need and giving to the ninjas what I have.

Not sure how many of you use vbscript for application packaging and deployment, but, I use it. Below is a template that can help in packaging software and setting up user scripts (active setup). I would be glad if someone can broaden this script and help me on areas that I marked in the script (which need to be improved)

Here is what I enevisioned in the template

  1. Write log file before starting the install
  2. Install msi/exe with appropriate command line
  3. if successful, write to log - else - exit with returning the code to SCCM
  4. Use active setup to run per user scripts/copy files etc

Here is what I think will make the script better

  1. A uninstall function which will search for application GUID in registry and uninstall the application using the uninstall string. This way, application will remove all previous versions

I need help with the uninstall function in the script. When I have written this, the command window opens and does not close. The script needs to check both HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node and HKEY_LOCAL_MACHINE\SOFTWARE (i.e, 32-bit and 64-bit registry locations) and uninstall the application. The command we need to run needs to be in such a way that it can be modified for executables as well. If someone already has it, please add it here and some folk might be able to use it effectively.

If someone has a template in powershell, please also share it.

--

Cheers


'##==============================================================================
'##==============================================================================
'##  SCRIPT.........:  install.vbs
'##  AUTHOR.........:  Tech Surfer
'##  VERSION........:  1.0.0.0
'##  REVISED DATE...........:  November 01, 2016
'##  DATE CREATED...........:  October 28, 2016
'##  LICENSE........:  Freeware
'##  REQUIREMENTS...:
'##
'##==============================================================================
'##==========******* USE SCRIPT AT YOUR OWN RISK *******=========================
'##==============================================================================
'##  DESCRIPTION....:  This script will help install applications. It is geared more towards msi's.
'##                    To run setup.exe files for silent installs, please review the script and change accordingly.
'##                    Script is intelligent enough to look for a specific name of application and uninstall previous versions (msi only).
'##                    For uninstalling EXE using their diaplay name, change the logic in the function at the bottom
'##                    Change the logfiles to whatever directories you want to write the log file to. Currently writing to C:\Temp\Application name
'##
'##  NOTES..........: ' Script does the following
      ' --- Gets current directory that the script is running from
      ' --- Getting standard file locations that suits all windows operating systems using registry keys
      ' --- Gets information on who is running the script
      ' --- If needed, script brings a popup window to warn that the install will run in specified time
      ' --- Gets 64-bit or 32-bit operating system which can be used to copy files/use directory structure as required
      ' --- Creates active setup for a script to be run for each user at logon
      ' --- Uninstalls application using the display name
      ' --- creates log files for install/uninstall
      ' --- Incase of error, quits the script by sending an error code (to SCCM/any other deployment tool)
'##
'##  CUSTOMIZE......: 'Customize the following to suit your needs
      ' DEPLOYNAME
      ' SETUPLOG
      ' POPUPTIMEOUT
      ' UNLOG
      ' FINDUNINSTALL("Application Name")
      ' MYFILE
      ' COMMANDLINE
      ' USERSCRIPTS
      ' APPCLOSE
'## Functions that can be used (see bottom for reference)
      ' WriteLogFileLine(sLogFileName,sLogFileLine)
      ' LANGUAGE
      ' OsAchitecture
      ' FINDUNINSTALL
'##==============================================================================
'##  Starting the Script
'##==============================================================================
On Error Resume Next
set fs = CreateObject("Scripting.FileSystemObject")
Set Sh = WScript.CreateObject("WScript.Shell")
'## Change the name of the application below accordingly
DEPLOYNAME = "ApplicationName"
'#Define current folder from where the script is running
CURRENTDIR = fs.GetParentFolderName(Wscript.ScriptFullName)
QUOTE = chr(34)
'# Getting standard file locations that suits all windows operating systems
cdesktop = sh.expandenvironmentstrings(sh.regread("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Common Desktop"))
cprograms = sh.expandenvironmentstrings(sh.regread("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Common Programs"))
cstart = sh.expandenvironmentstrings(sh.regread("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Common Start Menu"))
cappdata = sh.expandenvironmentstrings(sh.regread("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Common AppData"))
udesktop = sh.expandenvironmentstrings(sh.regread("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Desktop"))
'# Checking to see who is running the script. This will help investigate installation failure
Set objNetwork = CreateObject("Wscript.Network")
RUNNINGAS = objNetwork.UserName
'# Write a log file for my program and change the path here accordingly
SETUPLOG = "C:\Temp\" & DEPLOYNAME & ".log"
mylog =  WriteLogFileLine(SETUPLOG,"Installation is initiated by :: " & RUNNINGAS)
mylog =  WriteLogFileLine(SETUPLOG,"Script is run by ---- " & RUNNINGAS & " ---- from location :: " & CURRENTDIR)
mylog =  WriteLogFileLine(SETUPLOG,"Started installing application")
'# ================================================== BEGIN : Message while terminating any applications ==========================================================================================
'# Change number of seconds to wait as required
POPUPTIMEOUT = 0
APPCLOSE = "Enter name of applications that will be closed"
'# Change the below message as required to suit your application
POPUPMESSAGE = "This installation will close " & APPCLOSE & ". Please save all your work and close " & APPCLOSE & " applications. Application will install in " & POPUPTIMEOUT & " seconds!"
'# Change the below title as required to suit your application
POPUPTITLE = "WARNING!! " & APPCLOSE & " will close as part of the installation!"
If POPUPTIMEOUT <> 0 then MYPOPUP = sh.Popup(POPUPMESSAGE, POPUPTIMEOUT, POPUPTITLE)
'# ======================================== END of Message : Message while terminating any applications ========================================
'#change the name of the application you want to terminate
TASKKILL = sh.expandenvironmentstrings("%WINDIR%\system32\taskkill.exe")
'myret = sh.run("cmd.exe /c " & quote & TASKKILL & quote & " /f /im name*",1,False)
'# ================================================== Begin cleanup of previous versions of the applications ==================================================
'# Make sure the application name is exactly what you want changed
'# DANGER!!! Don't give a name like "Microsoft" or "Adobe" as this will uninstall every product that has similar display name
'uncomment and use this section
'myret = FINDUNINSTALL("ApplicationName")
'Writes a seperate uninstall log if it finds previous version of the package installed
UNLOG = "C:\Temp\" & DEPLOYNAME & "uninst.log"
'# ================================================== End cleanup of previous versions of the applications ================================================== 
'#==================================== End Uninstalling Previous Version =================================================================================

'# This section is looking for 64-bit or 32-bit of the Operating System
'# This can be checked in various ways. FOr example, you can look for SYSWOW64 folder (C:\Windows\SYSWOW64)
'# Some organizations have folder redirection issues and make sure your script does not redirect to wrong application
'Use Function OsAchitecture at the bottom if you need to find whether the system is 32-bit or 64-bit
'# Gather file location - change myfile.exe name to reflect actual file name
MYFILE = CURRENTDIR & "\setupfile.exe"
If fs.fileexists(MYFILE) Then 
 '#Installing Application. If the install fails here, the script will quit with appropriate error code
 mylog =  WriteLogFileLine(SETUPLOG,"Running Setup file :: " & quote & MYFILE & quote)
 MSILOG = "C:\Temp\" & DEPLOYNAME & "msi.log"
 COMMANDLINE = "msiexec.exe /i " & quote & MYFILE & quote & " /qb! ALLUSERS=1 REBOOT=ReallySuppress /l*v "& MSILOG
 myret = sh.run("cmd.exe /c " & quote & MYFILE & quote & COMMANDLINE,1,True)
 '# General successful exit code for application install are 0 and 30. If a specific application exits a different code, change that here. 
 If myret = 0 or myret = 3010 Then
  mylog =  WriteLogFileLine(SETUPLOG,"Application Successfully installed!! The exit code for application is :: " & myret)
 '# Writing a specific registry key if the application install is successful. This will help in detection method in SCCM and also for inventory purposes.
 '# This is mandatory and can be changed per suitability
  strSafeDate = Right("0" & DatePart("m",Date), 2) & "/" & Right("0" & DatePart("d",Date), 2) & "/" & DatePart("yyyy",Date)
  strSafeTime = Right("0" & Hour(Now), 2) & ":" & Right("0" & Minute(Now), 2) & ":" & Right("0" & Second(Now), 2)
  myret = sh.regwrite("HKEY_LOCAL_MACHINE\SOFTWARE\BBH_Custom\" & DEPLOYNAME & "\InstallationStatus", "Installed", "REG_SZ")
  myret = sh.regwrite("HKEY_LOCAL_MACHINE\SOFTWARE\BBH_Custom\" & DEPLOYNAME & "\Date", strSafeDate, "REG_SZ")
  myret = sh.regwrite("HKEY_LOCAL_MACHINE\SOFTWARE\BBH_Custom\" & DEPLOYNAME & "\Time", strSafeTime, "REG_SZ") 
 '# ========================= BEGIN CUSTOM ACTIONS HERE =================================================================================
 '# Add any custom action that you want to perform after successful here. This will ensure that these will only be created after a successful install and not everytime
 '# Example of custom actions :: Deleting/Creating shortcts, Appending specific files, creating/deleting directories etc 
 '# ========================= END CUSTOM ACTIONS HERE ================================================================================= 
 Else
  '# If the install failes with error code other than 0 or 3010, script will quit with appropriate exit code. Script will stop running here
  mylog =  WriteLogFileLine(SETUPLOG,"Installation Failed and Resullt is:: " & myret)
  mylog =  WriteLogFileLine(SETUPLOG,"Please Verify MSILOG for additional details which is located at:: " & MSILOG )
  wscript.quit(myret)
 End If
Else
 ''# If the setup file (MYFILE) does not exist, script will quit with exit code 1615 (this can be changed as per your needs). Script will stop running here
 mylog =  WriteLogFileLine(SETUPLOG,"Setup File " & quote & MYFILE & quote & " does not exist. Install Failed and Exiting!!!")
 myret = 1615
 wscript.quit(myret)
End If
'# ========================================= USER SCRIPTS ======================================================================================================================================
 '#Change to yes if you want to use Active Setup
 '#This same section can be done in the msi. This runs as logged in user and if they restricted privileges, some of the actions you want done may not be possible
 USERSCRIPTS = "NO"
 If USERSCRIPTS = "YES" Then
  mylog =  WriteLogFileLine(SETUPLOG,"USERSCRIPTS section selected. Activating activesetup")
  myret = sh.run("cmd.exe /c RD /S /Q " & quote & "C:\TEMP\" & DEPLOYNAME & quote,1,True)
  If not fs.folderexists("C:\TEMP\" & DEPLOYNAME) then fs.createfolder("C:\TEMP\" & DEPLOYNAME)
  myret = sh.run("cmd.exe /c echo a|XCOPY " & quote & CURRENTDIR & "\userfiles\*.*" & quote & " " & quote & "C:\TEMP\" & DEPLOYNAME & "\*.*" & quote & " /s /q",1,True)
  mylog =  WriteLogFileLine(SETUPLOG,"Copying user files")
  myret = sh.run("cmd.exe /c " & quote & "C:\Temp\" & DEPLOYNAME & "\user.vbs",1,True)
  myret = sh.regwrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components\" & DEPLOYNAME & "\StubPath", quote & "C:\Temp\" & DEPLOYNAME & "\user.vbs" & quote, "REG_SZ")
  'If you are redeploying the application, increase the version number in below script. This way, application will know that it neeeds to re-run the active setup script   
  myret = sh.regwrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Active Setup\Installed Components\" & DEPLOYNAME & "\Version", "1", "REG_SZ")
  mylog =  WriteLogFileLine(SETUPLOG,"Finished user file section")
 End If
'#================================================ End USER SCRIPTS ==============================================================================================================
'# ===================================== Begin Functions and other Criteria =======================================================
'# ===================================== Start Log Function ========================================================================
Function WriteLogFileLine(sLogFileName,sLogFileLine)
    dateStamp = Now()
 Set OFS = CreateObject("Scripting.FileSystemObject")
 Set logfile = OFS.OpenTextFile(sLogFileName, 8, True)
    logfile.WriteLine(cstr(dateStamp) + " - " + sLogFileLine)
    logfile.Close
    Set logfile = Nothing
    Set OFS = Nothing
End Function
'# ======================================= End Log Function =====================================================================
'# =========================== Function to get OS Language for the application to install ========================================
FUNCTION LANGUAGE()
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery ("Select * from Win32_OperatingSystem")
For Each objOperatingSystem in colOperatingSystems
LANGUAGE = objOperatingSystem.OSLanguage
Next
End Function
'# =========================== End Function to get OS Language for the application to install ========================================
'# =========================== Function to get OS Architecture ========================================
Function OsAchitecture ()
    On Error Resume Next
    Dim WshShell
    Set WshShell = CreateObject("WScript.Shell")
    OsAchitecture = WshShell.RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_OsAchitectureITECTURE")
    On Error Goto 0
End Function
'# =========================== End Function to get OS Architecture ========================================
'# =========================== BEGIN FINDUNINSTALL Function to get previous versions of the software ========================================
Function FINDUNINSTALL(strsoft)
const HKEY_LOCAL_MACHINE = &H80000002
strComputer = "."
Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
strKeyPath = "software\wow6432node\microsoft\windows\currentversion\uninstall" 'OR strKeyPath = "software\microsoft\windows\currentversion\uninstall"' Root level
oReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys
For Each subkey In arrSubKeys
On Error Resume Next
sDisplayName = Sh.Regread("HKLM\" & strKeyPath & "\" & subkey & "\Displayname")
If instr(lcase(sDisplayName), lcase(strsoft)) > 0 then
 sUninstallString = Sh.Regread("HKLM\" & strKeyPath & "\" & subkey & "\uninstallstring")
 If instr(lcase(sUninstallString), "msiexec") Then
 mylog =  WriteLogFileLine(SETUPLOG,"Found previous version of the package:: " & subkey)
 mylog =  WriteLogFileLine(SETUPLOG,"Beginning uninstalling previous version:: " & subkey)
 myret = sh.run("cmd.exe /c msiexec /X " & subkey & " /qn REBOOT=ReallySuppress /l*v " & quote & UNLOG & quote,1,True)
 If myret = 0 OR myret = 3010 Then
  mylog =  WriteLogFileLine(SETUPLOG,"Successfully uninstalled previous version!!!  Exit Code returned is :: " & myret)
 Else
  mylog =  WriteLogFileLine(SETUPLOG,"Uninstalling previous version failed!! Exit code for uninstall is :: " & myret)
  wscript.quit(myret)
 End If
 End If
end if
Next
Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
strKeyPath = "software\microsoft\windows\currentversion\uninstall" ' Root level
oReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys
For Each subkey In arrSubKeys
On Error Resume Next
sDisplayName = Sh.Regread("HKLM\" & strKeyPath & "\" & subkey & "\Displayname")
if instr(lcase(sDisplayName), lcase(strsoft)) > 0 then
 sUninstallString = Sh.Regread("HKLM\" & strKeyPath & "\" & subkey & "\uninstallstring")
 If instr(lcase(sUninstallString), "msiexec") Then
 mylog =  WriteLogFileLine(SETUPLOG,"Found previous version of the package:: " & subkey)
 mylog =  WriteLogFileLine(SETUPLOG,"Beginning uninstalling previous version:: " & subkey)
 myret = sh.run("cmd.exe /c msiexec /X " & subkey & " /qn REBOOT=ReallySuppress /l*v " & quote & UNLOG & quote,1,True)
 If myret = 0 OR myret = 3010 Then
  mylog =  WriteLogFileLine(SETUPLOG,"Successfully uninstalled previous version!!!  Exit Code returned is :: " & myret)
 Else
  mylog =  WriteLogFileLine(SETUPLOG,"Uninstalling previous version failed!! Exit code for uninstall is :: " & myret)
  wscript.quit(myret)
 End If
 End If
end if
Next
End Function
'# =========================== END FINDUNINSTALL Function to get previous versions of the software ========================================
'# ===================================== End Functions =======================================================
'##==============================================================================
'##  END OF FILE
'##==============================================================================