Files

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>