Hello all,
PSADT is new to me but I’m loving the power of it already. I’m getting my hands on it after being used to deploying all my packages with a VBS wrapper script using my own functions. The use of Powershell is appealing, yet hard to get used to coming from VBS exclusively. I’ve read the documentation and made a first script to deploy Firefox, see code below.
So far so good, but I’m having issues with eror handling. In my previous scripts I started with a main exit code (which seems to be present in deploy-application.psi as well) and I raise this every time an essential action /step of the installation process fails. However, when something goes wrong, I usually let my scripts continue to at least execute the rest of the actions. In PSADT however, when something goes wrong the script stops and doesn’t execute further functions.
For example, to install firefox I check installed versions first, then I use a welcome prompt when installation should continue. When all Firefox windows are closed, I start executing the setup, copy some extensions and then prompt the user when the script is done.
BUT:
- When the function Execute-Process encounters an error (like ‘Path not found’) it throws the error and the script stops executing.
- Rather I would want it to continue with the rest of the script, copy the files and foremost give the user the message that the installation failed!
I haven’t found a way to do this so far, but is there a way to achieve this?
With the function Copy-Item I could catch errors like this and raise the main exit code just like I used to. I had to specify -ContinueOnError $false for it to work, bu this doesn’t work with Execute-Process.
I guess the question comes down to whether I’m seeing it all wrong and I’m not using a correct way to handle errors, or am I missing some functionality that the toolkit provides and I’m simple not aware of? Fact is that I prefer to have total control of what happens in my script, so I want to decide when the script should continue and when not. I can have the script exit with a simple line of commands myself, so why would some functions bail out and others continue?
Additionally I would like to suggest to let the Show-InstallationProgress scale to the custom message text that is provided. When I use this block, it gets cut off and looks ugly:
Show-InstallationProgress -StatusMessage "Installation of $appName $appVersion in progress. Please wait…
nThis window will close automatically when the installation is finished.n
n Do not attempt to start new instances of $appName during this process.n
nThank you,nICT Client Services Team"
EXAMPLE SCRIPT:
<code>[CmdletBinding()] Param ( [Parameter(Mandatory=$false)] [ValidateSet('Install','Uninstall')] [string]$DeploymentType = 'Install', [Parameter(Mandatory=$false)] [ValidateSet('Interactive','Silent','NonInteractive')] [string]$DeployMode = 'Interactive', [Parameter(Mandatory=$false)] [switch]$AllowRebootPassThru = $false, [Parameter(Mandatory=$false)] [switch]$TerminalServerMode = $false, [Parameter(Mandatory=$false)] [switch]$DisableLogging = $false ) Try { ## Set the script execution policy for this process Try { Set-ExecutionPolicy -ExecutionPolicy 'ByPass' -Scope 'Process' -Force -ErrorAction 'Stop' } Catch {} ##*=============================================== ##* VARIABLE DECLARATION ##*=============================================== ## Variables: Application [string]$appVendor = 'Mozilla' [string]$appName = 'Firefox' [string]$appVersion = '50.1.0' [string]$appArch = 'x86' [string]$appLang = 'EN' [string]$appRevision = '01' [string]$appScriptVersion = '1.0.0' [string]$appScriptDate = '12/23/2016' [string]$appScriptAuthor = 'Jonathan De Nil' ##*=============================================== ## Variables: Install Titles (Only set here to override defaults set by the toolkit) [string]$installName = '' [string]$installTitle = '' ##* Do not modify section below #region DoNotModify ## Variables: Exit Code [int32]$mainExitCode = 0 ## Variables: Script [string]$deployAppScriptFriendlyName = 'Deploy Application' [version]$deployAppScriptVersion = [version]'3.6.8' [string]$deployAppScriptDate = '02/06/2016' [hashtable]$deployAppScriptParameters = $psBoundParameters ## Variables: Environment If (Test-Path -LiteralPath 'variable:HostInvocation') { $InvocationInfo = $HostInvocation } Else { $InvocationInfo = $MyInvocation } [string]$scriptDirectory = Split-Path -Path $InvocationInfo.MyCommand.Definition -Parent ## Dot source the required App Deploy Toolkit Functions Try { [string]$moduleAppDeployToolkitMain = "$scriptDirectory\AppDeployToolkit\AppDeployToolkitMain.ps1" If (-not (Test-Path -LiteralPath $moduleAppDeployToolkitMain -PathType 'Leaf')) { Throw "Module does not exist at the specified location [$moduleAppDeployToolkitMain]." } If ($DisableLogging) { . $moduleAppDeployToolkitMain -DisableLogging } Else { . $moduleAppDeployToolkitMain } } Catch { If ($mainExitCode -eq 0){ [int32]$mainExitCode = 60008 } Write-Error -Message "Module [$moduleAppDeployToolkitMain] failed to load: <code>n$($_.Exception.Message)</code>n </code>
n$($_.InvocationInfo.PositionMessage)" -ErrorAction ‘Continue’
## Exit the script, returning the exit code to SCCM
If (Test-Path -LiteralPath ‘variable:HostInvocation’) { $script:ExitCode = $mainExitCode; Exit } Else { Exit $mainExitCode }
}
#endregion
##* Do not modify section above
##*===============================================
##* END VARIABLE DECLARATION
##*===============================================
If ($deploymentType -ine 'Uninstall') {
##*===============================================
##* PRE-INSTALLATION
##*===============================================
[string]$installPhase = 'Pre-Installation'
## Detection check
[string]$ProgramPath = "$envProgramFilesX86\Example\Example.exe"
[boolean]$VersionOK = $false
If (Test-Path -Path $ProgramPath) {
[string]$ProgramVersion = Get-FileVersion -File $ProgramPath
Write-Log -Message "--> ProgramPath = $ProgramPath"
Write-Log -Message "--> ProgramVersion = $ProgramVersion"
If ([System.Version]$ProgramVersion -ge [System.Version]$appVersion) {
$VersionOK = $true
Write-Log -Message "--> Version OK."
}
Else {
Write-Log -Message "--> Version not OK."
}
}
If (!($VersionOK)) {
## Show Welcome Message
Show-InstallationWelcome -CloseApps "firefox=Mozilla Firefox" -ForceCloseAppsCountdown 1800 -Minimizewindows $false -BlockExecution -PersistPrompt
## Show Progress Message (with the default message)
Show-InstallationProgress
##*===============================================
##* INSTALLATION
##*===============================================
[string]$installPhase = 'Installation'
## Setup
Try { Execute-Process -Path "$dirFiles\Install\Firefox_Setup.exe" -Parameters "-ms /ini=<code>"$dirSupportFiles\Config\Config.ini</code>"" -ContinueOnError $false } Catch { $mainExitCode = $mainExitCode + 1 }
##*===============================================
##* POST-INSTALLATION
##*===============================================
[string]$installPhase = 'Post-Installation'
## Copy config files
Try { Copy-File -Path "$dirSupportFiles\Config\policies.js" -Destination "$envProgramFilesX86\Mozilla Firefox\defaults\pref\policies.js" -ContinueOnError $false } Catch { $mainExitCode = $mainExitCode + 1 }
Try { Copy-File -Path "$dirSupportFiles\Config\mozilla.cfg" -Destination "$envProgramFilesX86\Mozilla Firefox\mozilla.cfg" -ContinueOnError $false } Catch { $mainExitCode = $mainExitCode + 1 }
Try { Copy-File -Path "$dirSupportFiles\Extensions\*.*" -Destination "$envProgramFilesX86\Mozilla Firefox\browser\extensions" -ContinueOnError $false } Catch { $mainExitCode = $mainExitCode + 1 }
## Delete shortcuts
Remove-File -Path "$envCommonDesktop\*Firefox*.lnk" -ContinueOnError $true
## Display a message at the end of the install
If (-not $useDefaultMsi) {
If (!($mainExitCode -eq 0)) {
Show-InstallationPrompt -Message "Installation failed with exit code [$mainExitCode].`nPlease contact the Service Desk." -ButtonRightText "OK" -Icon "Error" -NoWait -Timeout 60
}
Else {
Show-InstallationPrompt -Message "Installation complete." -ButtonRightText "OK" -Icon "Information" -NoWait -Timeout 60
}
}
}
Else {
Write-Log -Message "--> $appName $appVersion or higher is already installed."
Write-Log -Message "--> Installation aborted."
}
}
ElseIf ($deploymentType -ieq 'Uninstall') {
##*===============================================
##* PRE-UNINSTALLATION
##*===============================================
[string]$installPhase = 'Pre-Uninstallation'
## Show Welcome Message, close Internet Explorer with a 60 second countdown before automatically closing
Show-InstallationWelcome -CloseApps "firefox=Mozilla Firefox" -ForceCloseAppsCountdown 1800 -Minimizewindows $false -BlockExecution -PersistPrompt
## Show Progress Message (with the default message)
Show-InstallationProgress
## <Perform Pre-Uninstallation tasks here>
Show-InstallationPrompt -Message "Uninstall placeholder." -ButtonRightText 'OK' -Icon "Information" -NoWait -Timeout 60
##*===============================================
##* UNINSTALLATION
##*===============================================
[string]$installPhase = 'Uninstallation'
## Handle Zero-Config MSI Uninstallations
If ($useDefaultMsi) {
[hashtable]$ExecuteDefaultMSISplat = @{ Action = 'Uninstall'; Path = $defaultMsiFile }; If ($defaultMstFile) { $ExecuteDefaultMSISplat.Add('Transform', $defaultMstFile) }
Execute-MSI @ExecuteDefaultMSISplat
}
## <Perform Uninstallation tasks here>
##*===============================================
##* POST-UNINSTALLATION
##*===============================================
[string]$installPhase = 'Post-Uninstallation'
## <Perform Post-Uninstallation tasks here>
}
##*===============================================
##* END SCRIPT BODY
##*===============================================
## Call the Exit-Script function to perform final cleanup operations
Exit-Script -ExitCode $mainExitCode
}
Catch {
[int32]$mainExitCode = 60001
[string]$mainErrorMessage = “$(Resolve-Error)”
Write-Log -Message $mainErrorMessage -Severity 3 -Source $deployAppScriptFriendlyName
Show-DialogBox -Text $mainErrorMessage -Icon ‘Stop’
Exit-Script -ExitCode $mainExitCode
}`