578 lines
17 KiB
XML
578 lines
17 KiB
XML
<job id="ZTIApplications">
|
|
<script language="VBScript" src="ZTIUtility.vbs"/>
|
|
<script language="VBScript" src="ZTIConfigFile.vbs"/>
|
|
<script language="VBScript">
|
|
|
|
' // ***************************************************************************
|
|
' //
|
|
' // Copyright (c) Microsoft Corporation. All rights reserved.
|
|
' //
|
|
' // Microsoft Deployment Toolkit Solution Accelerator
|
|
' //
|
|
' // File: ZTIApplications.wsf
|
|
' //
|
|
' // Version: 6.3.8456.1000
|
|
' //
|
|
' // Purpose: Install a list of applications
|
|
' //
|
|
' // Usage: cscript.exe [//nologo] ZTIApplications.wsf [/debug:true]
|
|
' //
|
|
' // ***************************************************************************
|
|
|
|
Option Explicit
|
|
RunNewInstance
|
|
|
|
|
|
'//----------------------------------------------------------------------------
|
|
'// Main Class
|
|
'//----------------------------------------------------------------------------
|
|
|
|
Class ZTIApplications
|
|
|
|
'//----------------------------------------------------------------------------
|
|
'// Class instance variable declarations
|
|
'//----------------------------------------------------------------------------
|
|
|
|
Dim oApplications
|
|
Dim oInstalledApplications
|
|
' Dim oXMLDoc
|
|
Dim oXMLApps
|
|
Dim dAvaiableApps
|
|
Dim sBDDRun
|
|
Dim aLanguages
|
|
Dim oDependentApplications
|
|
|
|
Dim g_ApplicationSuccessCodes
|
|
|
|
|
|
'//----------------------------------------------------------------------------
|
|
'// Constructor to initialize needed global objects
|
|
'//----------------------------------------------------------------------------
|
|
|
|
Private Sub Class_Initialize
|
|
|
|
g_ApplicationSuccessCodes = " 0 3010 "
|
|
End Sub
|
|
|
|
|
|
'//----------------------------------------------------------------------------
|
|
'// Main routine
|
|
'//----------------------------------------------------------------------------
|
|
|
|
Function Main
|
|
|
|
Dim iRetVal, sGuid, sCmd, bValidProcessorType
|
|
Dim iApplicationCount, iPercent
|
|
Dim sApplicationType
|
|
|
|
iRetVal = Success
|
|
|
|
' Validate that are not restarting from a failed install.
|
|
|
|
If ucase(oEnv("SystemDrive")) = "X:" Then
|
|
oLogging.CreateEntry "Environment Error: ManualRetry (From ZTIApplications).", LogTypeInfo
|
|
|
|
oEnvironment.Item("LTISuspend") = "LiteTouch is trying to install applications." & _
|
|
vbNewLine & "This cannot be performed in Windows PE." & _
|
|
vbNewLine & "If booting from a USB Flash Disk, please remove all drives before restarting." & _
|
|
vbNewLine & "Otherwise, ensure the hard disk is selected first in the BIOS boot order."
|
|
oEnvironment.Item("SMSTSRebootRequested") = "true"
|
|
oEnvironment.Item("SMSTSRetryRequested") = "true"
|
|
Main = SUCCESS
|
|
Exit Function
|
|
End if
|
|
|
|
|
|
' Prepare the Deployment Root Directory
|
|
|
|
If oEnvironment.Item("ResourceRoot") = "" then
|
|
oEnvironment.Item("ResourceRoot") = oFSO.GetParentFolderName(oUtility.ScriptDir)
|
|
End if
|
|
|
|
|
|
' Load the XML File
|
|
set oXMLApps = new ConfigFile
|
|
oXMLApps.sFileType = "Applications"
|
|
set dAvaiableApps = oXMLApps.FindAllItems
|
|
|
|
' Find our stub program
|
|
|
|
iRetVal = oUtility.FindFile("bddrun.exe", sBDDRun)
|
|
TestAndLog iRetVal, "Find File: BDDRun.exe"
|
|
|
|
|
|
if isempty(aLanguages) then
|
|
aLanguages = array( cstr(GetLocale), right("0000" & hex(GetLocale),4), "0x" & right("0000" & hex(GetLocale),4), _
|
|
cstr(GetLocale() and &h03ff), right("0000" & hex(GetLocale() and &h03ff),4), "0x" & right("0000" & hex(GetLocale() and &h03ff),4) )
|
|
end if
|
|
oLogging.CreateEntry "Language/Locale Identified (in order of precedence): " & join(aLanguages,","), LogTypeInfo
|
|
|
|
|
|
' Load the list of already-installed applications (probably doesn't exist yet)
|
|
|
|
Set oInstalledApplications = oEnvironment.ListItem("InstalledApplications")
|
|
|
|
Set oDependentApplications = oEnvironment.ListItem("DependentApplications")
|
|
|
|
|
|
' Check that an individual application guid wasn't passed via the commmand line.
|
|
' This is a mandatory single install intiate by a Task Sequence action.
|
|
|
|
If oEnvironment.Item("ApplicationSuccessCodes") <> "" then
|
|
g_ApplicationSuccessCodes = " " & oEnvironment.Item("ApplicationSuccessCodes") & " "
|
|
End if
|
|
|
|
If oEnvironment.Item("ApplicationGUID") <> "" Then
|
|
oLogging.CreateEntry "Mandatory Single Application install indicated. Guid: " & oEnvironment.Item("ApplicationGUID"), LogTypeInfo
|
|
|
|
iRetVal = InstallApplication(oEnvironment.Item("ApplicationGUID"), 0)
|
|
|
|
If iRetVal = 3010 then ' Reboot requested
|
|
|
|
' Set properties to indicate a reboot is needed and this script should be re-executed
|
|
|
|
oEnvironment.Item("SMSTSRebootRequested") = "true"
|
|
oEnvironment.Item("SMSTSRetryRequested") = "true"
|
|
|
|
oLogging.CreateEntry "Exiting to initiate a reboot with retry (to pick up where we left off)", LogTypeInfo
|
|
Main = Success
|
|
|
|
Exit Function
|
|
|
|
End if
|
|
|
|
Main = 0 ' Always succeed. The errors and warnings from above will be reported so the process can continue.
|
|
Exit Function
|
|
End If
|
|
|
|
' Load the list of Applications stored in the enviroment. First we being by processing the MandatoryApplication
|
|
' and then follow with the normal user selected Applications.
|
|
|
|
For Each sApplicationType in Array("MandatoryApplications", "Applications")
|
|
oLogging.CreateEntry "Processing Application Type: " & sApplicationType, LogTypeInfo
|
|
|
|
Set oApplications = oEnvironment.ListItem(sApplicationType)
|
|
|
|
If oApplications.Count = 0 then
|
|
oLogging.CreateEntry "Application List is empty, exiting ZTIApplications.wsf", LogTypeInfo
|
|
Main = Success
|
|
Else
|
|
|
|
' Process the list
|
|
|
|
oLogging.CreateEntry "Ready to install applications: " , LogTypeInfo
|
|
iApplicationCount = 0
|
|
For each sGuid in oApplications
|
|
|
|
iApplicationCount = iApplicationCount + 1
|
|
iPercent = CLng(iApplicationCount / oApplications.Count * 100)
|
|
iRetVal = InstallApplication(sGuid, iPercent)
|
|
|
|
If iRetVal = 3010 then ' Reboot requested
|
|
|
|
' Set properties to indicate a reboot is needed and this script should be re-executed
|
|
|
|
oEnvironment.Item("SMSTSRebootRequested") = "true"
|
|
oEnvironment.Item("SMSTSRetryRequested") = "true"
|
|
|
|
oLogging.CreateEntry "Exiting to initiate a reboot with retry (to pick up where we left off)", LogTypeInfo
|
|
iRetVal = Success
|
|
|
|
Exit Function
|
|
|
|
End if
|
|
|
|
Next
|
|
|
|
End if
|
|
|
|
Next
|
|
|
|
|
|
'Cleanup and Exit
|
|
|
|
Main = iRetVal
|
|
|
|
End Function
|
|
|
|
|
|
|
|
|
|
Function InstallApplication(sGuid, iPercent)
|
|
|
|
Dim oNode
|
|
Dim oDependentNode
|
|
Dim sDependentGuid
|
|
Dim sDir
|
|
Dim sCmd
|
|
Dim bValidProcessorType
|
|
Dim iResult
|
|
Dim sError
|
|
Dim sKey
|
|
Dim sValueName
|
|
Dim sValue
|
|
Dim oSupportedPlatformNode
|
|
Dim sSupportedPlatform
|
|
Dim bSupportedPlaformRequired
|
|
Dim bSupportedPlatformFound
|
|
Dim bModern
|
|
|
|
|
|
InstallApplication = Success
|
|
bSupportedPlaformRequired = False
|
|
|
|
|
|
' Check if application has already been installed
|
|
|
|
If oInstalledApplications.Exists(sGuid) then
|
|
oLogging.CreateEntry "Application " & sGuid & " has already been installed, will not install again.", LogTypeInfo
|
|
Exit Function
|
|
End if
|
|
|
|
|
|
' Find the entry in the XML document
|
|
|
|
If not dAvaiableApps.Exists(sGuid) then
|
|
oLogging.CreateEntry "ERROR, application GUID " & sGuid & " not found in application list, unable to execute", LogTypeError
|
|
Exit Function
|
|
Else
|
|
set oNode = dAvaiableApps.Item(sGuid)
|
|
End if
|
|
|
|
|
|
' Log details of the application
|
|
|
|
oLogging.CreateEntry "################", LogTypeInfo
|
|
oLogging.CreateEntry "Entry: " & sGuid, LogTypeInfo
|
|
oLogging.CreateEntry "Name: " & oUtility.SelectSingleNodeString(oNode,"Name"), LogTypeInfo
|
|
oLogging.CreateEntry "################", LogTypeInfo
|
|
|
|
|
|
|
|
' Use supported platform options to confirm application is applicable.
|
|
|
|
For each oSupportedPlatformNode in oNode.SelectNodes("SupportedPlatform")
|
|
sSupportedPlatform = oSupportedPlatformNode.Text
|
|
bSupportedPlaformRequired = True
|
|
bSupportedPlatformFound = False
|
|
|
|
oLogging.CreateEntry "################", LogTypeInfo
|
|
oLogging.CreateEntry vbTab & "Supported Platform entry: " & sSupportedPlatform, LogTypeInfo
|
|
oLogging.CreateEntry "################", LogTypeInfo
|
|
|
|
|
|
bSupportedPlatformFound = oUtility.IsSupportedPlatform(sSupportedPlatform)
|
|
|
|
If bSupportedPlatformFound = true Then
|
|
oLogging.CreateEntry vbTab & "Supported Platform Matched: " & sSupportedPlatform, LogTypeInfo
|
|
Exit For
|
|
End If
|
|
Next
|
|
|
|
If bSupportedPlaformRequired = True Then
|
|
If bSupportedPlatformFound <> True Then
|
|
oLogging.CreateEntry "Supported Plaform requirements not met, skipping this application", LogTypeInfo
|
|
Exit Function
|
|
End If
|
|
End If
|
|
|
|
|
|
' Make sure this should run for this Language Locale. If not, abort.
|
|
|
|
bValidProcessorType = TRUE
|
|
If not oNode.selectSingleNode("Language") is nothing then
|
|
sValueName = ucase(oUtility.SelectSingleNodeString(oNode,"Language"))
|
|
If sValueName <> "" then
|
|
|
|
' Removing logic because there is nothing in the documentation that indicates what valid values are nor are there
|
|
' any validations performed. Users have typically used this as more of a comment field, so this would be a breaking
|
|
' change.
|
|
' bValidProcessorType = FALSE
|
|
|
|
for each sValue in aLanguages
|
|
if ucase(sValue) = sValueName then
|
|
bValidProcessorType = TRUE
|
|
exit for
|
|
end if
|
|
next
|
|
End if
|
|
End if
|
|
|
|
If not bValidProcessorType then
|
|
oLogging.CreateEntry vbTab & vbTab & "Incorrect Language Type: " & oUtility.SelectSingleNodeString(oNode,"Language") & " = " & GetLocale(), LogTypeInfo
|
|
Exit Function
|
|
End if
|
|
|
|
|
|
' See if the uninstall registry key already exists, indicating that the app is installed
|
|
|
|
If not oNode.selectSingleNode("UninstallKey") is Nothing then
|
|
sKey = oUtility.SelectSingleNodeString(oNode,"UninstallKey")
|
|
If oUtility.SelectSingleNodeString(oNode,"UninstallKey") <> "" then
|
|
|
|
' Check if the registry key exists
|
|
|
|
For each sValueName in Array("DisplayName", "UninstallString", "QuietUninstallString")
|
|
|
|
sValue = empty
|
|
on error resume next
|
|
sValue = oShell.RegRead("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" & sKey & "\" & sValueName)
|
|
on error goto 0
|
|
|
|
If IsEmpty(sValue) then
|
|
On error resume next
|
|
sValue = oShell.RegRead("HKLM\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" & sKey & "\" & sValueName)
|
|
On error goto 0
|
|
End if
|
|
|
|
If not isempty(sValue) then
|
|
oLogging.CreateEntry "Uninstall registry key found, application is already installed.", LogTypeInfo
|
|
Exit Function
|
|
End if
|
|
|
|
Next
|
|
|
|
End if
|
|
End if
|
|
|
|
|
|
' Process any dependent programs
|
|
|
|
|
|
For each oDependentNode in oNode.SelectNodes("Dependency")
|
|
|
|
sDependentGuid = oDependentNode.Text
|
|
If oDependentApplications.Exists(sDependentGuid) then
|
|
oLogging.CreateEntry "Dependent Application has already been referenced, skipping application", LogTypeInfo
|
|
Else
|
|
oDependentApplications.Add sDependentGuid, ""
|
|
oLogging.CreateEntry "################", LogTypeInfo
|
|
oLogging.CreateEntry vbTab & "Dependent entry: " & sDependentGuid, LogTypeInfo
|
|
oLogging.CreateEntry "################", LogTypeInfo
|
|
|
|
iResult = InstallApplication(sDependentGuid, iPercent)
|
|
|
|
If iResult = 3010 then ' Reboot requested
|
|
|
|
oLogging.CreateEntry "Dependent application requested a reboot", LogTypeInfo
|
|
|
|
InstallApplication = 3010
|
|
Exit Function
|
|
|
|
End if
|
|
End If
|
|
Next
|
|
|
|
' Check if application has already been installed. Could have been installed by a dependent application
|
|
|
|
If oInstalledApplications.Exists(sGuid) then
|
|
oLogging.CreateEntry "Application " & sGuid & " has already been installed, will not install again.", LogTypeInfo
|
|
Exit Function
|
|
End if
|
|
|
|
|
|
|
|
' Install the specified application
|
|
|
|
bModern = False
|
|
sCmd = ""
|
|
If oNode.selectSingleNode("CommandLine") is Nothing then
|
|
' Do nothing
|
|
ElseIf oUtility.SelectSingleNodeString(oNode,"CommandLine") <> "" then
|
|
sCmd = oUtility.SelectSingleNodeString(oNode,"CommandLine")
|
|
If UCase(Right(sCmd,5)) = ".APPX" or UCase(Right(sCmd,11)) = ".APPXBUNDLE" then
|
|
bModern = True
|
|
End if
|
|
End if
|
|
|
|
|
|
' Change to the current directory
|
|
|
|
If not oNode.selectSingleNode("WorkingDirectory") is nothing then
|
|
|
|
sDir = oUtility.SelectSingleNodeString(oNode,"WorkingDirectory")
|
|
If Trim(sDir) <> "" and Trim(sDir) <> "." then
|
|
|
|
If Left(sDir, 2) = ".\" then
|
|
If (Instr(1, sCmd, ".CMD", 1) > 0 or Instr(1, sCmd, ".BAT", 1) > 0) and oEnvironment.Item("ResourceDrive") <> "" then
|
|
If oEnvironment.Item("DeploymentMethod") = "MEDIA" then
|
|
sDir = oEnvironment.Item("ResourceRoot") & Mid(sDir, 2)
|
|
Else
|
|
sDir = oEnvironment.Item("ResourceDrive") & Mid(sDir, 2)
|
|
End If
|
|
Else
|
|
sDir = oEnvironment.Item("ResourceRoot") & Mid(sDir, 2)
|
|
End if
|
|
End if
|
|
|
|
sDir = oEnvironment.Substitute(sDir)
|
|
|
|
oUtility.ValidateConnection sDir
|
|
|
|
oLogging.CreateEntry vbTab & vbTab & "Change directory: " & sDir, LogTypeInfo
|
|
On Error Resume Next
|
|
|
|
oShell.CurrentDirectory = sDir
|
|
|
|
If Err then
|
|
oLogging.CreateEntry "WARNING - unable to set working directory: " & Err.Description & " (" & Err.Number & ")", LogTypeWarning
|
|
End if
|
|
On Error Goto 0
|
|
|
|
End if
|
|
End if
|
|
|
|
|
|
' Build the command line
|
|
|
|
If bModern then
|
|
sCmd = BuildAppxCommand(sDir, oNode)
|
|
ElseIf sCmd <> "" then
|
|
sCmd = sBDDRun & " " & oEnvironment.Substitute(sCmd)
|
|
End if
|
|
|
|
|
|
' Launch Command
|
|
|
|
If sCmd = "" then
|
|
oLogging.CreateEntry vbTab & vbTab & "Run Command is missing (application bundle). ", LogTypeInfo
|
|
Else
|
|
oLogging.ReportProgress "Installing " & oUtility.SelectSingleNodeString(oNode,"Name"), iPercent
|
|
oLogging.CreateEntry vbTab & vbTab & "Run Command: " & sCmd, LogTypeInfo
|
|
oLogging.CreateEvent 41031, LogTypeInfo, "ZTI installing application ", Array(sGuid, oUtility.SelectSingleNodeString(oNode,"Name"))
|
|
|
|
On Error Resume Next
|
|
|
|
|
|
If bModern then
|
|
iResult = oShell.Run(sCmd, 0, true)
|
|
Else
|
|
iResult = oUtility.RunWithHeartbeat(sCmd)
|
|
End if
|
|
|
|
If Err then
|
|
iResult = Err.number
|
|
sError = Err.Description
|
|
oLogging.CreateEvent 41032, LogTypeError, "Error installing application " & oUtility.SelectSingleNodeString(oNode,"Name") & ": " & sError, Array(sGuid, oUtility.SelectSingleNodeString(oNode,"Name"), sError)
|
|
ElseIf instr(1,g_ApplicationSuccessCodes," " & iResult & " ",vbTextCompare ) <> 0 then
|
|
oLogging.CreateEvent 41033, LogTypeInfo, "Application " & oUtility.SelectSingleNodeString(oNode,"Name") & " installed successfully", Array(sGuid, oUtility.SelectSingleNodeString(oNode,"Name"), iResult)
|
|
If iResult <> 3010 then
|
|
' Normalize the results to either 3010 or 0 if successfull.
|
|
iResult = 0
|
|
End if
|
|
Else
|
|
oLogging.CreateEvent 41034, LogTypeError, "Application " & oUtility.SelectSingleNodeString(oNode,"Name") & " returned an unexpected return code: " & iResult, Array(sGuid, oUtility.SelectSingleNodeString(oNode,"Name"), iResult)
|
|
End if
|
|
|
|
On Error Goto 0
|
|
|
|
End if
|
|
|
|
' Update the list of installed applications
|
|
|
|
oInstalledApplications.Add sGuid, ""
|
|
Set oEnvironment.ListItem("InstalledApplications") = oInstalledApplications
|
|
|
|
'See if a reboot is needed
|
|
|
|
If not oNode.selectSingleNode("Reboot") is Nothing then
|
|
|
|
If UCase(oUtility.SelectSingleNodeString(oNode,"Reboot")) = "TRUE" then
|
|
|
|
oLogging.CreateEntry "Application " & oUtility.SelectSingleNodeString(oNode,"Name") & " needs a reboot, initiating.", LogTypeInfo
|
|
InstallApplication = 3010 ' Reboot indicator
|
|
Exit Function
|
|
|
|
End if
|
|
|
|
End if
|
|
|
|
|
|
|
|
End Function
|
|
|
|
|
|
Function BuildAppxCommand(sDir, oNode)
|
|
Dim sCmd
|
|
Dim sWorkingDir
|
|
Dim sDependencyArch
|
|
Dim oFile
|
|
Dim bFoundLicense
|
|
Dim iRC
|
|
Dim sCertCmd
|
|
|
|
|
|
' Make sure policy is set
|
|
|
|
oShell.RegWrite "HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Appx\AllowAllTrustedApps", 1, "REG_DWORD"
|
|
|
|
|
|
' Build the base command line
|
|
|
|
sCmd = "DISM.EXE /online /Add-ProvisionedAppxPackage /PackagePath:""" & oUtility.SelectSingleNodeString(oNode,"CommandLine") & """ "
|
|
|
|
|
|
' Determine where to check
|
|
|
|
If sDir = "" then
|
|
sWorkingDir = oFSO.GetParentFolderName(oUtility.SelectSingleNodeString(oNode,"CommandLine"))
|
|
Else
|
|
sWorkingDir = sDir
|
|
End if
|
|
|
|
|
|
' Add dependencies
|
|
|
|
If oFSO.FolderExists(sWorkingDir & "\Dependencies") then
|
|
For each sDependencyArch in Array("x86", "x64", ".")
|
|
For each oFile in oFSO.GetFolder(sWorkingDir & "\Dependencies\" & sDependencyArch).Files
|
|
If UCase(Right(oFile.Name,5)) = ".APPX" then
|
|
sCmd = sCmd & " /DependencyPackagePath:""" & oFile.Path & """"
|
|
End if
|
|
Next
|
|
Next
|
|
End if
|
|
|
|
|
|
' Add license
|
|
|
|
bFoundLicense = False
|
|
If oFSO.FolderExists(sWorkingDir) then
|
|
For each oFile in oFSO.GetFolder(sWorkingDir).Files
|
|
If UCase(Right(oFile.Name,4)) = ".XML" then
|
|
sCmd = sCmd & " /LicensePath:""" & oFile.Path & """"
|
|
bFoundLicense = True
|
|
End if
|
|
Next
|
|
End if
|
|
If not bFoundLicense then
|
|
sCmd = sCmd & " /SkipLicense"
|
|
End if
|
|
|
|
|
|
' Return the command line
|
|
|
|
BuildAppxCommand = sCmd
|
|
|
|
|
|
' Install any certs that are found in the working directory
|
|
|
|
For each oFile in oFSO.GetFolder(sWorkingDir).Files
|
|
If UCase(Right(oFile.Name,4)) = ".CER" then
|
|
|
|
sCertCmd = "certutil.exe -addstore root """ & oFile.Path & """"
|
|
oLogging.CreateEntry "Importing certificate: " & sCertCmd, LogTypeInfo
|
|
iRC = oShell.Run(sCertCmd, 0, true)
|
|
oLogging.CreateEntry "Return code from CERTUTIL = " & iRC, LogTypeInfo
|
|
|
|
End if
|
|
Next
|
|
|
|
End function
|
|
|
|
End class
|
|
|
|
</script>
|
|
</job>
|
|
|