Oracle Java, ruleset.xml and signing deploymentruleset.jar

Since Java 7 Update 51 Oracle has tighten the Java security. From now on only predefined sites are allowed to run, otherwise users will get all kind of warnings.
Fortunately the most warnings can be suppressed. In this article I will describe what admins can do.

Fortunately Oracle has described what can be done:

  1. Introducing Deployment Rule Sets
  2. Deployment Rule Set

The following steps need to be performed:

  1. Create a ruleset.xml
  2. Create a DeploymentRuleSet.jar from the ruleset.xml
  3. Sign the DeploymentRuleSet.jar with a self created certificate
  4. Copy the signed DeploymentRuleSet.jar, deployment.properties and deployment.config files to %windir%\sun\java\deployment.

The steps in detail:

In this example I will use Java 8 Update 151. That was the most recent version at the time of writing this article.

  1. Download Java JRE 8 Update 151 (offline installer) from Java Downloads for All Operating Systems.

    jre-8u151-windows-i586.exe

  2. Download Java JDK as the same version as the Java Runtime Engine from Java SE Development Kit 8 Downloads.

    jdk-8u151-windows-i586.exe

  3. Use 7Zip to extract the content of the file jdk-8u151-windows-i586.exe. You will get a ‘tools.zip’ folder.
  4. Extract the following files from the tools.zip file and copy them to a new folder:
    Folder PATH listing for volume Windows
    Volume serial number is 00000072 D689:C60A
    << Folder does not matter >>
    +---bin
    |       jar.exe
    |       jarsigner.exe
    |       jli.dll
    |       keytool.exe
    |       msvcr100.dll
    |       ruleset.xml
    |       
    \---lib
            tools.jar
    
  5. Create the ruleset.xml in the ‘bin’ folder (this one is an example grabbed from the Oracle Website):
    
    
    
        
        
          
        
        
      
    
      
        
        
      
    
      
        
        
      
    
      
        
        
      
    
      
        
        
          Blocked by corporate. Contact J. Smith, smith@host.example.com, if you need to run this app.
        
      
    
     
    
  6. Install Java 8 Update 151
  7. Run the following commands in the bin folder:
    cd "%~dp0\bin"
    keytool -keystore "C:\Program Files (x86)\Java\jre1.8.0_151\lib\security\cacerts" -storepass changeit -delete -alias DummyCompany
    jar.exe -cvf DeploymentRuleSet.jar ruleset.xml
    keytool -genkeypair -dname "cn=cnDummyCompany, ou=ouDummyCompany, o=oDummyCompany, c=EU" -alias DummyCompany -keypass Th!sH3lpsM3AL0t -keystore CA.jks -storepass Th!sH3lpsM3AL0t -validity 99999
    keytool -exportcert -keystore CA.jks -alias DummyCompany -file CA.cer -storepass Th!sH3lpsM3AL0t
    REN CA.cer CA.pem
    keytool -importcert -keystore "C:\Program Files (x86)\Java\jre1.8.0_151\lib\security\cacerts" -storepass changeit -file CA.pem -alias DummyCompany -noprompt
    jarsigner -verbose -keystore CA.jks -sigalg SHA256withDSA -signedjar DeploymentRuleSet.jar DeploymentRuleSet.jar DummyCompany -storepass Th!sH3lpsM3AL0t -tsa http://timestamp.digicert.com
    jarsigner -verify DeploymentRuleSet.jar
    copy DeploymentRuleSet.jar "C:\Windows\sun\java\deployment" /Y
    
  8. Create the following 2 files in C:\Windows\sun\java\deployment
    deployment.properties

    deployment.javaws.autodownload.locked= 
    deployment.javaws.autodownload=NEVER
    deployment.expiration.check.enabled=false
    deployment.expiration.decision.suppression=true
    deployment.expiration.decision=NEVER
    deployment.insecure.jres=ALWAYS
    deployment.security.level.locked
    deployment.security.level=HIGH
    deployment.user.security.exception.sites=C\:\\Windows\\Sun\\Java\\Deployment\\exception.sites
    deployment.user.security.exception.sites.locked
    deployment.security.mixcode.locked
    deployment.security.mixcode=HIDE_RUN
    deployment.webjava.enabled.locked
    deployment.webjava.enabled=true
    

    deployment.config

    deployment.system.config=file\:C\:/WINDOWS/Sun/Java/Deployment/deployment.properties
    deployment.system.config.mandatory=false
    
  9. Open Java Console and check the installation:

    Valid DeploymentRuleset


    Certificate details

The vb-script

The vbscript checks if there is a working network connection. That is needed as the certificate needs to be validated. See my blog article Check if there is a working internet connection when a firewall blocks ping requests for more information.

The vbscripts.

' ================================================================================================
' Installs Java certificates and installs deploymentruleset.jar
' Created by Willem-Jan Vroom
' Version history:
'
' 0.0.1
'  - Initial version
'
' 1.0.0
'  - Final version
'
' 1.0.1
'  - Checks if the folder %ProgramFiles%\Java\jre7 or %ProgramFiles(x86)%\Java\jre exits.
'    If not then quit.
'  - The file 'cacerts' will not be copied to the 'files_for_gpo' folder.
'
' 1.0.2
'  - Checks if run with elevated rights or admin rights
'  - Displays warnings on the screen (can be suppressed)
'  - Script cannot be run from a network share.
'
' 1.0.3
'  - Gets the installdir from the registry
'
' 1.0.4
'  - Output from the various commands to the log file. Useful for troubleshooting.
'
' Usuage:
'  - Create_and_install_Java_Certificates_v100.vbs
'    Creates the needed files in the default locations. Sufficient for a local installation
'
'  - Create_and_install_Java_Certificates_v100.vbs /remove
'    Removes the %windir%\Sun\java\development folder.
'
'  - Create_and_install_Java_Certificates_v100.vbs /gpo
'    Creates the files in the folder 'files_for_gpo'. These files can be copied to the users'
'    workstation.
'      
' ================================================================================================

' ------------------------------------------------------------------------------------------------
' Declare the most variables. 
' ------------------------------------------------------------------------------------------------

  Option Explicit

  Dim objShell                   : set objShell               = WScript.CreateObject("WScript.Shell")
  Dim objLogFileFSO              : Set objLogFileFSO          = CreateObject("Scripting.FileSystemObject")
  Dim objFSO                     : Set objFSO                 = CreateObject("Scripting.FileSystemObject")
  Dim objProcessEnv              : Set objProcessEnv          = objShell.Environment("PROCESS")
  Dim objWMIService              : Set objWMIService          = GetObject("winmgmts:\\.\root\cimv2")
  Dim fn_objWMIService           : Set fn_objWMIService       = GetObject("winmgmts:\\.\root\cimv2")
  Dim objReg                     : Set objReg                 = GetObject("winmgmts:\\.\root\default:StdRegProv")
  Dim objLogFile
  Dim CurrentDir                 : CurrentDir                 = Left(Wscript.ScriptFullname, InstrRev(Wscript.ScriptFullname, "\"))
                                   CurrentDir                 = Left(CurrentDir,len(CurrentDir)-1)
  Dim strcomputerName            : strcomputerName            = objProcessEnv("COMPUTERNAME")
  Dim strLogLocation             : strLogLocation             = "C:\WINDOWS\system32\Logfiles"
  Dim strOutputFile              : strOutputFile              = strLogLocation & "\" & strcomputerName & "_Installation_JavaCertificates_" & Replace(FormatDateTime(Now(), 2),"/","-") & ".log"
  Dim strArchitecture            : strArchitecture            = ""
  Dim strOS                      : strOS                      = ""
  Dim strCommand                 : strCommand                 = ""
  Dim strLine                    : strLine                    = ""
  Dim strQuery                   : strQuery                   = ""
  Dim strProgramFilesFolder      : strProgramFilesFolder      = ""
  Dim strExceptionSite           : strExceptionSite           = "" 
  Dim strErrorText               : strErrorText               = ""
  Dim strDeploymentRuleSetFolder : strDeploymentRuleSetFolder = objShell.ExpandEnvironmentStrings("%windir%") & "\sun\java\deployment"
  Dim strMemberOfGroups          : Set strMemberOfGroups      = objshell.Exec("whoami /groups")
  Dim MemberOfGroupsOutput       : Set MemberOfGroupsOutput   = strMemberOfGroups.StdOut
  Dim strMemberOfGroupsOutput    : strMemberOfGroupsOutput    = MemberOfGroupsOutput.ReadAll
  Dim bolPreReqPassed            : bolPreReqPassed            = True
  Dim strJavaExeFileVersion
  Dim strJarsignerExeFileVersion
  Dim strWebsite                 : strWebsite                 = "http://www.google.com"

  Dim colItems, objItem
  Dim valOSBuildNumber,valResult
  Dim arrArguments, valCounter
  Dim strKeyPath, strValueName, strValue, strCurrentVersion, strJavaHome

  Const ForWriting               = 2
  Const ForReading               = 1
  Const ForAppending             = 8
  Const OverWriteFiles           = True
  const HKEY_CURRENT_USER        = &H80000001
  const HKEY_LOCAL_MACHINE       = &H80000002
  Const HKEY_USERS               = &H80000003
  Const blnDebug                 = True

  Const strAlias                 = "DummyCompany"
  Const strPassword              = "changeit"
  Const strCN                    = "cnDummyCompany"
  Const strOU                    = "ouDummyCompany"
  Const strO                     = "oDummyCompany"
  Const strC                     = "EU"
  
  Const bolDisplayErrorsOnScreen = True

' ------------------------------------------------------------------------------------------------
' Checks if run with admin or elevated permissions. If not, then quit.
' ------------------------------------------------------------------------------------------------

  if InStr(strMemberOfGroupsOutput, "S-1-16-12288") = 0 AND InStr(strMemberOfGroupsOutput, "S-1-5-32-544") = 0 Then
     strErrorText = "You need to run this script with administrator or with elevated rights."
     ShowErrorOnScreen(strErrorText)
     wscript.quit(3)
  End if

' ------------------------------------------------------------------------------------------------
' Create the log location (if not exists)
' Open the logfile.  
' ------------------------------------------------------------------------------------------------

  CreateFolderStructure(strLogLocation)
  OpenLogFile()
  WriteToLog "- ACTION: script started."

' ------------------------------------------------------------------------------------------------
' Detect the current OS.  
' ------------------------------------------------------------------------------------------------

  Set colItems = objWMIService.ExecQuery("Select Caption,BuildNumber from Win32_OperatingSystem")
  For Each objItem in colItems
      strOS            = objItem.Caption
      valOSBuildNumber = objItem.BuildNumber
  next

' ------------------------------------------------------------------------------------------------
' Detect the current processor architecture.  
' ------------------------------------------------------------------------------------------------

  if objFSO.FolderExists(objShell.ExpandEnvironmentStrings("%windir%") & "\SysWOW64\Config") then  
     strArchitecture = "x64"
     strProgramFilesFolder=objProcessEnv("ProgramFiles(x86)")
       else
     strArchitecture = "x86"
     strProgramFilesFolder=objProcessEnv("ProgramFiles")
  end if

  WriteToLog("########## Details regarding operating system                        ##########")
  WriteToLog("Found Operating System:       " & strOS)
  WriteToLog("Found architecture:           " & strArchitecture)
  WriteToLog("########## End details regarding operating system                    ##########")
  WriteToLog(" ")

' ------------------------------------------------------------------------------------------------
' Sets SEE_MASK_NOZONECHECKS to 1.  
' That will avoid a screen that asks for permission to run an application from
' a share or mapped drive. 
' ------------------------------------------------------------------------------------------------

  objProcessEnv("SEE_MASK_NOZONECHECKS") = 1

' ------------------------------------------------------------------------------------------------
' Checks the prereqs:
'  - No UNC path
'  - Java Runtime Engine has been installed.
' ------------------------------------------------------------------------------------------------

  WriteToLog("########## Checking the pre-requirements                             ##########")

  if left(CurrentDir, 2) = "\\" Then
     strErrorText = "This script cannot run from an UNC path."
     WriteToLog (strErrorText)
     ShowErrorOnScreen(strErrorText)
     bolPreReqPassed  = false
  end if

  strKeyPath   = "SOFTWARE\JavaSoft\Java Runtime Environment"
  if strArchitecture = "x64" Then
     strKeyPath   = "SOFTWARE\Wow6432Node\JavaSoft\Java Runtime Environment"
  end if
 
  strValueName = "CurrentVersion"
  objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strCurrentVersion
  if isnull(strCurrentVersion) Then
     strErrorText = "There is no Java Runtime found."
     WriteToLog (strErrorText)
     ShowErrorOnScreen(strErrorText)
     bolPreReqPassed  = False
  end if

  if bolPreReqPassed Then
     strKeyPath   = strKeyPath & "\" & strCurrentVersion
     strValueName = "JavaHome" 
     objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strJavaHome
  end if

  if bolPreReqPassed Then
     strJavaExeFileVersion      = objFSO.GetFileVersion(strJavaHome & "\bin\java.exe")
     strJarsignerExeFileVersion = objFSO.GetFileVersion(CurrentDir  & "\jarsigner.exe")
     WriteToLog("File version '" & strJavaHome & "\bin\java.exe' is: "& strJavaExeFileVersion)
     WriteToLog("File version '" & CurrentDir  & "\jarsigner.exe' is: "& strJarsignerExeFileVersion)
     if strJavaExeFileVersion = strJarsignerExeFileVersion Then
        WriteToLog("This is ok: the installation can continue.")
          else
        strErrorText = "The file versions are different. The installation is aborted now."
        WriteToLog (strErrorText)
        ShowErrorOnScreen(strErrorText)
        bolPreReqPassed  = False
     end if
  end if

  if bolPreReqPassed Then
     strCommand = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File " & chr(34) & CurrentDir & "\CheckIfWebsiteIsReachable_with_vbscript.ps1" & chr(34) & " -URL "& strWebsite
     valResult = objShell.Run(strCommand, 0, True)
     WriteToLog("The command '" & strCommand & "' returns " & valResult & ".")
     if valResult = 1 Then
        strErrorText = "The website '" & strWebsite & "' could not be reached. There is no working internet connection. The installation is aborted."
        WriteToLog (strErrorText)
        ShowErrorOnScreen(strErrorText)
        bolPreReqPassed  = False
     end if
  end if

  WriteToLog("########## End checking the pre-requirements                         ##########")   

  if NOT bolPreReqPassed Then
     CloseLogFile
     wscript.quit(2)
  end if

' ------------------------------------------------------------------------------------------------
' Sets the working directory
' ------------------------------------------------------------------------------------------------

  WriteToLog(" ")
  WriteToLog("Current working directory: " & objShell.CurrentDirectory)
  objShell.CurrentDirectory = CurrentDir
  WriteToLog("New working directory:     " & objShell.CurrentDirectory)
  WriteToLog(" ")

' ------------------------------------------------------------------------------------------------
' Checks for command line options
' ------------------------------------------------------------------------------------------------

  if wscript.arguments.count > 0 Then
     Set arrArguments = wscript.arguments
     for valCounter = 0 to wscript.arguments.count - 1
        if instr(lcase(arrArguments(valCounter)),"/remove") > 0 or instr(lcase(arrArguments(valCounter)),"/uninstall") > 0 Then
           DeleteDeploymentRuleSet
           CloseLogFile
           Wscript.quit(0)
        end if
        if instr(lcase(arrArguments(valCounter)),"/gpo") > 0 Then
           strDeploymentRuleSetFolder = CurrentDir & "\files_for_gpo"
           WriteToLog("*** The files will be generated for GPO Policy ***")
        end if
     next
  end if

' ------------------------------------------------------------------------------------------------
' Uninstall whatever version has already been installed. 
' ------------------------------------------------------------------------------------------------

  DeleteDeploymentRuleSet

' ------------------------------------------------------------------------------------------------
' Start the main application. 
' ------------------------------------------------------------------------------------------------

  WriteToLog("########## Start generating Java DeployementRuleSet.xml file.        ##########")

  DeleteFile(CurrentDir & "\CA.jks")
  DeleteFile(CurrentDir & "\CA.cer")
  DeleteFile(CurrentDir & "\CA.pem")
  DeleteFile(CurrentDir & "\DeploymentRuleSet.jar")
  fnKillProcess("javaw.exe")

  DeleteFile(strDeploymentRuleSetFolder & "\exception.sites")

  CreateDefaultExceptionSiteFile

  WriteToLog("Delete the current certificate with the alias: " & strAlias)
  strCommand = "keytool -keystore " & chr(34) & strJavaHome & "\lib\security\cacerts" & chr(34)
  strCommand = strCommand & " -storepass " & strPassword & " -delete -alias " & strAlias
  if blnDebug Then
     WriteToLog("Running command: " & strCommand)
      else
     WriteToLog("Running command: " & Replace(strCommand, strPassword , "********"))
  End If
  RunCommandPlusOutput(strCommand)
  
  WriteToLog("Create DeploymentRuleSet.jar from the ruleset.xml")
  strCommand = "jar.exe -cvf DeploymentRuleSet.jar ruleset.xml"
  if blnDebug Then
     WriteToLog("Running command: " & strCommand)
      else
     WriteToLog("Running command: " & Replace(strCommand, strPassword , "********"))
  End If
  RunCommandPlusOutput(strCommand)

  WriteToLog("Create CA.jks certificate")
  strCommand = "keytool -genkeypair -dname " & chr(34) & "cn=" & strCN & ", ou=" & strOU & ", o=" & strO
  strCommand = strCommand & ", c=" & strC & chr(34) & " -alias " & strAlias
  strCommand = strCommand & " -keypass " & strPassword & " -keystore CA.jks -storepass " & strPassword & " -validity 99999"
  if blnDebug Then
     WriteToLog("Running command: " & strCommand)
      else
     WriteToLog("Running command: " & Replace(strCommand, strPassword , "********"))
  End If
  RunCommandPlusOutput(strCommand)

  WriteToLog("Create CA.cer certificate")
  strCommand = "keytool -exportcert -keystore CA.jks -alias " & strAlias & " -file CA.cer -storepass " & strPassword
  if blnDebug Then
     WriteToLog("Running command: " & strCommand)
      else
     WriteToLog("Running command: " & Replace(strCommand, strPassword , "********"))
  End If
  RunCommandPlusOutput(strCommand)

  WriteToLog("Rename CA.cer to CA.pem")
  objFSO.CopyFile CurrentDir & "\CA.cer", currentDir & "\CA.pem"
  DeleteFile(CurrentDir & "\CA.cer")

  WriteToLog("Import CA.pem")
  strCommand = "keytool -importcert -keystore " & chr(34) & strJavaHome & "\lib\security\cacerts" & chr(34)
  strCommand = strCommand & " -storepass " & strPassword & " -file CA.pem -alias " & strAlias & " -noprompt"
  if blnDebug Then
     WriteToLog("Running command: " & strCommand)
      else
     WriteToLog("Running command: " & Replace(strCommand, strPassword , "********"))
  End If
  RunCommandPlusOutput(strCommand)

  WriteToLog("Sign CA.jks")
  strCommand = "jarsigner -verbose -keystore CA.jks -sigalg SHA256withDSA -signedjar "
  strCommand = strCommand & "DeploymentRuleSet.jar DeploymentRuleSet.jar " & strAlias & " -storepass " & strPassword & " -tsa http://timestamp.digicert.com"
  if blnDebug Then
     WriteToLog("Running command: " & strCommand)
      else
     WriteToLog("Running command: " & Replace(strCommand, strPassword , "********"))
  End If
  RunCommandPlusOutput(strCommand)

  WriteToLog("Sign DeploymentRuleSet.jar")
  strCommand = "jarsigner -verify -verbose DeploymentRuleSet.jar"
  if blnDebug Then
     WriteToLog("Running command: " & strCommand)
      else
     WriteToLog("Running command: " & Replace(strCommand, strPassword , "********"))
  End If
  RunCommandPlusOutput(strCommand)

  WriteToLog("Create the folder '" & strDeploymentRuleSetFolder & "' (if not already exists)") 
  CreateFolderStructure(strDeploymentRuleSetFolder)

  WriteToLog("Delete any existing 'DeploymentRuleSet.jar'")
  DeleteFile(strDeploymentRuleSetFolder & "\DeploymentRuleSet.jar")
  
  WriteToLog("Copy the new 'DeploymentRuleSet.jar' to '" & strDeploymentRuleSetFolder & "'.")
  objFSO.CopyFile CurrentDir & "\DeploymentRuleSet.jar", strDeploymentRuleSetFolder & "\"
  WriteToLog("########## End generating Java DeployementRuleSet.xml file.          ##########")
  WriteToLog(" ")
  WriteToLog("########## Copying deployment.config and deployment.properties.      ##########")

  objFSO.CopyFile CurrentDir & "\Main files\deployment.config"    , strDeploymentRuleSetFolder & "\" 
  objFSO.CopyFile CurrentDir & "\Main files\deployment.properties", strDeploymentRuleSetFolder & "\"
  objFSO.CopyFile CurrentDir & "\Main files\exception.sites"      , strDeploymentRuleSetFolder & "\"

  WriteToLog("########## End copying deployment.config and deployment.properties.  ##########")

  WriteToLog("########## Performing after installation checks.                     ##########")
  
  if fnAfterInstallationCheck Then
     WriteToLog("The deployment ruleset has been processed successfully.")
      else
     WriteToLog("There was an error while processing the deployment ruleset. The files where not copied to")
     WriteToLog("the folder '" & strDeploymentRuleSetFolder &"'.")
  end if

  WriteToLog("########## End performing after installation checks.                 ##########")


  CloseLogFile

Sub OpenLogFile() 

' ------------------------------------------------------------------------------------------------
' Subroutine: OpenLogFile() 
' The name of the logfile is mentinoed in the variabele strOutputFile.
' ------------------------------------------------------------------------------------------------

  If objLogFileFSO.FileExists(strOutputFile) Then
     Set objLogFile = objLogFileFSO.OpenTextFile(strOutputFile, ForWriting)
         Else
     Set objLogFile = objLogFileFSO.CreateTextFile(strOutputFile)
  End If

End Sub

Sub CloseLogFile()

' ------------------------------------------------------------------------------------------------
' Subroutine: CloseLogFile()
' Close the log file.
' ------------------------------------------------------------------------------------------------

  WriteToLog "- ACTION: script ended."
  objLogFile.Close
  Set objLogfileFSO = Nothing

End Sub

Function WriteToLog(sLogMessage)

' ------------------------------------------------------------------------------------------------
' Function: WriteToLog(sLogMessage)
' Writes an entry 'sLogMessage' in the logfile.
' ------------------------------------------------------------------------------------------------

  if instr(sLogMessage, "- ACTION: ") = 0 then sLogMessage = "          " & sLogMessage
  objLogFile.WriteLine("Time: " & now & "  " & sLogMessage)

End Function

Sub CreateFolderStructure(strFolderNameToBeCreated)

' ------------------------------------------------------------------------------------------------
' Subroutine: CreateFolderStructure(strFolderNameToBeCreated)
' Creates the map as mentioned in strFolderNameToBeCreated.
' ------------------------------------------------------------------------------------------------

  Dim arrFoldersTMP : arrFoldersTMP = split (strFolderNameToBeCreated,"\")
  Dim strFolder     : strFolder     = ""
  Dim objFolderTMP
 
  For Each objFolderTMP in arrFoldersTMP
      strFolder = strFolder & objFolderTMP
      If NOT objFSO.FolderExists(strFolder) Then
             objFSO.CreateFolder(strFolder)
      end If
      strFolder = strFolder & "\"
  Next
 
End Sub

Function RunCommandPlusOutput(strCommand)

' ------------------------------------------------------------------------------------------------
' Function: RunCommandPlusOutput(strCommand)
' Runs the command strCommand and returns the outpunt in RunCommandPlusOutput
' ------------------------------------------------------------------------------------------------

  Dim strResultsOfExecCommand          : Set strResultsOfExecCommand        = objshell.Exec(strCommand)
  Dim objResultsOfExecCommandOutput    : Set objResultsOfExecCommandOutput  = strResultsOfExecCommand.StdOut
  Dim strResultsOfExecCommandOutput    : strResultsOfExecCommandOutput      = objResultsOfExecCommandOutput.ReadAll
  strResultsOfExecCommandOutput = vbCrLf & vbCrLf & "---    Result of Running Comand ---   "& vbCrLf & strResultsOfExecCommandOutput
  strResultsOfExecCommandOutput = strResultsOfExecCommandOutput & "---  End result of running command --- " & vbCrLf
  WriteToLog (strResultsOfExecCommandOutput)

End Function


Function DeleteFile(strFileName)

' ------------------------------------------------------------------------------------------------
' Function: DeleteFile(strFileName)
' Deletes the given file
' ------------------------------------------------------------------------------------------------

  if objFSO.FileExists(strFileName) Then
     objFSO.DeleteFile(strFileName)
     WriteToLog("The file '" & strFileName & "' has been deleted.")
  end if

End Function 

Function fnKillProcess(strProcessName)

' ------------------------------------------------------------------------------------------------
' Function: fnKillProcess(strProcessName)
' Terminates the given processname.
' ------------------------------------------------------------------------------------------------

  Dim colProcess
  Dim objProcess

  Set colProcess = fn_objWMIService.ExecQuery ("Select * From Win32_Process")
  For Each objProcess In colProcess
    If Instr(LCase(objProcess.Name),LCase(strProcessName)) > 0 Then
       objShell.Run "TASKKILL /F /T /IM " & objProcess.Name, 0, False
       objProcess.Terminate()
       WriteToLog("Terminating application: " & objProcess.Name)
    End If
  Next

End Function



Sub CreateDefaultExceptionSiteFile

' ------------------------------------------------------------------------------------------------
' Subroutine: CreateDefaultExceptionSiteFile
' Create the default content for the exception.site file.
' ------------------------------------------------------------------------------------------------

  strExceptionSite = ""

End Sub

Sub DeleteDeploymentRuleSet

' ------------------------------------------------------------------------------------------------
' Subroutine: DeleteDeploymentRuleSet
' Deletes the folder %Windir%\sun\java\deployment
' ------------------------------------------------------------------------------------------------

  WriteToLog("########## Delete deploymentruleset from the system.                 ##########")

  if objFSO.FolderExists(strDeploymentRuleSetFolder) Then
     objFSO.DeleteFolder(strDeploymentRuleSetFolder)
     WriteToLog("The folder '" & strDeploymentRuleSetFolder & "' has been deleted successfully.")
  end if

  WriteToLog("Delete the current certificate with the alias: " & strAlias)
  strCommand = "keytool -keystore " & chr(34) & strJavaHome & "\lib\security\cacerts" & chr(34)
  strCommand = strCommand & " -storepass " & strPassword & " -delete -alias " & strAlias
  WriteToLog("Running command: " & Replace(strCommand, strPassword , "********"))
  RunCommandPlusOutput(strCommand)

  WriteToLog("########## End deleting deploymentruleset from the system.           ##########")

End Sub

Sub ShowErrorOnScreen(strErrorTextToShow)

' ------------------------------------------------------------------------------------------------
' Subroutine: ShowErrorOnScreen
' Shows an error message on the screen if allowd
' ------------------------------------------------------------------------------------------------

  if bolDisplayErrorsOnScreen Then
     msgbox strErrorTextToShow,16,"Error while creating and installing Java Certificate."
  end if

End Sub

Function fnAfterInstallationCheck

' ------------------------------------------------------------------------------------------------
' function: fnAfterInstallationCheck
' Checks if all files are in C:\Windows\Sun\Java\Deployment
' ------------------------------------------------------------------------------------------------

  fnAfterInstallationCheck = True
  
  if NOT objFSO.FileExists(strDeploymentRuleSetFolder & "\DeploymentRuleSet.jar") Then 
     writeToLog("### FATAL ERROR: The file '" & strDeploymentRuleSetFolder & "\DeploymentRuleSet.jar' does not exists!")
     fnAfterInstallationCheck = False
  End if

  if NOT objFSO.FileExists(strDeploymentRuleSetFolder & "\deployment.config") Then 
     writeToLog("### FATAL ERROR: The file '" & strDeploymentRuleSetFolder & "\deployment.config' does not exists!")
     fnAfterInstallationCheck = False
  End if

  if NOT objFSO.FileExists(strDeploymentRuleSetFolder & "\deployment.properties") Then 
     writeToLog("### FATAL ERROR: The file '" & strDeploymentRuleSetFolder & "\deployment.properties' does not exists!")
     fnAfterInstallationCheck = False
  End if

End Function

Group policy

If you run this script with the parameter /gpo then there will be a new folder created ‘files_for_gpo’. With a GPO setting, the files in that folder can be copied to %windir%\sun\java\deployment.
More information can be found in this article: Centralized Management of Java SE Environment Using GPO (Redux).

The screen prints below are created while following the guidelines in the above mentioned post.

Start Group Policy Management Console

Start Group Policy Management Console

Create new WMI query

Create new WMI query

Define the name

Define the name

Enter the query: Select * From win32_Directory where (name="c:\\Program Files\\Java\\jre7" or name="c:\\Program Files (x86)\\Java\\jre7")

Enter the query: Select * From win32_Directory where (name=”c:Program FilesJavajre7″ or name=”c:Program Files (x86)Javajre7″)

Click Save to save the query

Click Save to save the query

Specify the folder to be created

Specify the folder to be created

Specify the source and destination file

Specify the source and destination file

  • The source file will be:
    \\demoforest\sysvol\demoforest.local\JavaScripts\deployment.config
  • The destination file will be:
    %windir%\sun\java\deployment\deployment.config

Do the same for the other 3 files.

The same for all other files

The same for all other files

Apply the WMI filter to the GPO.

Apply the WMI filter to the GPO.

The files at the correct location on the client.

The files at the correct location on the client.

And the policy is also applied on the client.

And the policy is also applied on the client.

The whole package (excluding jre1.8.0_151.msi) can be downloaded here.




Check if there is a working internet connection when a firewall blocks ping requests

Sometimes you need to check if there is a working internet connection. You can use the
pingcommand for that. But this command does not work if ICMP echo request have disabled on the firewall. If this is the case we have to check the status of a website. If the status is 200 then there is a working internet connection.

In this example I will use both vbscript and powershell to check if there is a working internet connection.

The basics

  1. The command Invoke-WebRequest -Uri www.google.com -TimeoutSec 1 -UseBasicParsing gives a lot of internet about the webpage. Pay attention to the statuscode.

    Invoke-WebRequest -Uri www.google.com -TimeoutSec 1 -UseBasicParsing

  2. The command (Invoke-WebRequest -Uri www.google.com -TimeoutSec 1 -UseBasicParsing).StatusCode returns only the statuscode.

    (Invoke-WebRequest -Uri www.google.com -TimeoutSec 1 -UseBasicParsing).StatusCode

  3. There is an error message if there is no working internet connection.

    Invoke-WebRequest -Uri www.google.com -TimeoutSec 1 -UseBasicParsing
    With no working internet connection.

  4. If there is a working internet connection then the script returns 200.

    Try {(Invoke-WebRequest -Uri www.google.com -TimeoutSec 1 -UseBasicParsing).StatusCode} Catch {Write-Host “Error!!!”}
    Working internet connection.

  5. In this case there is no working internet connection, so an error message is shown.

    Try {(Invoke-WebRequest -Uri www.google.com -TimeoutSec 1 -UseBasicParsing).StatusCode} Catch {Write-Host “Error!!!”}
    No working internet connection.

Further testing with PowerShell

<#
.NOTES
===========================================================================
Created with:     Windows PowerShell ISE
Created on:       21-October-2017
Created by:       Willem-Jan Vroom
Organization:     
Filename:         CheckIfWebsiteIsReachable.ps1
===========================================================================
.DESCRIPTION:

It checks if there is a working internet connection by reading the webpage.
This is very usefull in case the ping command does not work when ICMP echo
requests are disabled on the firewall.

#>
param ($URL)
Function Get-StatusCodeFromWebsite
{
  param($Website)
  Try
   {
    (Invoke-WebRequest -Uri $Website -TimeoutSec 1 -UseBasicParsing).StatusCode
   }
  Catch
   {
   }
}

$URL = "www.google.com"
$Result = Get-StatusCodeFromWebsite -Website $URL
if($Result -eq 200)
 {
  Write-Host "The website $URL is reachable."
 }
 else
 {
  Write-Host "The website $URL is not reachable."
 }

Result if there is a working internet connection.

Result if there is no working internet connection.

The next step: use vbscript and powershell to detect if there is a working internet connection

As far as I know vbscript has not the option to detect the status from a website. So we use the powershell function with vbscript to detect if there is a working internet connection.

The powershell script has changed a little bit:

<#
.NOTES
===========================================================================
Created with:     Windows PowerShell ISE
Created on:       21-October-2017
Created by:       Willem-Jan Vroom
Organization:     
Filename:         CheckIfWebsiteIsReachable_with_vbscript.ps1
===========================================================================
.DESCRIPTION:

It checks if there is a working internet connection by reading the webpage.
This is very usefull in case the ping command does not work when ICMP echo
requests are disabled on the firewall.

#>
Param ($URL)
Function Get-StatusCodeFromWebsite
{
  param($Website)
  Try
   {
    (Invoke-WebRequest -Uri $Website -TimeoutSec 1 -UseBasicParsing).StatusCode
   }
  Catch
   {
   }
}

$Result = Get-StatusCodeFromWebsite -Website $URL
if($Result -eq 200)
 {
  Exit 0
 }
 else
 {
  Exit 1
 }

It exits with an exit code:
0 = success
1 = failure

And we use vbscript to check:

' ================================================================================================
' Check if a there is a working network connection. Do not use ping, as the ping command cannot
' bu used in case ICMP echo requests have been disabled on the firewall.
' Created by Willem-Jan Vroom
' Version history:
'
' 0.0.1
'  - Initial version
'
' 1.0.0
'  - Final version
' ================================================================================================

' ------------------------------------------------------------------------------------------------
' Declare the most variables. 
' ------------------------------------------------------------------------------------------------
 
  Option Explicit

  Dim objShell      : set objShell   = WScript.CreateObject("WScript.Shell")
  Dim strWebsite    : strWebsite     = "http://www.vroom.cc"
  Dim strCurrentDir : strCurrentDir  = Left(Wscript.ScriptFullname, InstrRev(Wscript.ScriptFullname, "\"))
  Dim strCommand    : strCommand     = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File " & chr(34) & strCurrentDir & "CheckIfWebsiteIsReachable_with_vbscript.ps1" & chr(34) & " -URL "& strWebsite
  Dim strText       : strText        = ""
  Dim valResult     : valResult      = 0

' ------------------------------------------------------------------------------------------------
' Check the website that is mentioned in the string strWebsite. 
' Use the exitcode from the powershell script:
'  0 = Success
'  1 = Failure
' ------------------------------------------------------------------------------------------------

  valResult = objShell.Run(strCommand, 6, True)
  if valResult = 0 Then 
     strText = "The website '" & strWebSite & "' could be reached"
       else
     strText = "The website '" & strWebSite & "' could not be reached"
  end if

' ------------------------------------------------------------------------------------------------
' Display a message box with the result. 
' ------------------------------------------------------------------------------------------------

  msgbox strText,0,"The result."

In this example we try the webpage http://www.vroom.cc/.

Result if there is a working internet connection.

Result if there is no working internet connection.

You can download the scripts in a ZIP file.




How to save money on Oracle Java Client Licenses

Oracle has multiple software for Java Clients. You can use the Enterprise version (JEE), but also the Runtime Engine (JRE). There is one big difference: you have to pay for the commercial use of the JEE. But I will give a work around that will save you money!

  1. On the Licensing and Distribution FAQs you find additional license information about the Java Runtime Engine:

    Yes, you may make unlimited copies for internal use for the purpose of running applications on Java-enabled general purpose desktop computers and servers.

    No, you may make unlimited copies for internal use for the purpose of running applications on Java-enabled general purpose desktop computers and servers.

  2. However, the JEE has different license conditions. It is mentioned on the Java Platform, Standard Edition MSI Enterprise JRE Installer Guide:

    The MSI Enterprise JRE Installer requires a commercial license for use in production.

However, there is a work around. Use the regular JRE installation instead.

  1. Download the latest JRE from Java Downloads for All Operating Systems.
  2. Run the installer, but stop when this screen appears:

    Installation screen

  3. The MSI is extracted from the installer in one of the subfolders of C:\Users\%UserName%\AppData\LocalLow\Oracle\Java.
  4. Quit the installer.
  5. Use Orca to create a transform file, based on the MSI. In this case it is jre1.8.0_151.msi.

    Orca

    Orca

  6. And the enterprise version is not used:

    Orca – enterprise no.

  7. A vbscript to uninstall previous versions and install the latest version

    ' ================================================================================================
    ' Installs Java Runtime 8 Update 151
    ' Created by Willem-Jan Vroom
    ' Version history:
    '
    ' 1.0.0
    '   Initial version
    ' 
    ' ================================================================================================
    
    
    ' ------------------------------------------------------------------------------------------------
    ' Declare the most variables. 
    ' ------------------------------------------------------------------------------------------------
    
      Option Explicit
    
      Dim objShell                          : set objShell                      = WScript.CreateObject("WScript.Shell")
      Dim objNetWork                        : set objNetWork                    = Wscript.CreateObject("WScript.Network")
      Dim objLogFileFSO                     : Set objLogFileFSO                 = CreateObject("Scripting.FileSystemObject")
      Dim objFSO                            : Set objFSO                        = CreateObject("Scripting.FileSystemObject")
      Dim objProcessEnv                     : Set objProcessEnv                 = objShell.Environment("PROCESS")
      Dim objFolder
      Dim objFile
      Dim colFiles
      Dim objWMIService                     : Set objWMIService                 = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
      Dim fn_objWMIService                  : Set fn_objWMIService              = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
      Dim objReg                            : Set objReg                        = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
      Dim objLogFile
      Dim colListOfServices
      Dim objService 	
      Dim strCurrentDir                     : strCurrentDir                     = Left(Wscript.ScriptFullname, InstrRev(Wscript.ScriptFullname, "\"))
                                              strCurrentDir                     = Left(strCurrentDir,len(strCurrentDir)-1)
      Dim strcomputerName                   : strcomputerName                   = objProcessEnv("COMPUTERNAME")
      Dim strLogLocation                    : strLogLocation                    = "C:\WINDOWS\system32\Logfiles"
      Dim strOutputFile                     : strOutputFile                     = strLogLocation & "\" & strcomputerName & "_JavaRuntime1.8.0_151_Install_" & Replace(FormatDateTime(Now(), 2),"/","-") & ".log"
      Dim strCurrentUser                    : strCurrentUser                    = ""
      Dim strCurrentUserSID                 : strCurrentUserSID                 = "" 
      Dim strOS                             : strOS                             = ""
      Dim strValueName                      : strValueName                      = ""
      Dim strValue                          : strValue                          = ""
      Dim strArchitecture                   : strArchitecture                   = ""
      Dim strMSI                            : strMSI                            = ""
      Dim strMST                            : strMST                            = ""
      Dim strMSILogFile                     : strMSILogFile                     = ""
      Dim strCommand                        : strCommand                        = ""
      Dim strSoftwareName                   : strSoftwareName                   = "%Java 6 %,%Java 7 %,%Java 8 %"
      Dim arrSoftwareToUninstall            : arrSoftwareToUninstall             = split(strSoftwareName,",")
      Dim strFileNamesToKill                : strFileNamesToKill                = "iexplore.exe,chrome.exe,firefox.exe,javaw.exe,webstart.exe"
      Dim arrFileNamesToKill                : arrFileNamesToKill                = split(strFileNamesToKill,",")
      Dim objSoftwareToUninstall
      
      Dim arrValues,arrSubKeys, arrArguments, strFileName, strCommonPrograms
    
      Dim colProcess, objProcess 
      Dim valResult, valOSBuildNumber, valCounter
      Dim objSubfolder
      Dim objItem, colItems
      Dim strKeyPath
    
      Const ForWriting           = 2
      Const ForReading           = 1
      Const ForAppending         = 8
      Const OverWriteFiles       = True
      const HKEY_CURRENT_USER    = &H80000001
      const HKEY_LOCAL_MACHINE   = &H80000002
      Const HKEY_USERS           = &H80000003 
      
    
    ' ------------------------------------------------------------------------------------------------
    ' Create the log location (if not exists)
    ' Open the logfile.  
    ' ------------------------------------------------------------------------------------------------
    
      CreateFolderStructure(strLogLocation)
      OpenLogFile()
      WriteToLog "- ACTION: script started."
    
    ' ------------------------------------------------------------------------------------------------
    ' Detect the current OS.  
    ' ------------------------------------------------------------------------------------------------
    
      Set colItems = objWMIService.ExecQuery("Select Caption,BuildNumber from Win32_OperatingSystem")
      For Each objItem in colItems
          strOS            = objItem.Caption
          valOSBuildNumber = objItem.BuildNumber
      next
    
    ' ------------------------------------------------------------------------------------------------
    ' Detect the current processor architecture.  
    ' ------------------------------------------------------------------------------------------------
    
      if objFSO.FolderExists(objShell.ExpandEnvironmentStrings("%windir%") & "\SysWOW64\Config") then  
         strArchitecture = "x64"
           else
         strArchitecture = "x86"
      end if
    
      WriteToLog("########## Details regarding operating system and logged on user        ##########")
      WriteToLog("Found Operating System:    " & strOS)
      WriteToLog("Found architecture:        " & strArchitecture)
    
    ' ------------------------------------------------------------------------------------------------
    ' Find pending reboots and write it to the log file.  
    ' ------------------------------------------------------------------------------------------------
    
      if PendingRebootRequired Then
         WriteToLog("Pending restarts:          Yes")
           else
         WriteToLog("Pending restarts:          No")
      End if
      WriteToLog("########## End details regarding operating system and logged on user    ##########")
      WriteToLog(" ")
    
    ' ------------------------------------------------------------------------------------------------
    ' Sets SEE_MASK_NOZONECHECKS to 1.  
    ' That will avoid a screen that asks for permission to run an application from
    ' a share or mapped drive. 
    ' ------------------------------------------------------------------------------------------------
    
      objProcessEnv("SEE_MASK_NOZONECHECKS") = 1
    
    ' ------------------------------------------------------------------------------------------------
    ' Check if the parameter /uninstall is given.
    ' In that case: remove the product and quit.
    ' ------------------------------------------------------------------------------------------------
    
      if wscript.arguments.count > 0 Then
         Set arrArguments = wscript.arguments
         for valCounter = 0 to wscript.arguments.count - 1
             if instr(lcase(arrArguments(valCounter)),"/uninstall") > 0 or instr(lcase(arrArguments(valCounter)),"/remove") > 0 Then
                UninstallJavaAllVersions
                CloseLogFile()
                wscript.Quit(0)
             end if
         next
      end if
    
      KillProcess()
    
      UninstallJavaAllVersions
    
    ' ------------------------------------------------------------------------------------------------
    ' Install Java 8 (x86 version only)
    ' ------------------------------------------------------------------------------------------------
    
      strMSI=FindFileInTheFolder(strCurrentDir & "\x86", "msi")
      strMST=FindFileInTheFolder(strCurrentDir & "\x86", "mst")
    
      KillProcess()
      strMSILogFile = left(strMST,len(strMST)-4) & " ('x86').log"
    
      WriteToLog("########## Start installing Java 8.0.151.                               ##########")
      WriteToLog(" ")
         
      strCommand = "msiexec /i " & chr(34) & strCurrentDir & "\x86\" & strMSI & chr(34)
      strCommand = strcommand & " TRANSFORMS=" & chr(34) & strCurrentDir & "\x86\" & strMST & chr(34)
      strCommand = strCommand & " /qn /l*v " & chr(34) & strLogLocation & "\" & strMSILogFile & chr(34)
      WriteToLog ("Running command: " & strCommand)
      valResult = objShell.Run(strCommand,6,True)
      WriteToLog ("Result: " & valResult)
      WriteToLog(" ")
      WriteToLog("########## End installing Java 8.0.151.                                 ##########")
      WriteToLog(" ")
    
    
    ' ------------------------------------------------------------------------------------------------
    ' Uninstall the Automatic Update function (msi)
    ' ------------------------------------------------------------------------------------------------
    
      WriteToLog("########## Start uninstalling the Java Update Manager.                  ##########")
      WriteToLog(" ")
    
      strMSI        = "au.msi"
      strMST        = "Oracle_JavaRuntime_DisableAutomaticUpdate_8.0.1510.1_ENG_W7_1.0.0.mst"
      strMSILogFile = left(strMST,len(strMST)-4) & ".log"
    
      strCommand = "msiexec /x " & chr(34) & strCurrentDir & "\AutoUpdater\" & strMSI & chr(34)
      strCommand = strCommand & " /qn /l*v " & chr(34) & strLogLocation & "\" & strMSILogFile & chr(34)
      WriteToLog ("Running command: " & strCommand)
      valResult = objShell.Run(strCommand,6,True)
    
      if valResult = 1605 then
         valResult = 0  ' 1605 -> This action is only valid for products that are currently installed.
      end if
    
      WriteToLog ("Result: " & valResult)
      
      WriteToLog(" ")
      WriteToLog("########## End uninstalling the Java Update Manager.                    ##########")
      WriteToLog(" ")
    
      ModifyIcons()
    
      CloseLogFile()
         
    
    ' ================================================================================================
    ' All the subroutines and functions.
    ' ================================================================================================
    
    Function fnKillProcess(strProcessName)
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: fnKillProcess(strProcessName)
    ' Terminates the given processname.
    ' ------------------------------------------------------------------------------------------------
    
      Set colProcess = fn_objWMIService.ExecQuery ("Select * From Win32_Process")
      For Each objProcess In colProcess
        If Instr(LCase(objProcess.Name),LCase(strProcessName)) > 0 Then
           objShell.Run "TASKKILL /F /T /IM " & objProcess.Name, 0, False
           objProcess.Terminate()
           WriteToLog("Terminating application: " & objProcess.Name)
        End If
      Next
    
    End Function
    
    Sub OpenLogFile() 
    
    ' ------------------------------------------------------------------------------------------------
    ' Subroutine: OpenLogFile() 
    ' The name of the logfile is mentinoed in the variabele strOutputFile.
    ' ------------------------------------------------------------------------------------------------
    
      If objLogFileFSO.FileExists(strOutputFile) Then
         Set objLogFile = objLogFileFSO.OpenTextFile(strOutputFile, ForAppending)
             Else
         Set objLogFile = objLogFileFSO.CreateTextFile(strOutputFile)
      End If
    
    End Sub
    
    Sub CloseLogFile()
    
    ' ------------------------------------------------------------------------------------------------
    ' Subroutine: CloseLogFile()
    ' Close the log file.
    ' ------------------------------------------------------------------------------------------------
      WriteToLog("########## End installation of Java 8.                                  ##########")
      WriteToLog("- ACTION: script ended.")
      WriteToLog(" ")
      objLogFile.Close
      Set objLogfileFSO = Nothing
    
    End Sub
    
    Function WriteToLog(sLogMessage)
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: WriteToLog(sLogMessage)
    ' Writes an entry 'sLogMessage' in the logfile.
    ' ------------------------------------------------------------------------------------------------
    
      if instr(sLogMessage, "- ACTION: ") = 0 then sLogMessage = "          " & sLogMessage
      objLogFile.WriteLine("Time: " & now & "  " & sLogMessage)
    
    End Function
    
    Function PendingRebootRequired()
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: PendingRebootRequired()
    ' Detects if there are pending reboots by querying the registry:
    ' * HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing
    '   Key: RebootPending    (Only on Vista and above)
    ' * HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update
    '   Key: RebootRequired
    ' * HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager
    '   Value: PendingFileRenameOperations
    '
    ' (C) by Peter Fonk
    ' ------------------------------------------------------------------------------------------------
     
      PendingRebootRequired = False
    
      If valOSBuildNumber >= 6001 Then 
         PendingRebootRequired = KeyExists("RebootPending", "SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\")
         if PendingRebootRequired Then
            Exit Function
         end if
      End If 
    
      PendingRebootRequired = KeyExists("RebootRequired", "SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\")   
      if PendingRebootRequired Then
         Exit Function
      end if   
    
      PendingRebootRequired = ValueExists("PendingFileRenameOperations", "SYSTEM\CurrentControlSet\Control\Session Manager\")
    
    End Function
    
    
    Function KeyExists(Key, KeyPath)
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: KeyExists(Key, KeyPath)
    ' Checks to see if the 'Key' in 'KeyPath' exists.
    ' ------------------------------------------------------------------------------------------------
    
      Dim arrSubKeys
      Dim oReg: Set oReg = GetObject("winmgmts:!root/default:StdRegProv")
      Dim regReadResult : regReadResult = oReg.EnumKey(HKEY_LOCAL_MACHINE, KeyPath, arrSubKeys)
      Dim i
      	
      KeyExists = False
        
      If regReadResult = 0 And IsArray(arrSubKeys) Then
         For i = 0 To UBound(arrSubKeys)
             If InStr(arrSubKeys(i), Key) <> 0 Then
           	    KeyExists = True
        	    i = UBound(arrSubKeys)
    	 End If
         Next	
      End If
        
      Set oReg = Nothing
    
    End Function
    
    Function ValueExists(Key, KeyPath)
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: ValueExists(Key, KeyPath)
    ' Checks to see if the value 'Key' in 'KeyPath' exists.
    ' ------------------------------------------------------------------------------------------------
    
      Dim arrSubValues
      Dim oReg: Set oReg = GetObject("winmgmts:!root/default:StdRegProv")
      Dim regReadResult : regReadResult = oReg.EnumValues(HKEY_LOCAL_MACHINE, KeyPath, arrSubValues)
      Dim i
      	
      ValueExists = False
        
      If regReadResult = 0 And IsArray(arrSubValues) Then
         For i = 0 To UBound(arrSubValues)
             If InStr(arrSubValues(i), Key) <> 0 Then
        	    ValueExists = True
        	    i = UBound(arrSubValues)
             End If
         Next	
      End If
        
      Set oReg = Nothing
    
    End Function
    
    Sub CreateFolderStructure(strFolderNameToBeCreated)
    
    ' ------------------------------------------------------------------------------------------------
    ' Subroutine: CreateFolderStructure(strFolderNameToBeCreated)
    ' Creates the map as mentioned in strFolderNameToBeCreated.
    ' ------------------------------------------------------------------------------------------------
    
      Dim arrFoldersTMP : arrFoldersTMP = split (strFolderNameToBeCreated,"\")
      Dim strFolder  : strFolder  = ""
      Dim objFolderTMP
     
      For Each objFolderTMP in arrFoldersTMP
          strFolder = strFolder & objFolderTMP
          If NOT objFSO.FolderExists(strFolder) Then
                 objFSO.CreateFolder(strFolder)
          end If
          strFolder = strFolder & "\"
      Next
     
    End Sub
    
    Function GetSIDFromUser(UserName)
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: GetSIDFromUser(UserName)
    ' Gets the SID from the give username.
    ' We use the registry to avoid an empty result if run under the SYSTEM account.
    ' ------------------------------------------------------------------------------------------------
    
      Dim DomainName, Result, WMIUser
    
      If InStr(UserName, "\") > 0 Then
        DomainName = Mid(UserName, 1, InStr(UserName, "\") - 1)
        UserName = Mid(UserName, InStr(UserName, "\") + 1)
      Else
        DomainName = CreateObject("ADSystemInfo").DomainShortName
      End If
    
      On Error Resume Next
      Set WMIUser = GetObject("winmgmts:{impersonationlevel=impersonate}!" _
        & "/root/cimv2:Win32_UserAccount.Domain='" & DomainName & "'" _
        & ",Name='" & UserName & "'")
      If Err.Number = 0 Then
        Result = WMIUser.SID
      Else
        Result = ""
      End If
      On Error GoTo 0
    
      GetSIDFromUser = Result
    
    End Function
    
    Function UninstallJavaAllVersions()
    	Dim result
    	Dim objSoftware
    	Dim colSoftware
    
            WriteToLog("########## Start uninstalling all previous Java versions.               ##########")
    
            For Each objSoftwareToUninstall in arrSoftwareToUninstall
               Set colSoftware = objWMIService.ExecQuery("Select * from Win32_Product Where Name LIKE '" & objSoftwareToUninstall & "'" )
    	   For Each objSoftware in colSoftware
                    WriteToLog "- ACTION: Uninstalling " & objSoftware.Name & "."
    		result = objShell.Run("msiexec.exe /x " & objSoftware.IdentifyingNumber & " REBOOT=ReallySuppress /qn /l*v " & chr(34) & "c:\windows\system32\logfiles\Uninstalling " & objSoftware.Name & ".log" & chr(34),0,True)
    		WriteToLog "- ACTION: " & objSoftware.Name & " removed." & vbcrlf
    	   Next
           Next
    
           WriteToLog("########## End uninstalling all previous Java versions.                 ##########")
           WriteToLog(" ")
    
           Set objSoftware = Nothing
           Set colSoftware = Nothing
    End Function
    
    Function KillProcess()
    	Dim objProcess
    	Dim colProcess : Set colProcess = objWMIService.ExecQuery ("Select * from Win32_Process")
    	For Each objProcess in colProcess
    		Dim strFileName, strTemp
    		For Each strFileName In arrFileNamesToKill
        		If LCase(objProcess.Name) = LCase(strFileName) Then
                                    On Error Resume Next
    				objWshShell.Run "TASKKILL /F /T /IM " & objProcess.Name, 0, False
    				objProcess.Terminate()
    				WriteToLog "- ACTION: " & objProcess.Name & " terminated"
                                    On Error Goto 0
    			End If
    		Next	
    	Next
    	
    	Set objProcess = Nothing
    	Set colProcess = Nothing
    End Function
    
    Sub ModifyIcons()
    
    ' ------------------------------------------------------------------------------------------------
    ' Subroutine: ModifyIcons()
    ' Removes all the Java icons from both the Desktop and Start Menu and replace it by a modified
    ' version
    ' ------------------------------------------------------------------------------------------------
    
      WriteToLog(" ")
      WriteToLog("---------- Modify the Start Menu and remove unneeded icons.             ----------")
      WriteToLog(" ")
    
      strKeyPath       = "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
      strValueName     = "Common Programs"
      objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strCommonPrograms
    
      if objFSO.FolderExists(strCommonPrograms & "\Java") Then 
         objFSO.DeleteFolder(strCommonPrograms & "\Java")
         WriteToLog("The folder '" & strCommonPrograms & "\Java' has been deleted.")
          else
         WriteToLog("The folder '" & strCommonPrograms & "\Java' does not exists thus not deleted.")
      End if
    
      WriteToLog(" ")
      WriteToLog("---------- End modifying Start Menu.                                    ----------")
      WriteToLog(" ")
    
    
    End Sub
    
    Function FindFileInTheFolder(strFolderName, strExtension)
    
      ' -----------------------------------------------------------------------------------------------------------------
      ' Function: FindFileInTheFolder(strFolderName, strExtension)
      ' Returns the full file name in the folder strFolderName and the extension strExtension
      ' -----------------------------------------------------------------------------------------------------------------
    
      Set objFolder = objFSO.GetFolder(strFolderName)
      Set colFiles  = objFolder.Files
      FindFileInTheFolder = ""
    
      For Each objFile in colFiles
          if lcase(right(objFile.Name,3)) = lcase(strExtension) Then
             FindFileInTheFolder  = objFile.Name
          end if
      Next
             
    End Function
    

    You can download the script – excluding the MSI – here.




Installing OneDrive NextGen Synchronisation Client

The OneDrive for Business client can give some difficulties, like unable to synchronize:

Unable to sync files with OneDrive for Business.

Unable to sync files with OneDrive for Business.

This can be solved by installing the new OneDrive Next Gen Sync Client. In this article I will describe how this application can be installed via SCCM 2012.

Please be informed that you still need the OneDrive for Business client to synchronize with Sharepoint lists.

Background information

The OneDrive NextGen Sync Client is installed the users’ %LOCALAPPDATA% directory. As the application is installed the %LOCALAPPDATA% directory, you can assume that you can install the application with user rights in SCCM 2012. If you do so, the installation will fail:

Failure as admin rights are needed to install.

Failure as admin rights are needed to install.


As you can see, there are ‘hidden’ admin rights needed.

The solution

  • Created a vscript that installs the application and sets a detection rule after a successful installation. The detection rule can be used in SCCM 2012 to detect a successful installation.
    ' ================================================================================================
    ' Installs Microsoft OneDriveNextGenSyncClient 17.3.6386.0412
    ' Created by Willem-Jan Vroom
    ' Version history:
    '
    ' 0.0.1
    '    Initial version
    '
    ' 1.0.0
    '    Final version
    '
    ' ================================================================================================
    
    ' ------------------------------------------------------------------------------------------------
    ' Declare the most variables.
    ' ------------------------------------------------------------------------------------------------
    
      Option Explicit
    
      Dim objShell                          : set objShell                      = WScript.CreateObject("WScript.Shell")
      Dim objLogFileFSO                     : Set objLogFileFSO                 = CreateObject("Scripting.FileSystemObject")
      Dim objFSO                            : Set objFSO                        = CreateObject("Scripting.FileSystemObject")
      Dim objProcessEnv                     : Set objProcessEnv                 = objShell.Environment("PROCESS")
      Dim objWMIService                     : Set objWMIService                 = GetObject("winmgmts:\\.\root\cimv2")
      Dim fn_objWMIService                  : Set fn_objWMIService              = GetObject("winmgmts:\\.\root\cimv2")
      Dim objReg                            : Set objReg                        = GetObject("winmgmts:\\.\root\default:StdRegProv")
      Dim objLogFile
      Dim CurrentDir                        : CurrentDir                        = Left(Wscript.ScriptFullname, InstrRev(Wscript.ScriptFullname, "\"))
                                              CurrentDir                        = Left(CurrentDir,len(CurrentDir)-1)
      Dim strcomputerName                   : strcomputerName                   = objProcessEnv("COMPUTERNAME")
      Dim strLogLocation                    : strLogLocation                    = "C:\WINDOWS\system32\Logfiles"
      Dim strOutputFile                     : strOutputFile                     = strLogLocation & "\" & strcomputerName & "_Installation_OneDriveSyncClient_" & Replace(FormatDateTime(Now(), 2),"/","-") & ".log"
      Dim strArchitecture                   : strArchitecture                   = "x86"
      Dim strCurrentUser                    : strCurrentUser                    = ""
      Dim strCurrentUserSID                 : strCurrentUserSID                 = ""
      Dim strOS                             : strOS                             = ""
      Dim strCommand                        : strCommand                        = ""
      Dim strLine                           : strLine                           = ""
      Dim strQuery                          : strQuery                          = ""
      Dim strCommonDesktop                  : strCommonDesktop                  = ""
      Dim strArray                          : strArray                          = ""
      Dim strProcess                        : strProcess                        = ""
      Dim strLanguage                       : strLanguage                       = ""
      Dim strInstallLanguage                : strInstallLanguage                = ""
      Dim strDetectUserUILanguage           : strDetectUserUILanguage           = ""
      Dim strValue                          : strValue                          = ""
      Dim strKeyPath                        : strKeyPath                        = ""
      Dim strValueName                      : strValueName                      = ""
      Dim strCommonPrograms                 : strCommonPrograms                 = ""
      Dim strFileToDelete                   : strFileToDelete                   = ""
      dim strProgramFilesFolder             : strProgramFilesFolder             = objProcessEnv("ProgramFiles")
      Dim strDotNetInstallPath              : strDotNetInstallPath              = ""
      Dim strWindir                         : strWinDir                         = objShell.ExpandEnvironmentStrings("%WinDir%")
      Dim dwValue                           : dwValue                           = 0
    
      Dim arrFileNamesToKill                : arrFileNamesToKill                = Array("doesnotexist.exe")
      Dim objFileNameToKill
    
      Dim arrArguments
      Dim arrLanguage
      Dim strDNSDomain                      : strDNSDomain                      = CreateObject("ADSystemInfo").DomainShortName
      Dim valCounter
      Dim valResult
      Dim valReturnCode
    
      Dim colProcess, objProcess
      Dim valOSBuildNumber
      Dim objSubfolder
      Dim colItems, objItem, Subfolder
      Dim colSoftware, objSoftware
      Dim arrValues, arrSubKeys
    
      Const ForWriting           = 2
      Const ForReading           = 1
      Const ForAppending         = 8
      Const OverWriteFiles       = True
      const HKEY_CURRENT_USER    = &H80000001
      const HKEY_LOCAL_MACHINE   = &H80000002
      Const HKEY_USERS           = &H80000003
    
      Const DEBUGMODE            = False
    
    ' ------------------------------------------------------------------------------------------------
    ' Create the log location (if not exists)
    ' Open the logfile.
    ' ------------------------------------------------------------------------------------------------
    
      CreateFolderStructure(strLogLocation)
      OpenLogFile()
      WriteToLog "- ACTION: script started."
      WriteToLog " "
    
    ' ------------------------------------------------------------------------------------------------
    ' Detect the current OS.
    ' ------------------------------------------------------------------------------------------------
    
      Set colItems = objWMIService.ExecQuery("Select Caption,BuildNumber from Win32_OperatingSystem")
      For Each objItem in colItems
          strOS            = objItem.Caption
          valOSBuildNumber = objItem.BuildNumber
      next
    
    ' ------------------------------------------------------------------------------------------------
    ' Find the currently logged on userid.
    ' And translate it to the users SID.
    ' ------------------------------------------------------------------------------------------------
    
      Set colProcess = objWMIService.ExecQuery("Select * from Win32_Process where Name = 'explorer.exe'")
      For Each objProcess in colProcess
          valReturnCode = objProcess.GetOwner(strCurrentUser)
          if valReturnCode <> 0 Then strCurrentUser = "Unable to find the username!"
      Next
    
      strCurrentUser = Ucase(strDNSDomain) & "\" & strCurrentUser
    
      strCurrentUserSID = GetSIDFromUser(strCurrentUser)
    
    ' ------------------------------------------------------------------------------------------------
    ' Detect the current processor architecture.
    ' ------------------------------------------------------------------------------------------------
    
      if objFSO.FolderExists(strWindir & "\syswow64") Then
         strArchitecture = "x64"
         strProgramFilesFolder = objProcessEnv("ProgramFiles(x86)")
      end if
    
    ' ------------------------------------------------------------------------------------------------
    ' Detect the current User Interface MUI.
    ' ------------------------------------------------------------------------------------------------
    
      strDetectUserUILanguage = DetectUserUILanguage
    
      WriteToLog("########## Details regarding operating system and logged on user     ##########")
      WriteToLog("Found Operating System:       " & strOS)
      WriteToLog("Found architecture:           " & strArchitecture)
      WriteToLog("Logged on userid:             " & strCurrentUser)
      WriteToLog("Logged on user SID:           " & strCurrentUserSID)
      WriteToLog("Language:                     " & strDetectUserUILanguage)
      WriteToLog("########## End details regarding operating system and logged on user ##########")
      WriteToLog(" ")
      WriteToLog("########## Installation                                              ##########")
    
      ' ------------------------------------------------------------------------------------------------
      ' Close applications that might screw up the installation.
      ' ------------------------------------------------------------------------------------------------
    
      For Each objFileNameToKill in arrFileNamesToKill
        fnKillProcess(objFileNameToKill)
      Next
    
    ' ------------------------------------------------------------------------------------------------
    ' Sets SEE_MASK_NOZONECHECKS to 1.
    ' That will avoid a screen that asks for permission to run an application from
    ' a share or mapped drive.
    ' ------------------------------------------------------------------------------------------------
    
      objProcessEnv("SEE_MASK_NOZONECHECKS") = 1
    
    ' ------------------------------------------------------------------------------------------------
    ' Uninstall other Samsung Kies installations.
    ' if the command line option '/uninstall' is given, then only a uninstall and quit.
    ' ------------------------------------------------------------------------------------------------
    
      if wscript.arguments.count > 0 Then
         if lcase(wscript.arguments(0)) = "/uninstall" or lcase(wscript.arguments(0)) = "/remove" then
    	WriteToLog("The command line option '" & wscript.arguments(0) & "' was found, so only a silent uninstall will be performed.")
            RemoveOneDriveSyncClient()
            WriteToLog("########## End Uninstall                                      ##########")
            WriteToLog(" ")
            CloseLogFile()
            wscript.quit
         end if
      end if
    
    ' ------------------------------------------------------------------------------------------------
    ' Start the base installation
    ' ------------------------------------------------------------------------------------------------
    
      strCommand = chr(34) & CurrentDir & "\OneDriveSetup.exe" & chr(34)
      strCommand = strCommand & " /silent"
      WriteToLog ("Running command: " & strCommand)
      valResult = objShell.Run (strCommand,6,True)
      WriteToLog("Result: " & valResult)
      if valResult = 0 Then 
         GenereteSCCM2012DetectionRule
      end if
      WriteToLog("########## End Installation                                          ##########")
      WriteToLog(" ")
      CloseLogFile()
      wscript.quit valReturnCode
    
    Sub OpenLogFile()
    
    ' ------------------------------------------------------------------------------------------------
    ' Subroutine: OpenLogFile()
    ' The name of the logfile is mentinoed in the variabele strOutputFile.
    ' ------------------------------------------------------------------------------------------------
    
      If objLogFileFSO.FileExists(strOutputFile) Then
         Set objLogFile = objLogFileFSO.OpenTextFile(strOutputFile, ForAppending)
             Else
         Set objLogFile = objLogFileFSO.CreateTextFile(strOutputFile)
      End If
    
    End Sub
    
    Sub CloseLogFile()
    
    ' ------------------------------------------------------------------------------------------------
    ' Subroutine: CloseLogFile()
    ' Close the log file.
    ' ------------------------------------------------------------------------------------------------
    
      WriteToLog "- ACTION: script ended."
      objLogFile.Close
      Set objLogfileFSO = Nothing
    
    End Sub
    
    Function WriteToLog(sLogMessage)
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: WriteToLog(sLogMessage)
    ' Writes an entry 'sLogMessage' in the logfile.
    ' ------------------------------------------------------------------------------------------------
    
      if instr(sLogMessage, "- ACTION: ") = 0 then sLogMessage = "          " & sLogMessage
      objLogFile.WriteLine("Time: " & now & "  " & sLogMessage)
    
    End Function
    
    Function GetSIDFromUser(UserName)
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: GetSIDFromUser(UserName)
    ' Gets the SID from the give username.
    ' We use the registry to avoid an empty result if run under the SYSTEM account.
    ' ------------------------------------------------------------------------------------------------
    
      Dim DomainName, Result, WMIUser
    
      If InStr(UserName, "\") > 0 Then
        DomainName = Mid(UserName, 1, InStr(UserName, "\") - 1)
        UserName = Mid(UserName, InStr(UserName, "\") + 1)
      Else
        DomainName = CreateObject("WScript.Network").UserDomain
      End If
    
      On Error Resume Next
      Set WMIUser = GetObject("winmgmts:{impersonationlevel=impersonate}!" _
        & "/root/cimv2:Win32_UserAccount.Domain='" & DomainName & "'" _
        & ",Name='" & UserName & "'")
      If Err.Number = 0 Then
        Result = WMIUser.SID
      Else
        Result = ""
      End If
      On Error GoTo 0
    
      GetSIDFromUser = Result
    
    End Function
    
    Sub CreateFolderStructure(strFolderNameToBeCreated)
    
    ' ------------------------------------------------------------------------------------------------
    ' Subroutine: CreateFolderStructure(strFolderNameToBeCreated)
    ' Creates the map as mentioned in strFolderNameToBeCreated.
    ' ------------------------------------------------------------------------------------------------
    
      Dim arrFoldersTMP : arrFoldersTMP = split (strFolderNameToBeCreated,"\")
      Dim strFolder  : strFolder  = ""
      Dim objFolderTMP
    
      For Each objFolderTMP in arrFoldersTMP
          strFolder = strFolder & objFolderTMP
          If NOT objFSO.FolderExists(strFolder) Then
                 objFSO.CreateFolder(strFolder)
          end If
          strFolder = strFolder & "\"
      Next
    
    End Sub
    
    Function DetectUserUILanguage
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: DetectUserUILanguage
    ' Detects the User Interface Language 
    ' Modified by Willem-Jan Vroom d.d 12 Feb 14: also detects Czech, Finnish, Hungarian, Polish,
    ' Russian, Slovak, Slovian and Turkish languages on Windows 7.
    ' ------------------------------------------------------------------------------------------------
      
      if instr(lcase(strOS),"windows xp") > 0 then
         strKeyPath               = strCurrentUserSID & "\Control Panel\Desktop"
         strValueName             = "MultiUILanguageId"
         strLanguage              = "eng"
         objReg.GetStringvalue HKEY_USERS,strKeyPath,strValueName,strValue
         if NOT IsEmpty(strValue) Then
            strValue = UCase(right(strValue,4))
            if strValue = "040C" then strLanguage = "fra"
            if strValue = "0410" then strLanguage = "ita"
            if strValue = "0407" then strLanguage = "ger"
            if strValue = "040A" then strLanguage = "spa"
            if strValue = "0C0A" then strLanguage = "spa"
         end if
          else
         strKeyPath               = strCurrentUserSID & "\Control Panel\Desktop"
         strValueName             = "PreferredUILanguages"
         strLanguage              = "eng"
         objReg.GetMultiStringValue HKEY_USERS,strKeyPath,strValueName,arrValues
         if not IsNull(arrValues) Then
            strValue=arrValues(0)
            if NOT IsEmpty(strValue) then
               strValue = lcase(left(strValue,2))
               if strValue = "fr" then strLanguage = "fra"
               if strValue = "it" then strLanguage = "ita"
               if strValue = "de" then strLanguage = "ger"
               if strValue = "es" then strLanguage = "spa"
               if strValue = "cs" then strLanguage = "cze"
               if strValue = "fi" then strLanguage = "fin"
               if strValue = "hu" then strLanguage = "hun"
               if strValue = "pl" then strLanguage = "pol"
               if strValue = "ru" then strLanguage = "rus"
               if strValue = "sk" then strLanguage = "sky"
               if strValue = "sl" then strLanguage = "slv"
               if strValue = "sv" then strLanguage = "swe"
               if strValue = "tr" then strLanguage = "tur"
               if strValue = "nb" then strLanguage = "nor"
            end if
         end if
         if strLanguage = "eng" then
            strKeyPath               = ".DEFAULT\Control Panel\Desktop\MuiCached"
            strValueName             = "MachinePreferredUILanguages"
            objReg.GetMultiStringValue HKEY_USERS,strKeyPath,strValueName,arrValues
            if not IsNull(arrValues) Then
               strValue=arrValues(0)
               if NOT IsEmpty(strValue) then
                  strValue = lcase(left(strValue,2))
                  if strValue = "fr" then strLanguage = "fra"
                  if strValue = "it" then strLanguage = "ita"
                  if strValue = "de" then strLanguage = "ger"
                  if strValue = "es" then strLanguage = "spa"
                  if strValue = "cs" then strLanguage = "cze"
                  if strValue = "fi" then strLanguage = "fin"
                  if strValue = "hu" then strLanguage = "hun"
                  if strValue = "pl" then strLanguage = "pol"
                  if strValue = "ru" then strLanguage = "rus"
                  if strValue = "sk" then strLanguage = "sky"
                  if strValue = "sl" then strLanguage = "slv"
                  if strValue = "sv" then strLanguage = "swe"
                  if strValue = "tr" then strLanguage = "tur"
                  if strValue = "nb" then strLanguage = "nor"
               end if
            end if
         end if     
      end if
    
      DetectUserUILanguage = strLanguage
    End Function
    
    Function fnKillProcess(strProcessName)
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: fnKillProcess(strProcessName)
    ' Terminates the given processname.
    ' ------------------------------------------------------------------------------------------------
    
      Set colProcess = fn_objWMIService.ExecQuery ("Select * From Win32_Process")
      For Each objProcess In colProcess
        If Instr(LCase(objProcess.Name),LCase(strProcessName)) > 0 Then
           objShell.Run "TASKKILL /F /T /IM " & objProcess.Name, 0, False
           objProcess.Terminate()
           WriteToLog("Terminating application: " & objProcess.Name)
        End If
      Next
    
    End Function
    
    Function GenereteSCCM2012DetectionRule
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: GenereteSCCM2012DetectionRule
    ' Creates the SCCM 2012 Detection Rule to detect a successfull installation.
    ' ------------------------------------------------------------------------------------------------
    
      WriteToLog ("Creates the SCCM 2012 Detection Rule.")
      strKeyPath   = "SOFTWARE\VroomSoft\SCCM2012DetectionRules"
      strValueName = "Install_OneDriveSyncClient_17.3.6386.0412"
      strValue     = "true"
      objReg.CreateKey      HKEY_LOCAL_MACHINE, strKeyPath  
      objReg.SetStringValue HKEY_LOCAL_MACHINE, strKeyPath, strValueName, strValue
      
    End Function
    
    Function RemoveOneDriveSyncClient()
    
    ' ------------------------------------------------------------------------------------------------
    ' Function: RemoveOneDriveSyncClient()
    ' Removes OneDrive Next Gen Sync Client.
    ' ------------------------------------------------------------------------------------------------
    
      strCommand = chr(34) & CurrentDir & "\OneDriveSetup.exe" & chr(34)
      strCommand = strCommand & " /uninstall"
      WriteToLog ("Running command: " & strCommand)
      valResult = objShell.Run (strCommand,6,True)
      WriteToLog("Result: " & valResult)
      if valResult = 0 Then
         strKeyPath   = "SOFTWARE\VroomSoft\SCCM2012DetectionRules"
         strValueName = "Install_OneDriveSyncClient_17.3.6386.0412"
         objReg.DeleteValue HKEY_LOCAL_MACHINE, strKeyPath, strValueName
      end if 
      
    End Function
    
  • This is the detection rule that will be used in SCCM 2012:
    Detection rule set in the vbscript.

    Detection rule set in the vbscript.

  • Implementation in SCCM 2012

    1. Create a ‘installation program’ and ‘uninstall program’:
      New application.

      New application.

    2. The detection rule:
      Detection rule.

      Detection rule.

    3. The detection method:
      Detection method.

      Detection method.

    4. The application is installed with admin rights:
      Installation with admin rights.

      Installation with admin rights.

    5. And deploy the application to a deviced based collection:
      Deployment to a device based collection.

      Deployment to a device based collection.


      Deploy as available.

      Deploy as available.


      Show all notifications.

      Show all notifications.

    Check on a client

    1. Log on to a client and go to the Software Catalog:
      The application is visible in the software center

      The application is visible in the software center


      You can find the new application under installed applications.

      You can find the new application under installed applications.

    2. You can use regedit to find the detection rule which is set via vbscript:
      The detection rule is found in the registry

      The detection rule is found in the registry

    3. The installation log file (found in c:\windows\system32\logfiles):
      Installation log file

      Installation log file

    4. Now you can select the folders you want to synchronize or want to exclude from synchronization:
      You can select the folders you want so synchronize.

      You can select the folders you want so synchronize.


      Unselect the folders you do not want to synchronize.

      Unselect the folders you do not want to synchronize.

    Uninstall the application

    You can uninstall the OneDrive NextGen Sync Client if you do not want to use it anymore. All the data will remain on the computer:

    You can uninstall the client.

    You can uninstall the client.


    The uninstall in the log file.

    The uninstall in the log file.




User Environment Variables in App-V 5.0 with SP1, SP2 and SP2 Hotfix 4

Dan Gough wrote an excellent article named: User Environment Variables in App-V 5 Scripts. To summarize: it is about the fact that environment variables are not shown correctly in AppV 5.0.
However: the question is: is this still the case? Time to investigate!

To test this, I re-used an old package: Firefox 24. It does not need any startup-scripts, but it is an ideal candidate for testing.

I have done the following:

  1. I created a VB script with the following content:
    ' ===========================================================================
    ' Example of environment variables when running as a script.
    ' ===========================================================================
    
      Option Explicit
      
      Dim objShell             : set objShell        = CreateObject("WScript.Shell")
      Dim strText              : strText             = ""
      Dim strUserShellFolders  : strUserShellFolders = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders"
      Dim strShellFolders      : strShellFolders     = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders"
      Dim strVolatileEnv       : strVolatileEnv      = "HKCU\Volatile Environment"
      
      strText = strText & "Displaying the various variables when running scripts in AppV 5.0." & vbCrlf
      On Error Resume Next
      strText = strText & "AppV 5.0 Client version:   " & objShell.RegRead("HKLM\SOFTWARE\Microsoft\AppV\Client\Version")
      On Error Goto 0
      strText = strText & vbCrlf & vbCrlf
      
      
      ' Start with environment variables
      strText = strText & "Environment variables:" & vbCrlf
      strText = strText & " - APPDATA:       " & objShell.ExpandEnvironmentStrings("%APPDATA%") & vbCrlf
      strText = strText & " - LOCALAPPDATA:  " & objShell.ExpandEnvironmentStrings("%LOCALAPPDATA%") & vbCrlf
      strText = strText & " - USERNAME:      " & objShell.ExpandEnvironmentStrings("%USERNAME%") & vbCrlf
      strText = strText & " - USERPROFILE:   " & objShell.ExpandEnvironmentStrings("%USERPROFILE%") & vbCrlf & vbCrlf
      
      ' Use HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders
      strText = strText & "Use " & strUserShellFolders & ":" & vbCrlf
      strText = strText & " - AppData:       " & objShell.RegRead(strUserShellFolders & "\Appdata") & vbCrlf
      strText = strText & " - Local AppData: " & objShell.RegRead(strUserShellFolders & "\Local Appdata") & vbCrlf
      strText = strText & " - Desktop:       " & objShell.RegRead(strUserShellFolders & "\Desktop") & vbCrlf & vbCrlf
      
      ' Use HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders
      strText = strText & "Use " & strShellFolders & ":" & vbCrlf
      strText = strText & " - AppData:       " & objShell.RegRead(strShellFolders & "\Appdata") & vbCrlf
      strText = strText & " - Local AppData: " & objShell.RegRead(strShellFolders & "\Local Appdata") & vbCrlf
      strText = strText & " - Desktop:       " & objShell.RegRead(strShellFolders & "\Desktop") & vbCrlf & vbCrlf
      
      ' Use HKEY_CURRENT_USER\Volatile Environment
      strText = strText & "Use " & strVolatileEnv & ":" & vbCrlf
      strText = strText & " - APPDATA:       " & objShell.RegRead(strVolatileEnv & "\APPDATA") & vbCrlf
      strText = strText & " - LOCALAPPDATA:  " & objShell.RegRead(strVolatileEnv & "\LOCALAPPDATA") & vbCrlf
      strText = strText & " - USERNAME:      " & objShell.RegRead(strVolatileEnv & "\USERNAME") & vbCrlf
      strText = strText & " - USERPROFILE:   " & objShell.RegRead(strVolatileEnv & "\USERPROFILE") & vbCrlf
      
      msgbox strText,,"Results from environment variables"
    
  2. Modified the package by adding the file in the scripts folder:
    Add the vbscript in sequencer

    Add the vbscript in sequencer

  3. Installed AppV 5.0 with SP1 on a client
  4. Logged in with an account with standard user rights.
  5. Started PowerShell as admin and installed Firefox. Also I enabled packaging scripts:
    Powershell commands to add the package.

    Powershell commands to add the package.

  6. Started Firefox:
    The environment variables are shown incorrect,

    The environment variables are shown incorrect,

  7. Upgraded the client to SP2:
    Install the client.

    Install the client.


    Reboot the computer.

    Reboot the computer.

  8. Started Firefox:
    The environment variables are shown correctly,

    The environment variables are shown correctly,

  9. Upgraded the client to SP2 with HF4:
    Install the client.

    Install the client.


    Reboot the computer.

    Reboot the computer.

  10. Started Firefox:
    The environment variables are shown correctly,

    The environment variables are shown correctly,

To summarize: if you want to use scripts and environment variables are needed, then use at least SP2. If you cannot upgrade the client, then use the HKCU\Volatile Environment.




Multiple shortcuts with different access permissions

Let’s take the following scenario: you have a backend with a development, test, acceptance and production environment. Each environment is accessed with different shortcuts in the Start Menu. In that shortcut the environment is shown. The shortcut in the Start Menu is only shown if you are allowed to use that environment.

In the time of AppV 4.6, you simply made 4 OSD files, each of them pointing to the correct environment. In the ‘Application Virtualization Management Console’ you set the access permissions who may use that shortcut. So far so good.

Now, with AppV 5.0 that is less easy. But still it can be done. And I will show how.

Approach:

  1. Create the key ‘HKCU\Software\DemoShortcuts’ with Value ‘Environment’. The value ‘Environment’ will be filled in with ‘DEV’, ‘TEST’, ‘ACC’ or ‘PROD’
  2. Create a vbscript that reads the above mentioned key registry from the virtual registry and displays the value.
  3. The registry key is set in the user config xml file. This will be explained further later on.

The content of the shortcut.vbs

' =======================================================================
' Demo: this shortcut is used multiple times
' It reads the content from 
'  - Key:        HKCU\Software\DemoShortcuts
'  - ValueName:  Environment
' And that value is displayed in the box.
' =======================================================================

  Option Explicit
  Dim objShell      : Set objShell = WScript.CreateObject("WScript.Shell")
  Dim strEnv        : strEnv       = ""

' =======================================================================
' Read the registry
' =======================================================================

  strEnv = objShell.RegRead("HKEY_CURRENT_USER\Software\DemoShortcuts\Environment")
  
  if IsNull(strEnv) then
     strEnv = "DUMMY"
  end if

' =======================================================================
' Display the message-box with the correct environment.
' =======================================================================

  msgbox "Welcome to the " & strEnv & " environment."

Packaging steps:

  1. Use the sequencer to install the vbscript in C:\Demo_MoreShortcuts_1.0_ENG.100
  2. Create the shortcut as per screenprint:

    During the sequencing phase create the Start Menu as per screen print.

    During the sequencing phase create the Start Menu as per screen print.

    Properties DEV shortcut:

    Properties of the shortcut pointing to the DEV environment.

    Properties of the shortcut pointing to the DEV environment.

    Properties TEST shortcut:

    Properties of the shortcut pointing to the TEST environment.

    Properties of the shortcut pointing to the TEST environment.

    Properties ACC shortcut:

    Properties of the shortcut pointing to the ACC environment.

    Properties of the shortcut pointing to the ACC environment.

    Properties PROD shortcut:

    Properties of the shortcut pointing to the PROD environment.

    Properties of the shortcut pointing to the PROD environment.

  3. After sequencing the shortcuts – except one – are gone. That is due to the fact that multiple shortcuts are pointing to the same vbscript. Thus the shortcuts should be made again.

    The sequencer screws up the shortcuts. That has to be corrected.

    The sequencer screws up the shortcuts. That has to be corrected.

    The corrected shortcuts in the sequencer.

    The corrected shortcuts in the sequencer.

Create the user config xml files for each environment:

It is mandatory to have an user config xml for each environment.

  1. Create 4 copies of the Demo_MoreShortcuts_1.0_ENG_UserConfig.xml file.
  2. Modify each copy to reflect the following:
    • Remove the shortcuts that are not needed in that environment.
    • Add the registry key
    • Remove parts that are not needed.
    • Rename it:
      • Demo_MoreShortcuts_1.0_ENG_UserConfig – DEV.xml
        
        
          
            
            
            
              
                
                  
                    [{Programs}]\Demo Application\Start the DEV environment.lnk
                    [{AppVPackageRoot}]\shortcut.vbs
                    [{SystemX86}]\shell32.dll.159.ico
                    
                    [{AppVPackageRoot}]
                    [{AppVPackageRoot}]\shortcut.vbs
                  
                
              
            
         
            
            
              
            
            
            
            
            
                  
                    
                      
                    
                  
            
            
            
            
            
            
            
            
            
          
          
          
            
              
                Start the DEV environment
                
                
              
            
          
        
        
        
      • Demo_MoreShortcuts_1.0_ENG_UserConfig – TEST.xml
        
        
          
            
            
            
              
                
                  
                    [{Programs}]\Demo Application\Start the TEST environment.lnk
                    [{AppVPackageRoot}]\shortcut.vbs
                    [{SystemX86}]\shell32.dll.77.ico
                    
                    [{AppVPackageRoot}]
                    [{AppVPackageRoot}]\shortcut.vbs
                  
                
              
            
         
            
            
              
            
            
            
            
             
                  
                    
                      
                    
                  
            
            
            
            
            
            
            
            
            
          
          
          
            
              
                Start the TEST environment
                
                
              
            
          
        
        
        
      • Demo_MoreShortcuts_1.0_ENG_UserConfig – ACC.xml
        
        
          
            
            
            
              
                
                  
                    [{Programs}]\Demo Application\Start the ACC environment.lnk
                    [{AppVPackageRoot}]\shortcut.vbs
                    [{SystemX86}]\shell32.dll.112.ico
                    
                    [{AppVPackageRoot}]
                    [{AppVPackageRoot}]\shortcut.vbs
                  
                
              
            
        
            
            
              
            
            
            
            
            
                  
                    
                      
                    
                  
            
            
            
            
            
            
            
            
            
          
          
          
            
              
                Start the ACC environment
                
                
              
            
          
        
        
        
      • Demo_MoreShortcuts_1.0_ENG_UserConfig – PROD.xml
        
        
          
            
            
            
              
                
                  
                    [{Programs}]\Demo Application\Start the PROD environment.lnk
                    [{AppVPackageRoot}]\shortcut.vbs
                    [{SystemX86}]\shell32.dll.137.ico
                    
                    [{AppVPackageRoot}]
                    [{AppVPackageRoot}]\shortcut.vbs
                  
                
              
            
        
            
            
              
            
            
            
            
             
                  
                    
                      
                    
                  
            
            
            
            
            
            
            
            
            
          
          
          
            
              
                Start the PROD environment
                
                
              
            
          
        
        

Importing in the AppV 5.0 Management Interface:

  1. Import the application in the AppV 5.0 with the ‘Application Virtualization’ web page.

    Add the package.

    Add the package.

    Select the .appv file.

    Select the .appv file.

    The package has been imported.

    The package has been imported.

    Specify the AD group name that is allowed to use that specific shortcut.

    Specify the AD group name that is allowed to use that specific shortcut.

    Enter the AD group name for that specific shortcut.

    Enter the AD group name for that specific shortcut.

    And grant access.

    And grant access.

  2. For each shortcut change the assigned configuration and use the correct user config xml file.

    Under 'Assigned configuration' select Custom.

    Under ‘Assigned configuration’ select Custom.

    Click 'Edit' to modify the shortcut.

    Click ‘Edit’ to modify the shortcut.

    You will see the settings as saved in the appv file. Click on [Advanced] to overwrite that configuration.

    You will see the settings as saved in the appv file.
    Click on [Advanced] to overwrite that configuration.

    Click on [Import and overwrite this configuration.]

    Click on [Import and overwrite this configuration.]

    And select the correct user config xml file. In this case the one for the DEV environment.

    And select the correct user config xml file. In this case the one for the DEV environment.

    Confirm that it is ok to overwrite the current configuration.

    Confirm that it is ok to overwrite the current configuration.

    The result.

    The result.

    Do the same for all the other environments.  Publish the package when done.

    Do the same for all the other environments.
    Publish the package when done.

    The final result.

    The final result.

Testing:

  1. Login with the test user account that has been assigned to the development shortcut.
  2. After a short while the icon is visible in the Start Menu.

    Only the DEV environment in the Start Menu.

    Only the DEV environment in the Start Menu.

  3. If you start the shortcut, you will see that the correct environment is shown.

    The DEV environment.

    The DEV environment.

  4. In the virtual registry you will see the settings as set in the user config xml file.

    Start regedit with the /appvve parameter.

    Start regedit with the /appvve parameter.

    And the correct environment is shown in regedit.  So the value that is mentioned in the user config xml is used.

    And the correct environment is shown in regedit.
    So the value that is mentioned in the user config xml is used.

  5. And the same for all the other environments:
    • The TEST environment:

      Only the TEST environment in the Start Menu.

      Only the TEST environment in the Start Menu.

      And the result.

      And the result.

    • The ACC environment:

      Only the ACC environment in the Start Menu.

      Only the ACC environment in the Start Menu.

      The result

      The result.

    • The PROD environment:

      Only the PROD environment in the Start Menu.

      Only the PROD environment in the Start Menu.

      The result.

      The result.

The files that are used are stored in this zip file: Demo_MoreShortcuts.




Check if a MSI has already been installed

Sometimes it is easy to know if a MSI has already been installed. For example: use the same script to deploy both a MSI and the patches. If the MSI has already been installed, then install only the patches. Making an ‘adminstrative installation point’ and apply the patch was not a solution.

The script:

Option Explicit

Const HKEY_LOCAL_MACHINE = &H80000002

dim strMSINameToCheck : strMSINameToCheck="\\server\share\path\to\name.msi"

If not fnCheckIsMSIInstalled(strMSINameToCheck) then
   wscript.echo "MSI '" & strMSINameToCheck & "' has not been installed."
     Else
   wscript.echo "MSI '" & strMSINameToCheck & "' has been installed."
end If


Function fnCheckIsMSIInstalled(strMSIName)

  ' -----------------------------------------------------------------------------------------------------------------
  ' Function: fnCheckIsMSIInstalled(strMSIName)
  ' Checks if the MSI given in strMSIName has been installed.
  ' strMSIName = "\\server\share\path\to\install.msi"
  ' This script is based on the example in 
  ' http://www.pcreview.co.uk/forums/getting-property-info-via-vbscript-text-file-t1544137.html
  ' -----------------------------------------------------------------------------------------------------------------

  Dim fn_objFSO    : Set fn_objFSO = CreateObject("Scripting.FileSystemObject")
  Dim fn_objWI     : Set fn_objWI  = CreateObject("WindowsInstaller.Installer")

  Dim fn_objReg    : Set fn_objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
  Dim strKeyPath   : strKeyPath    = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\"
  Dim strValueName : strValueName  = "InstallDate"

  ' -----------------------------------------------------------------------------------------------------------------
  ' check if the file exists and that the given file is a MSI
  ' -----------------------------------------------------------------------------------------------------------------

  If NOT fn_objFSO.FileExists(strMSIName) then
     ' --------------------------------------------------------------------------------------------------------------
     ' Leave the function and clean up the mess.
     ' --------------------------------------------------------------------------------------------------------------
     fnCheckIsMSIInstalled = False
     Set fn_objFSO     = Nothing
     Set fn_objWI      = Nothing
     Set fn_objReg     = Nothing
     Exit Function
  End If
  If lcase(right(strMSIName,3)) <> "msi" then
     ' --------------------------------------------------------------------------------------------------------------
     ' Leave the function and clean up the mess.
     ' --------------------------------------------------------------------------------------------------------------
     fnCheckIsMSIInstalled = False
     Set fn_objFSO     = Nothing
     Set fn_objWI      = Nothing
     Set fn_objReg     = Nothing
     Exit Function
  End If

  ' -----------------------------------------------------------------------------------------------------------------
  ' Find the property 'ProductCode' in the given MSI
  ' -----------------------------------------------------------------------------------------------------------------

  Dim fn_objDB     : Set fn_objDB   = fn_objWI.OpenDatabase(strMSIName,2)
  Dim fn_objView   : Set fn_objView = fn_objDB.OpenView("Select `Value` From Property WHERE `Property` ='ProductCode'")
  fn_objView.Execute
  Dim fn_objRec    : Set fn_objRec  = fn_objView.Fetch
  If fn_objRec is Nothing Then
     ' --------------------------------------------------------------------------------------------------------------
     ' Leave the function and clean up the mess.
     ' --------------------------------------------------------------------------------------------------------------
     fnCheckIsMSIInstalled = False
     Set fn_objFSO     = Nothing
     Set fn_objWI      = Nothing
     Set fn_objReg     = Nothing
     Set fn_objDB      = Nothing
     Set fn_objView    = Nothing
     Set fn_objRec     = Nothing
     Exit Function
  End If
  Dim strProductCode : strProductCode = fn_objRec.StringData(1)

  ' -----------------------------------------------------------------------------------------------------------------
  ' Check that the key InstallDate in the hive HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{ProductCode}
  ' or in HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{ProductCode}
  ' exists
  ' -----------------------------------------------------------------------------------------------------------------

  strKeyPath = strKeyPath & strProductCode
  fn_objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue
  if IsNull(strValue) then 
     strKeyPath    = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\"
     strKeyPath    = strKeyPath & strProductCode
     fn_objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,strValueName,strValue
     if IsNull(strValue) then 
        fnCheckIsMSIInstalled = False
          else
        fnCheckIsMSIInstalled = True
     end if
       else
     fnCheckIsMSIInstalled = True
  end if


  Set fn_objFSO     = Nothing
  Set fn_objWI      = Nothing
  Set fn_objReg     = Nothing
  Set fn_objDB      = Nothing
  Set fn_objView    = Nothing
  Set fn_objRec     = Nothing
  
End Function




Installing all Microsoft Visual C++ Runtime modules

On my blog post Latest Supported Visual C++ Downloads you a link to the Microsoft site Latest Supported Visual C++ Downloads. Once downloaded, how to install all these updates?

I made a script that installs all the Microsoft C++ Runtime modules. On x86 only the x86 modules are installed. On x64, both x86 and x64 modules are installed.

The list has been populated on June, 14th, 2014. So the list of C++ Runtime modules might – and will be – change.

The folder list should be as follows:

Folder PATH listing for volume OS
Volume serial number is 000000C0 0475:818B
C:.
|   install_all_VisualCPlusPlusRuntimes_v101.vbs
|   
+---01.Microsoft Visual C++ 2005 SP1 Redistributable Package
|       vcredist_x64.exe
|       vcredist_x86.exe
|       
+---02.Microsoft Visual C++ 2005 SP1 Redistributable Package ATL Security Update
|       vcredist_x64.exe
|       vcredist_x86.exe
|       
+---03.Microsoft Visual C++ 2005 SP1 Redistributable Package MFC Security Update
|       vcredist_x64.EXE
|       vcredist_x86.EXE
|       
+---04.Microsoft Visual C++ 2008 SP1 Redistributable Package
|       vcredist_x64.exe
|       vcredist_x86.exe
|       
+---05.Microsoft Visual C++ 2008 SP1 Redistributable Package MFC Security Update
|       vcredist_x64.exe
|       vcredist_x86.exe
|       
+---06.Microsoft Visual C++ 2010 SP1 Redistributable Package
|       vcredist_x64.exe
|       vcredist_x86.exe
|       
+---07.Microsoft Visual C++ 2010 SP1 Redistributable Package MFC Security Update
|       vcredist_x64.exe
|       vcredist_x86.exe
|       
+---08.Microsoft Visual C++ 2012 Update 3
|       vcredist_x64.exe
|       vcredist_x86.exe
|       
+---09.Microsoft Visual C++ 2013 Redistributable Package
|       vcredist_x64.exe
|       vcredist_x86.exe
|       
\---10.Microsoft Visual C++ 2015 Redistributable Update 3
        vcredist_x64.exe
        vcredist_x86.exe

The only thing you have to do is to download all the redistributable packages:

The code:

' ================================================================================================
' Install all Microsoft C++ Runtimes
' Created by Willem-Jan Vroom
' Version history:
'
' 0.0.1
'    Initial version
'
' 1.0.0
'    Final version
'
' 1.0.1
'    Added support for C++ Redistributable 2015
'
' ================================================================================================

' ------------------------------------------------------------------------------------------------
' Declare the most variables. 
' ------------------------------------------------------------------------------------------------

  Option Explicit

  Dim objShell            : set objShell              = WScript.CreateObject("WScript.Shell")
  Dim objLogFileFSO       : Set objLogFileFSO         = CreateObject("Scripting.FileSystemObject")
  Dim objFSO              : Set objFSO                = CreateObject("Scripting.FileSystemObject")
  Dim objProcessEnv       : Set objProcessEnv         = objShell.Environment("PROCESS")
  Dim objWMIService       : Set objWMIService         = GetObject("winmgmts:\\.\root\cimv2")
  Dim fn_objWMIService    : Set fn_objWMIService      = GetObject("winmgmts:\\.\root\cimv2")
  Dim objReg              : Set objReg                = GetObject("winmgmts:\\.\root\default:StdRegProv")
  Dim objLogFile
  Dim CurrentDir          : CurrentDir                = Left(Wscript.ScriptFullname, InstrRev(Wscript.ScriptFullname, "\"))
                            CurrentDir                = Left(CurrentDir,len(CurrentDir)-1)
  Dim strcomputerName     : strcomputerName           = objProcessEnv("COMPUTERNAME")
  Dim strLogLocation      : strLogLocation            = "C:\WINDOWS\system32\Logfiles"
  Dim strOutputFile       : strOutputFile             = strLogLocation & "\" & strcomputerName & "_Installation_C++Runtimes_" & Replace(FormatDateTime(Now(), 2),"/","-") & ".log"
  Dim strArchitecture     : strArchitecture           = ""
  Dim strCurrentUser      : strCurrentUser            = ""
  Dim strCurrentUserSID   : strCurrentUserSID         = "" 
  Dim strOS               : strOS                     = ""
  Dim strCommand          : strCommand                = ""
  Dim strLine             : strLine                   = ""
  Dim strQuery            : strQuery                  = ""
  Dim strCommonDesktop    : strCommonDesktop          = ""
  Dim strArray            : strArray                  = ""  
  Dim strAppDataFolder    : strAppDataFolder          = ""
  Dim strProcess          : strProcess                = ""
  Dim strValue            : strValue                  = ""
  Dim strKeyPath          : strKeyPath                = ""
  Dim strValueName        : strValueName              = ""
  Dim strLogFile
  Dim dwValue             : dwValue                   = 0
  Dim arrFolderUnsorted   : Redim arrFolderUnsorted(0)

  Dim arrArguments
  Dim arrLanguage
  Dim valCounter
  Dim valResult 
  Dim valReturnCode

  Dim colProcess, objProcess 
  Dim valOSBuildNumber
  Dim objSubfolder
  Dim colItems, objItem, Subfolder
  Dim colSoftware, objSoftware
  Dim arrValues, strHolder

  dim objFolders, objFolder, arrFolders, arrVersions, objVersion


  Const ForWriting           = 2
  Const ForReading           = 1
  Const ForAppending         = 8
  Const OverWriteFiles       = True
  const HKEY_CURRENT_USER    = &H80000001
  const HKEY_LOCAL_MACHINE   = &H80000002
  Const HKEY_USERS           = &H80000003 

' ------------------------------------------------------------------------------------------------
' Create the log location (if not exists)
' Open the logfile.  
' ------------------------------------------------------------------------------------------------

  CreateFolderStructure(strLogLocation)
  OpenLogFile()
  WriteToLog "- ACTION: script started."
  WriteToLog " "

' ------------------------------------------------------------------------------------------------
' Detect the current OS.  
' ------------------------------------------------------------------------------------------------

  Set colItems = objWMIService.ExecQuery("Select Caption,BuildNumber from Win32_OperatingSystem")
  For Each objItem in colItems
      strOS            = objItem.Caption
      valOSBuildNumber = objItem.BuildNumber
  next

' ------------------------------------------------------------------------------------------------
' Detect the current processor architecture.  
' ------------------------------------------------------------------------------------------------

  if objFSO.FolderExists(objShell.ExpandEnvironmentStrings("%windir%") & "\SysWOW64\Config") then  
     strArchitecture = "x64"
     arrVersions=Array("x86","x64")
       else
     strArchitecture = "x86"
     arrVersions=Array("x86")
  end if


  WriteToLog("########## Details regarding operating system                        ##########")
  WriteToLog("Found Operating System:       " & strOS)
  WriteToLog("Found architecture:           " & strArchitecture)
  WriteToLog("########## End details regarding operating system                    ##########")
  WriteToLog(" ")
  WriteToLog("########## Installation                                              ##########")

' ------------------------------------------------------------------------------------------------
' Sets SEE_MASK_NOZONECHECKS to 1.  
' That will avoid a screen that asks for permission to run an application from
' a share or mapped drive. 
' ------------------------------------------------------------------------------------------------

  objProcessEnv("SEE_MASK_NOZONECHECKS") = 1
  
  ' ------------------------------------------------------------------------------------------------
  ' Start the installation:
  '  1. Loop throu all the subfolders, sorted.
  '     Source: 
  '     http://blogs.technet.com/b/heyscriptingguy/archive/2004/11/22/how-can-i-list-the-members-of-a-group-in-alphabetical-order.aspx
  '  2. Depending on the foldername the correct parameters are passed to the vcredit_xx.exe
  '     Logging enabled.
  ' ------------------------------------------------------------------------------------------------ 

  ' 1: Get all the subfolder of the parent folder.

  valCounter  = 0
  set objFolders = objFSO.GetFolder(CurrentDir)
  Set arrFolders = objFolders.SubFolders
  For Each objFolder in arrFolders
      arrFolderUnsorted(valCounter) = objFolder.Name
      Redim Preserve arrFolderUnsorted(valCounter+1)
      valCounter = valCounter + 1
  Next   

  Redim Preserve arrFolderUnsorted(valCounter-1)
  Dim j

  ' 2: Sort them:

  For valCounter = (UBound(arrFolderUnsorted) - 1) to 0 Step -1
    For j= 0 to valCounter
        If UCase(arrFolderUnsorted(j)) > UCase(arrFolderUnsorted(j+1)) Then
            strHolder = arrFolderUnsorted(j+1)
            arrFolderUnsorted(j+1) = arrFolderUnsorted(j)
            arrFolderUnsorted(j) = strHolder
        End If
    Next
  Next

  ' 3: Install

  For valCounter = 0 to ubound(arrFolderUnsorted) ' I know: the folders are sorted now....

      if instr(arrFolderUnsorted(valCounter),"2005") > 0 Then InstallCPlusPlus2005Runtimes
      if instr(arrFolderUnsorted(valCounter),"2008") > 0 Then InstallCPlusPlus2008Runtimes
      if instr(arrFolderUnsorted(valCounter),"2010") > 0 Then InstallCPlusPlus2010Runtimes
      if instr(arrFolderUnsorted(valCounter),"2012") > 0 Then InstallCPlusPlus2012Runtimes
      if instr(arrFolderUnsorted(valCounter),"2013") > 0 Then InstallCPlusPlus2013Or2015Runtimes
      if instr(arrFolderUnsorted(valCounter),"2015") > 0 Then InstallCPlusPlus2013Or2015Runtimes

  next

  WriteToLog("########## End Installation                                          ##########")
  WriteToLog("########## Summary of installed C++ Redistributables                 ##########")
  WriteToLog(" ")

  Set colSoftware = objWMIService.ExecQuery("Select * from Win32_Product Where Name LIKE '%Visual C++%' AND (Name LIKE '%Redistributable%' OR Name LIKE '%Runtime%')")
  For Each objSoftware in colSoftware
      WriteToLog("Name:     " & objSoftware.Name)
      WriteToLog("Version:  " & objSoftware.Version)
      WriteToLog(" ")
  Next


  WriteToLog(" ")
  WriteToLog("########## End summary of installed C++ Redistributables             ##########")
  WriteToLog(" ")

  CloseLogFile()
  wscript.quit 0

Sub OpenLogFile() 

' ------------------------------------------------------------------------------------------------
' Subroutine: OpenLogFile() 
' The name of the logfile is mentinoed in the variabele strOutputFile.
' ------------------------------------------------------------------------------------------------

  If objLogFileFSO.FileExists(strOutputFile) Then
     Set objLogFile = objLogFileFSO.OpenTextFile(strOutputFile, ForWriting)
         Else
     Set objLogFile = objLogFileFSO.CreateTextFile(strOutputFile)
  End If

End Sub

Sub CloseLogFile()

' ------------------------------------------------------------------------------------------------
' Subroutine: CloseLogFile()
' Close the log file.
' ------------------------------------------------------------------------------------------------

  WriteToLog "- ACTION: script ended."
  objLogFile.Close
  Set objLogfileFSO = Nothing

End Sub

Function WriteToLog(sLogMessage)

' ------------------------------------------------------------------------------------------------
' Function: WriteToLog(sLogMessage)
' Writes an entry 'sLogMessage' in the logfile.
' ------------------------------------------------------------------------------------------------

  if instr(sLogMessage, "- ACTION: ") = 0 then sLogMessage = "          " & sLogMessage
  objLogFile.WriteLine("Time: " & now & "  " & sLogMessage)

End Function

Sub CreateFolderStructure(strFolderNameToBeCreated)

' ------------------------------------------------------------------------------------------------
' Subroutine: CreateFolderStructure(strFolderNameToBeCreated)
' Creates the map as mentioned in strFolderNameToBeCreated.
' ------------------------------------------------------------------------------------------------

  Dim arrFoldersTMP : arrFoldersTMP = split (strFolderNameToBeCreated,"\")
  Dim strFolder  : strFolder  = ""
  Dim objFolderTMP
 
  For Each objFolderTMP in arrFoldersTMP
      strFolder = strFolder & objFolderTMP
      If NOT objFSO.FolderExists(strFolder) Then
             objFSO.CreateFolder(strFolder)
      end If
      strFolder = strFolder & "\"
  Next
 
End Sub

Function fnKillProcess(strProcessName)

' ------------------------------------------------------------------------------------------------
' Function: fnKillProcess(strProcessName)
' Terminates the given processname.
' ------------------------------------------------------------------------------------------------

  Set colProcess = fn_objWMIService.ExecQuery ("Select * From Win32_Process")
  For Each objProcess In colProcess
    If Instr(LCase(objProcess.Name),LCase(strProcessName)) > 0 Then
       objShell.Run "TASKKILL /F /T /IM " & objProcess.Name, 0, False
       objProcess.Terminate()
       WriteToLog("Terminating application: " & objProcess.Name)
    End If
  Next

End Function

Sub InstallCPlusPlus2005Runtimes
' ------------------------------------------------------------------------------------------------
' Subroutine: InstallCPlusPlus2005Runtimes
' Installs the C++ 2005 Runtime modules.
' ------------------------------------------------------------------------------------------------

  for Each objVersion in arrVersions
      if instr(arrFolderUnsorted(valCounter),"MFC") > 0 Then
         strLogFile = right(arrFolderUnsorted(valCounter),len(arrFolderUnsorted(valCounter))-2) & " (" & objVersion & ").log" 
         strCommand = chr(34) & CurrentDir & "\" & arrFolderUnsorted(valCounter) & "\vcredist_" & objVersion & ".exe" & chr(34) & " /t:c:\temp /q"
         strCommand = strCommand & ":a /c:" & chr(34) & "msiexec /i vcredist.msi /qb! /l*v "
         strCommand = strCommand & chr(34) & chr(34) & strLogLocation & "\" & strLogFile & chr(34) & chr(34) & chr(34)
         WriteToLog("Running command: " & strCommand)
         valResult = objShell.Run(strCommand, 6, True)
         WriteToLog("Result: " & valResult)
           else
         strCommand = chr(34) & CurrentDir & "\" & arrFolderUnsorted(valCounter) & "\vcredist_" & objVersion & ".exe" & chr(34) & " /q"
         WriteToLog("Running command: " & strCommand)
         valResult = objShell.Run(strCommand, 6, True)
         WriteToLog("Result: " & valResult)
     end if
  next

End sub

Sub InstallCPlusPlus2008Runtimes
' ------------------------------------------------------------------------------------------------
' Subroutine: InstallCPlusPlus2008Runtimes
' Installs the C++ 2008 Runtime modules.
' ------------------------------------------------------------------------------------------------

  for Each objVersion in arrVersions
      strLogFile = right(arrFolderUnsorted(valCounter),len(arrFolderUnsorted(valCounter))-2) & " (" & objVersion & ").log" 
      strCommand = chr(34) & CurrentDir & "\" & arrFolderUnsorted(valCounter) & "\vcredist_" & objVersion & ".exe" & chr(34) & " /q /l "
      strCommand = strCommand & chr(34) & strLogLocation & "\" & strLogFile & chr(34)
      WriteToLog("Running command: " & strCommand)
      valResult = objShell.Run(strCommand, 6, True)
      WriteToLog("Result: " & valResult)
  next
  
End sub

Sub InstallCPlusPlus2010Runtimes
' ------------------------------------------------------------------------------------------------
' Subroutine: InstallCPlusPlus2010Runtimes
' Installs the C++ 2010 Runtime modules.
' ------------------------------------------------------------------------------------------------

  for Each objVersion in arrVersions
      strLogFile = right(arrFolderUnsorted(valCounter),len(arrFolderUnsorted(valCounter))-2) & " (" & objVersion & ").log" 
      strCommand = chr(34) & CurrentDir & "\" & arrFolderUnsorted(valCounter) & "\vcredist_" & objVersion & ".exe" & chr(34) & " /passive /norestart /log "
      strCommand = strCommand & chr(34) & strLogLocation & "\" & strLogFile & chr(34)
      WriteToLog("Running command: " & strCommand)
      valResult = objShell.Run(strCommand, 6, True)
      WriteToLog("Result: " & valResult)
  next

End sub

Sub InstallCPlusPlus2012Runtimes
' ------------------------------------------------------------------------------------------------
' Subroutine: InstallCPlusPlus2012Runtimes
' Installs the C++ 2012 Runtime modules.
' ------------------------------------------------------------------------------------------------

  for Each objVersion in arrVersions
      strLogFile = right(arrFolderUnsorted(valCounter),len(arrFolderUnsorted(valCounter))-2) & " (" & objVersion & ").log" 
      strCommand = chr(34) & CurrentDir & "\" & arrFolderUnsorted(valCounter) & "\vcredist_" & objVersion & ".exe" & chr(34) & " /install /passive /norestart /log "
      strCommand = strCommand & chr(34) & strLogLocation & "\" & strLogFile & chr(34)
      WriteToLog("Running command: " & strCommand)
      valResult = objShell.Run(strCommand, 6, True)
      WriteToLog("Result: " & valResult)
  next

End sub

Sub InstallCPlusPlus2013Or2015Runtimes
' ------------------------------------------------------------------------------------------------
' Subroutine: InstallCPlusPlus2013Or2015Runtimes
' Installs the C++ 2013 Runtime modules.
' ------------------------------------------------------------------------------------------------

  for Each objVersion in arrVersions
      strLogFile = right(arrFolderUnsorted(valCounter),len(arrFolderUnsorted(valCounter))-2) & " (" & objVersion & ").log" 
      strCommand = chr(34) & CurrentDir & "\" & arrFolderUnsorted(valCounter) & "\vcredist_" & objVersion & ".exe" & chr(34) & " /install /passive /norestart /log "
      strCommand = strCommand & chr(34) & strLogLocation & "\" & strLogFile & chr(34)
      WriteToLog("Running command: " & strCommand)
      valResult = objShell.Run(strCommand, 6, True)
      WriteToLog("Result: " & valResult)
  next

End sub            

Link to the files, including the code.




Same homepage for Firefox as for Internet Explorer

Sometimes each country has a different homepage. In Internet Explorer you can set each homepage via the policy. Also that can be done for Firefox in combination with GPO For Firefox. But it also generates extra administrative load as the same setting should be maintained at 2 places.

To avoid this, I made a script that reads the current Internet Explorer homepage (set via policy) and set is as the default homepage for Firefox.

' ================================================================================================
' Sets the Firefox homedirectory to the same as Internet Explorer.
' If the default Internet Explorer homepage has not been set or the default Microsoft homepage is
' used, then about:blank will be opened.
' Also, force this setting, so the user cannot override the homepage setting to, for example, pages
' from the last session. 
' 
' Created by Willem-Jan Vroom
' Version history:
'
'   0.0.1 Initial version
' 
' ================================================================================================

' ------------------------------------------------------------------------------------------------
' Declare the most variables. 
' ------------------------------------------------------------------------------------------------

  Option Explicit

  Dim objShell                          : set objShell                      = CreateObject("WScript.Shell")
  Dim objNetWork                        : set objNetWork                    = CreateObject("WScript.Network")
  Dim objLogFile                        : Set objLogFile                    = CreateObject("Scripting.FileSystemObject")
  Dim objLogFileFSO                     : Set objLogFileFSO                 = CreateObject("Scripting.FileSystemObject")
  Dim objFSO                            : Set objFSO                        = CreateObject("Scripting.FileSystemObject")
  Dim objProcessEnv                     : Set objProcessEnv                 = objShell.Environment("PROCESS")
  Dim objWMIService                     : Set objWMIService                 = GetObject("winmgmts:\\.\root\cimv2")
  Dim objReg                            : Set objReg                        = GetObject("winmgmts:\\.\root\default:StdRegProv")
  Dim CurrentDir                        : CurrentDir                        = Left(Wscript.ScriptFullname, InstrRev(Wscript.ScriptFullname, "\"))
  Dim strcomputerName                   : strcomputerName                   = objProcessEnv("COMPUTERNAME")
  Dim strLogLocation                    : strLogLocation                    = "C:\WINDOWS\system32\Logfiles"
  Dim strOutputFile                     : strOutputFile                     = strLogLocation & "\" & strcomputerName & "_Set_Firefox_Homepage" & Replace(FormatDateTime(Now(), 2),"/","-") & ".log"
  Dim strArchitecture                   : strArchitecture                   = "x86"
  Dim strCurrentUser                    : strCurrentUser                    = ""
  Dim strCurrentUserSID                 : strCurrentUserSID                 = "" 
  Dim strOS                             : strOS                             = ""
  Dim strKeyPath                        : strKeyPath                        = ""
  Dim strIEStartPage                    : strIEStartPage                    = ""
  Dim strFFStartPage                    : strIEStartPage                    = ""
  Dim strCommand                        : strCommand                        = ""
  Dim strWindir                         : strWinDir                         = objShell.ExpandEnvironmentStrings("%WinDir%")
  
  Dim colItems
  Dim objItem
  Dim colComputers
  Dim objComputer


  Const ForWriting           = 2
  Const ForReading           = 1
  Const ForAppending         = 8
  Const OverWriteFiles       = True
  const HKEY_CURRENT_USER    = &H80000001
  const HKEY_LOCAL_MACHINE   = &H80000002
  Const HKEY_USERS           = &H80000003 

' ------------------------------------------------------------------------------------------------
' Create the log location (if not exists)
' Open the logfile.  
' ------------------------------------------------------------------------------------------------

  CreateFolderStructure(strLogLocation)
  OpenLogFile()
  WriteToLog "- ACTION: script started."

' ------------------------------------------------------------------------------------------------
' Detect the current OS.  
' ------------------------------------------------------------------------------------------------

  Set colItems = objWMIService.ExecQuery("Select Caption,BuildNumber from Win32_OperatingSystem")
  For Each objItem in colItems
      strOS            = objItem.Caption
      valOSBuildNumber = objItem.BuildNumber
  next

' ------------------------------------------------------------------------------------------------
' Find the currently logged on userid.
' And translate it to the users SID.
' ------------------------------------------------------------------------------------------------

  Set colComputers = objWMIService.ExecQuery("Select * from Win32_ComputerSystem")
  For Each objComputer in colComputers
      strCurrentUser= objComputer.UserName
  Next
  strCurrentUserSID = GetSIDFromUser(strCurrentUser)

' ------------------------------------------------------------------------------------------------
' Detect the current processor architecture.  
' ------------------------------------------------------------------------------------------------

  if objFSO.FolderExists(strWindir & "\syswow64") Then
     strArchitecture = "x64"
  end if  

  WriteToLog("########## Details regarding operating system and logged on user ##########")
  WriteToLog("Found Operating System: " & strOS)
  WriteToLog("Found architecture:     " & strArchitecture)
  WriteToLog("Logged on userid:       " & strCurrentUser)
  WriteToLog("Logged on user SID:     " & strCurrentUserSID)

' ------------------------------------------------------------------------------------------------
' Find the current homedir (from the current logon user)  
' It is stored in HKCU\Software\Microsoft\Internet Explorer\Main, hive ‘Start Page’
' ------------------------------------------------------------------------------------------------

  WriteToLog("- ACTION: Read Registry hive")
  WriteToLog("  HKEY_USERS\" & strCurrentUserSID & "\Software\Microsoft\Internet Explorer\Main")
  WriteToLog("     Hive: 'Start Page'")
  objReg.GetStringValue HKEY_USERS, strCurrentUserSID & "\Software\Microsoft\Internet Explorer\Main","Start Page",strIEStartPage
  WriteToLog("IE Start Page:          " & strIEStartPage)

' ------------------------------------------------------------------------------------------------
' Check if the home page starts with http://www.microsoft.com/isapi/redir.dll
' In that case the homepage for Firefox will be changed to about:blank
' ------------------------------------------------------------------------------------------------

  if instr(strIEStartPage, "http://www.microsoft.com/isapi/redir.dll") > 0 then
     WriteToLog("The firefox homepage will be set to about:blank as the default Internet Explorer page has already been set.")     
     strIEStartPage = "about:blank"
  end if

' ------------------------------------------------------------------------------------------------
' Set the Firefox homepage.
' ------------------------------------------------------------------------------------------------

  WriteToLog("- ACTION: Set the Firefox homepage to: " & strIEStartPage)
  objReg.CreateKey HKEY_LOCAL_MACHINE, "Software\Policies\Mozilla\lockPref"
  objReg.SetStringValue HKEY_LOCAL_MACHINE, "Software\Policies\Mozilla\lockPref", "browser.startup.homepage", strIEStartPage
  objReg.GetStringValue HKEY_LOCAL_MACHINE, "Software\Policies\Mozilla\lockPref", "browser.startup.homepage", strFFStartPage
  WriteToLog("- ACTION: Verify the Firefox homepage.")
  WriteToLog("  HKEY_LOCAL_MACHINESoftware\Policies\Mozilla\lockPref")
  WriteToLog("     Hive: 'browser.startup.homepage' has been set to " & strFFStartPage)
  WriteToLog(" ")
  
' ------------------------------------------------------------------------------------------------
' Force the use of the homepage.
' ------------------------------------------------------------------------------------------------

  WriteToLog("- ACTION: Force the use of the homepage " & strIEStartPage)
  objReg.SetStringValue HKEY_LOCAL_MACHINE, "Software\Policies\Mozilla\lockPref", "browser.startup.page", "1"
  objReg.GetStringValue HKEY_LOCAL_MACHINE, "Software\Policies\Mozilla\lockPref", "browser.startup.page", strFFStartPage
  WriteToLog("- ACTION: Verify the force of using the homepage.")
  WriteToLog("  HKEY_LOCAL_MACHINESoftware\Policies\Mozilla\lockPref")
  WriteToLog("     Hive: 'browser.startup.page' has been set to " & strFFStartPage)
  WriteToLog(" ")  

' ------------------------------------------------------------------------------------------------
' We are done!
' ------------------------------------------------------------------------------------------------

  CloseLogFile()
  wscript.Quit 0


Sub OpenLogFile() 

' ------------------------------------------------------------------------------------------------
' Subroutine: OpenLogFile() 
' The name of the logfile is mentinoed in the variabele strOutputFile.
' ------------------------------------------------------------------------------------------------

  If objLogFileFSO.FileExists(strOutputFile) Then
     Set objLogFile = objLogFileFSO.OpenTextFile(strOutputFile, ForWriting)
         Else
     Set objLogFile = objLogFileFSO.CreateTextFile(strOutputFile)
  End If

End Sub

Sub CloseLogFile()

' ------------------------------------------------------------------------------------------------
' Subroutine: CloseLogFile()
' Close the log file.
' ------------------------------------------------------------------------------------------------

  WriteToLog("########## End configuring Firefox          ##########")
  WriteToLog "- ACTION: script ended."
  objLogFile.Close
  Set objLogfileFSO = Nothing

End Sub

Function WriteToLog(sLogMessage)

' ------------------------------------------------------------------------------------------------
' Function: WriteToLog(sLogMessage)
' Writes an entry 'sLogMessage' in the logfile.
' ------------------------------------------------------------------------------------------------

  if instr(sLogMessage, "- ACTION: ") = 0 then sLogMessage = "          " & sLogMessage
  objLogFile.WriteLine("Time: " & now & "  " & sLogMessage)

End Function


Sub CreateFolderStructure(strFolderNameToBeCreated)

' ------------------------------------------------------------------------------------------------
' Subroutine: CreateFolderStructure(strFolderNameToBeCreated)
' Creates the map as mentioned in strFolderNameToBeCreated.
' ------------------------------------------------------------------------------------------------

  Dim arrFoldersTMP : arrFoldersTMP = split (strFolderNameToBeCreated,"\")
  Dim strFolder  : strFolder  = ""
  Dim objFolderTMP
 
  For Each objFolderTMP in arrFoldersTMP
      strFolder = strFolder & objFolderTMP
      If NOT objFSO.FolderExists(strFolder) Then
             objFSO.CreateFolder(strFolder)
      end If
      strFolder = strFolder & "\"
  Next
 
End Sub

Function GetSIDFromUser(UserName)

' ------------------------------------------------------------------------------------------------
' Function: GetSIDFromUser(UserName)
' Gets the SID from the give username.
' ------------------------------------------------------------------------------------------------

  Dim DomainName, Result, WMIUser

  If InStr(UserName, "\") > 0 Then
    DomainName = Mid(UserName, 1, InStr(UserName, "\") - 1)
    UserName = Mid(UserName, InStr(UserName, "\") + 1)
  Else
    DomainName = CreateObject("WScript.Network").UserDomain
  End If

  On Error Resume Next
  Set WMIUser = GetObject("winmgmts:{impersonationlevel=impersonate}!" _
    & "/root/cimv2:Win32_UserAccount.Domain='" & DomainName & "'" _
    & ",Name='" & UserName & "'")
  If Err.Number = 0 Then
    Result = WMIUser.SID
  Else
    Result = ""
  End If
  On Error GoTo 0

  GetSIDFromUser = Result

End Function



Reinstall all virtual applications deployed by SCCM 2007

The client I am working for now, uses SCCM 2007 to deploy App-V 4.6 packages. In the past it was needed to re-install both the SCCM 2007 and App-V client. As a result that the user has to re-install all the virtual applications.

To avoid this I made a vbscript that reruns every advertisement that points to a virtual application. This script is based on the following article on MyITForum: Re-running advertisements on an Advanced Client.

' ================================================================================================
' Installs all the AppV Packages again
' Created by Willem-Jan Vroom
' Version history:
'
' v0.0.1
'   Initial version
'
' v.0.0.2
'   Added support to rerun all the advertisements for the virtual packages. 
' ================================================================================================

' ------------------------------------------------------------------------------------------------
' Declare the most variables. 
' ------------------------------------------------------------------------------------------------

  Option Explicit

  Dim objShell               : set objShell         = WScript.CreateObject("WScript.Shell")
  Dim objNetWork             : set objNetWork       = Wscript.CreateObject("WScript.Network")
  Dim objLogFileFSO          : Set objLogFileFSO    = CreateObject("Scripting.FileSystemObject")
  Dim objFSO                 : Set objFSO           = CreateObject("Scripting.FileSystemObject")
  Dim objProcessEnv          : Set objProcessEnv    = objShell.Environment("PROCESS")
  Dim objWMIService          : Set objWMIService    = GetObject("winmgmts:\\.\root\cimv2")
  Dim objReg                 : Set objReg           = GetObject("winmgmts:\\.\root\default:StdRegProv")
  Dim objLogFile
  Dim colListOfServices
  Dim objService 	
  Dim strCurrentDir          : strCurrentDir        = Left(Wscript.ScriptFullname, InstrRev(Wscript.ScriptFullname, "\"))
                               strCurrentDir        = Left(strCurrentDir,len(strCurrentDir)-1)
  Dim strCommand             : strCommand           = ""
  Dim strLogLocation         : strLogLocation       = "C:\WINDOWS\system32\Logfiles"
  Dim strcomputerName        : strcomputerName      = objProcessEnv("COMPUTERNAME")
  Dim strOutputFile          : strOutputFile        = strLogLocation & "\" & strcomputerName & "_ReinstallAllAppVPackages_" & Replace(FormatDateTime(Now(), 2),"/","-") & ".log"
  Dim strOS                  : strOS                = ""
  Dim strKeyPath             : strKeyPath           = ""
  Dim strArchitecture        : strArchitecture      = "x86"
  Dim strWindir              : strWinDir            = objShell.ExpandEnvironmentStrings("%WinDir%")


  Dim valOSBuildNumber, valResult
  Dim objItem, colItems
  Dim arrSubKeys, objSubKey

  Const ForWriting           = 2
  Const ForReading           = 1
  Const ForAppending         = 8
  Const OverWriteFiles       = True
  const HKEY_CURRENT_USER    = &H80000001
  const HKEY_LOCAL_MACHINE   = &H80000002
  Const HKEY_USERS           = &H80000003 

' ------------------------------------------------------------------------------------------------
' Detect the current OS architecture.  
' ------------------------------------------------------------------------------------------------
 
  if objFSO.FolderExists(strWindir & "\syswow64") Then
     strArchitecture = "x64"
  end if

' ------------------------------------------------------------------------------------------------
' If run on a x64 OS, then start the application again, but with the 32 bits wscript.exe.
' This is needed as the SCCM Parts are 32 bits only.   
' ------------------------------------------------------------------------------------------------

  if strArchitecture = "x64" and instr(lcase(wscript.FullName),"system32") > 0 Then
     strCommand = strWinDir & "\syswow64\wscript.exe " & chr(34) & wscript.scriptfullname & chr(34)
     valResult = objShell.Run (strCommand,0,True)
     wscript.quit (valResult)
  end if

' ------------------------------------------------------------------------------------------------
' Create the log location (if not exists)
' Open the logfile.  
' ------------------------------------------------------------------------------------------------

  CreateFolderStructure(strLogLocation)
  OpenLogFile()
  WriteToLog "- ACTION: script started."

' ------------------------------------------------------------------------------------------------
' Detect the current OS.  
' ------------------------------------------------------------------------------------------------

  Set colItems = objWMIService.ExecQuery("Select Caption,BuildNumber from Win32_OperatingSystem")
  For Each objItem in colItems
      strOS            = objItem.Caption
      valOSBuildNumber = objItem.BuildNumber
  Next

  WriteToLog("########## Details regarding operating system and logged on user        ##########")
  WriteToLog("Found Operating System:    " & strOS)
  WriteToLog("Found OS architecture:     " & strArchitecture)
  WriteToLog("Wscript engine:            " & wscript.FullName)
  WriteToLog("########## End details regarding operating system and logged on user    ##########")
  WriteToLog(" ")

' ------------------------------------------------------------------------------------------------
' Reinstall the App-V packages that have been installed by SCCM.  
' The location of the package are:
' on x86:
'  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\SMS\Mobile Client\Software Distribution\
'                     VirtualAppPackages\{PKG GUID}
' 
' on x64:
'  HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\SMS\Mobile Client\Software Distribution\
'                     VirtualAppPackages\{PKG GUID}
' ------------------------------------------------------------------------------------------------

  if strArchitecture = "x64" then
     strKeyPath = "SOFTWARE\Wow6432Node\Microsoft\SMS\Mobile Client\Software Distribution\VirtualAppPackages"
      else
     strKeyPath = "SOFTWARE\Microsoft\SMS\Mobile Client\Software Distribution\VirtualAppPackages"
  end if
  objReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys
  if IsArray(arrSubKeys) Then
     For Each objSubKey in arrSubKeys
         RerunAppVPackageAdvertisement(strKeyPath & "\" & objSubKey)
     Next
     else 
    WriteToLog("No AppV packages in SCCM have been found. Thus quitting.")
  end if
  CloseLogFile()


Sub OpenLogFile() 

' ------------------------------------------------------------------------------------------------
' Subroutine: OpenLogFile() 
' The name of the logfile is mentinoed in the variabele strOutputFile.
' ------------------------------------------------------------------------------------------------

  If objLogFileFSO.FileExists(strOutputFile) Then
     Set objLogFile = objLogFileFSO.OpenTextFile(strOutputFile, ForAppending)
         Else
     Set objLogFile = objLogFileFSO.CreateTextFile(strOutputFile)
  End If

End Sub


Function WriteToLog(sLogMessage)

' ------------------------------------------------------------------------------------------------
' Function: WriteToLog(sLogMessage)
' Writes an entry 'sLogMessage' in the logfile.
' ------------------------------------------------------------------------------------------------

  if instr(sLogMessage, "- ACTION: ") = 0 then sLogMessage = "          " & sLogMessage
  objLogFile.WriteLine("Time: " & now & "  " & sLogMessage)

End Function

Sub CloseLogFile()

' ------------------------------------------------------------------------------------------------
' Subroutine: CloseLogFile()
' Close the log file.
' ------------------------------------------------------------------------------------------------
  WriteToLog("########## End repairing all the AppV Packages.                         ##########")
  WriteToLog("- ACTION: script ended.")           
  objLogFile.Close
  Set objLogfileFSO = Nothing

End Sub


Sub CreateFolderStructure(strFolderNameToBeCreated)

' ------------------------------------------------------------------------------------------------
' Subroutine: CreateFolderStructure(strFolderNameToBeCreated)
' Creates the map as mentioned in strFolderNameToBeCreated.
' ------------------------------------------------------------------------------------------------

  Dim arrFoldersTMP : arrFoldersTMP = split (strFolderNameToBeCreated,"\")
  Dim strFolder     : strFolder     = ""
  Dim objFolderTMP
 
  For Each objFolderTMP in arrFoldersTMP
      strFolder = strFolder & objFolderTMP
      If NOT objFSO.FolderExists(strFolder) Then
             objFSO.CreateFolder(strFolder)
      end If
      strFolder = strFolder & "\"
  Next
 
End Sub

Sub RerunAppVPackageAdvertisement(key)

' ------------------------------------------------------------------------------------------------
' Subroutine: RerunAppVPackageAdvertisement(key)
' Reinstalls the AppV application as mentioned in the key by rerunning the advertisement by
' checking the hive 'SCCM Advert IDs'. 
' This part is based on the following article:
' http://www.myitforum.com/articles/8/view.asp?id=6841
' ------------------------------------------------------------------------------------------------

  Dim arrSCCMAdvID            : objReg.GetMultiStringValue HKEY_LOCAL_MACHINE, key, "SCCM Advert IDs",       arrSCCMAdvID
  Dim strSoftGridPackageName  : objReg.GetStringValue HKEY_LOCAL_MACHINE,      key, "SoftGrid Package Name", strSoftGridPackageName
  Dim strSCCMAdvID            : strSCCMAdvID=arrSCCMAdvID(0)
  Dim strOldRerunBehavior
  WriteToLog ("---------------------------------------------------------------------------------")
  WriteToLog ("Processing SCCM AppV Package: " & strSoftGridPackageName & " with advertisement ID " & strSCCMAdvID & ".")

  WriteToLog ("Step 1: Get the ID of the ScheduledMessage on the client.")
  Dim objNMS                  : Set objNMS        = GetObject("winmgmts:\\.\root\ccm\policy\machine\actualconfig")
  Dim objSched, objScheds     : Set objScheds     = objNMS.ExecQuery("Select * From CCM_Scheduler_ScheduledMessage")
  Dim strSchMsgID

  For Each objSched in objScheds
      if instr(objSched.ScheduledMessageID, strSCCMAdvID) > 0 Then
         strSchMsgID = objSched.ScheduledMessageID
         Exit For
      End if
  next
  WriteToLog ("        Found Scheduled Message ID: " & strSchMsgID)
      
  WriteToLog ("Step 2: Change the rerun behavior to 'RerunAlways'.")
  Set objNMS        = GetObject("winmgmts:\\.\root\ccm\policy\machine\actualconfig")
  Set objScheds     = objNMS.ExecQuery("select * from CCM_SoftwareDistribution where ADV_AdvertisementID = '" & strSCCMAdvID & "'")
  For Each objSched in objScheds
      strOldRerunBehavior = objSched.ADV_RepeatRunBehavior
      objSched.ADV_RepeatRunBehavior = "RerunAlways"
      objSched.Put_ 0
  Next
  
  WriteToLog ("Step 3: Rerun the advertisement.")
  Set objNMS        = GetObject("winmgmts:\\.\root\ccm")
  Dim objSMSClient             :  Set objSMSClient = objNMS.Get("SMS_Client")
  objSMSClient.TriggerSchedule strSchMsgID
  wscript.sleep 18000

  WriteToLog ("Step 4: Change the rerun behavior back to '" & strOldRerunBehavior & "'.")
  Set objNMS        = GetObject("winmgmts:\\.\root\ccm\policy\machine\actualconfig")
  Set objScheds     = objNMS.ExecQuery("select * from CCM_SoftwareDistribution where ADV_AdvertisementID = '" & strSCCMAdvID & "'")
  For Each objSched in objScheds
      objSched.ADV_RepeatRunBehavior = strOldRerunBehavior
      objSched.Put_ 0
  Next
  WriteToLog ("The rerun for " & strSoftGridPackageName & " has been completed.")
  WriteToLog ("---------------------------------------------------------------------------------")
  WriteToLog (" ")

End Sub