2025-08-30 11:52:33 -04:00
<#
. SYNOPSIS
PSApppDeployToolkit - This script performs the installation or uninstallation of an application ( s ) .
. DESCRIPTION
- The script is provided as a template to perform an install or uninstall of an application ( s ) .
- The script either performs an " Install " deployment type or an " Uninstall " deployment type .
- The install deployment type is broken down into 3 main sections / phases : Pre-Install , Install , and Post-Install .
The script dot-sources the AppDeployToolkitMain . ps1 script which contains the logic and function s required to install or uninstall an application .
PSApppDeployToolkit is licensed under the GNU LGPLv3 License - ( C ) 2023 PSAppDeployToolkit Team ( Sean Lillis , Dan Cunningham and Muhammad Mashwani ) .
This program is free software : you can redistribute it and / or modify it under the terms of the GNU Lesser General Public License as published by the
Free Software Foundation , either version 3 of the License , or any later version . This program is distributed in the hope that it will be useful , but
WITHOUT ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
for more details . You should have received a copy of the GNU Lesser General Public License along with this program . If not , see < http : / / www . gnu . org / licenses / > .
. PARAMETER DeploymentType
The type of deployment to perform . Default is : Install .
. PARAMETER DeployMode
Specifies whether the installation should be run in Interactive , Silent , or NonInteractive mode . Default is : Interactive . Options : Interactive = Shows dialogs , Silent = No dialogs , NonInteractive = Very silent , i . e . no blocking apps . NonInteractive mode is automatically set if it is detected that the process is not user interactive .
. PARAMETER AllowRebootPassThru
Allows the 3010 return code ( requires restart ) to be passed back to the parent process ( e . g . SCCM ) if detected from an installation . If 3010 is passed back to SCCM , a reboot prompt will be triggered .
. PARAMETER TerminalServerMode
Changes to " user install mode " and back to " user execute mode " for installing / uninstalling applications for Remote Desktop Session Hosts / Citrix servers .
. PARAMETER DisableLogging
Disables logging to file for the script . Default is : $false .
. EXAMPLE
powershell . exe -Command " & { & '.\Deploy-Application.ps1' -DeployMode 'Silent'; Exit $LastExitCode } "
. EXAMPLE
powershell . exe -Command " & { & '.\Deploy-Application.ps1' -AllowRebootPassThru; Exit $LastExitCode } "
. EXAMPLE
powershell . exe -Command " & { & '.\Deploy-Application.ps1' -DeploymentType 'Uninstall'; Exit $LastExitCode } "
. EXAMPLE
Deploy-Application . exe -DeploymentType " Install " -DeployMode " Silent "
. INPUTS
None
You cannot pipe objects to this script .
. OUTPUTS
None
This script does not generate any output .
. NOTES
Toolkit Exit Code Ranges :
- 60000 - 68999 : Reserved for built-in exit codes in Deploy-Application . ps1 , Deploy-Application . exe , and AppDeployToolkitMain . ps1
- 69000 - 69999 : Recommended for user customized exit codes in Deploy-Application . ps1
- 70000 - 79999 : Recommended for user customized exit codes in AppDeployToolkitExtensions . ps1
. LINK
https : / / psappdeploytoolkit . com
#>
[ CmdletBinding ( ) ]
Param (
[ Parameter ( Mandatory = $false ) ]
[ ValidateSet ( 'Install' , 'Uninstall' , 'Repair' ) ]
[ 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 = 'FlowJo LLC'
[ String ] $appName = 'FlowJo'
[ String ] $appVersion = '10.10.0'
[ String ] $appArch = ''
[ String ] $appLang = 'EN'
[ String ] $appRevision = '01'
2025-08-30 11:54:12 -04:00
[ String ] $appScriptVersion = '1.1.0'
2025-08-30 11:52:33 -04:00
[ String ] $appScriptDate = '01/10/2024'
[ String ] $appScriptAuthor = 'John Palmer'
## NCH Custom Variables ##
# Define the running executable you want to check on Install/Uninstall and prompt the user to close if active.
$ProcessName = 'FlowJo_v10.10.0'
##*===============================================
## 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.9.3'
[ String ] $deployAppScriptDate = '02/05/2023'
[ 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: `n $( $_ . Exception . Message ) `n `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' -and $deploymentType -ine 'Repair' ) {
##*===============================================
##* PRE-INSTALLATION
##*===============================================
[ String ] $installPhase = 'Pre-Installation'
## Show Welcome Message, close Internet Explorer if required, allow up to 3 deferrals, verify there is enough disk space to complete the install, and persist the prompt
#Show-InstallationWelcome -CloseApps 'iexplore' -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
## Show Progress Message (with the default message)
#Show-InstallationProgress
## <Perform Pre-Installation tasks here>
## Remove the comments if you want to check for an active process and only prompt the close diaglog if the process is active. ##
@ (
" javaw " ,
" FlowJo_V10.10.0 "
" FlowJo_V10.9.0 "
" FlowJo_V10.8.1 " ,
" FlowJo_V10.8.0 " ,
" FlowJo_V10.7.1 " ,
" FlowJo_V10.7.0 " ,
" FlowJo_V10.6.2 " ,
" FlowJo_V10 " ,
" FlowJo7.6.0 " ,
" FlowJo7.6.5 "
" FlowJo "
) | Foreach-Object {
if ( Get-Process $_ -ErrorAction SilentlyContinue )
{
Write-Log " $_ is running "
Show-InstallationWelcome -CloseApps 'javaw=FlowJo,FlowJo_V10.10.0=FlowJo,FlowJo_V10.9.0=FlowJo,FlowJo_V10.8.1=FlowJo,FlowJo_V10.8.0=FlowJo,FlowJo_V10.7.1=FlowJo,FlowJo_V10.7.0=FlowJo,FlowJo_V10.6.2=FlowJo,FlowJo_V10=FlowJo,FlowJo7.6.5=FlowJo,FlowJo7.6.0=FlowJo' -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
}
else { Write-Log " $_ is not running " }
}
# Remove FlowJo 10.8.1 #
if ( Test-Path -LiteralPath 'C:\Program Files\FlowJo 10.8.1\Change FlowJo 10.8.1 Installation.exe' )
{
Execute-Process -Path " C:\Program Files\FlowJo 10.8.1\Change FlowJo 10.8.1 Installation.exe " -Parameters '-i' , " silent "
Remove-item -Path " C:\Program Files\FlowJo 10.8.1\jre " -Recurse
}
# Remove FlowJo 10.9.0 #
if ( Test-Path -LiteralPath 'C:\Program Files\FlowJo 10.9.0\Change FlowJo 10.9.0 Installation.exe' )
{
Execute-Process -Path " C:\Program Files\FlowJo 10.9.0\Change FlowJo 10.9.0 Installation.exe " -Parameters '-i' , " silent "
Remove-item -Path " C:\Program Files\FlowJo 10.9.0\jre " -Recurse
}
## Remove the previous versions of FlowJo and the old license dongle connectionss ##
if ( Test-Path -LiteralPath 'C:\Program Files\SEH Computertechnik GmbH\SEH UTN Manager' )
{
Write-Log " SEH UTN Manager exists and will be uninstalled. "
Execute-Process -Path " C:\Program Files\SEH Computertechnik GmbH\SEH UTN Manager\Uninstall.exe " -Parameters '/S'
}
if ( Test-Path -LiteralPath 'C:\Program Files\FlowJo License Server Connector' )
{
Write-Log " Removing the License Server Connection Scripts. "
Remove-Item -Path 'C:\Program Files\FlowJo License Server Connector' -Recurse
}
if ( Test-Path -LiteralPath 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\FlowJo License Server Connector.lnk' )
{
Write-Log " Removing the Start Menu Shortcut for the old License Connector Utility. "
Remove-Item -Path 'C:\ProgramData\Microsoft\Windows\Start Menu\Programs\FlowJo License Server Connector.lnk' -Recurse
}
## Remove the dongle based desktop connection shortcut. ##
if ( Test-Path -LiteralPath 'C:\Users\Public\Desktop\FlowJo License Server Connector.lnk' )
{
Write-Log " Removing the License Server Connection Shortcut "
Remove-Item -Path 'C:\Users\Public\Desktop\FlowJo License Server Connector.lnk' -Recurse
}
##*===============================================
##* INSTALLATION
##*===============================================
[ String ] $installPhase = 'Installation'
## Handle Zero-Config MSI Installations
If ( $useDefaultMsi ) {
[ Hashtable ] $ExecuteDefaultMSISplat = @ { Action = 'Install' ; Path = $defaultMsiFile } ; If ( $defaultMstFile ) {
$ExecuteDefaultMSISplat . Add ( 'Transform' , $defaultMstFile )
}
Execute-MSI @ExecuteDefaultMSISplat ; If ( $defaultMspFiles ) {
$defaultMspFiles | ForEach-Object { Execute-MSI -Action 'Patch' -Path $_ }
}
}
## <Perform Installation tasks here>
## Install FlowJo ##
If ( Get-InstalledApplication -Name " FlowJo 10.10.0 " )
{
Write-Log " FlowJo 10.10.0 is installed. "
}
Else
{
Write-Log " Installing FlowJo 10.10.0 "
Execute-Process -Path " $dirFiles \FlowJo-Win64-10.10.0.exe " -Parameters '-i' , " silent "
}
##*===============================================
##* POST-INSTALLATION
##*===============================================
[ String ] $installPhase = 'Post-Installation'
## <Perform Post-Installation tasks here>
# Define an array with the names of the desktop shortcuts to check and remove
$shortcutsToRemove = @ (
" FlowJo_v10.9.0.lnk "
" FlowJo_V10.9.0.lnk "
" FlowJo_V10.8.1.lnk " ,
" FlowJo_V10.8.0.lnk " ,
" FlowJo_V10.7.1.lnk " ,
" FlowJo_V10.7.0 " ,
" FlowJo_V10.lnk " ,
" FlowJo.lnk "
)
# Location of the Public Desktop
$publicDesktopPath = [ System.Environment ] :: GetFolderPath ( " CommonDesktopDirectory " )
# Go through each shortcut and check if it exists on the Public Desktop and then delete it
foreach ( $shortcut in $shortcutsToRemove ) {
$shortcutPath = Join-Path -Path $publicDesktopPath -ChildPath $shortcut
if ( Test-Path -Path $shortcutPath ) {
# Remove the shortcut from the Public Desktop
Remove-Item -Path $shortcutPath -Force
Write-Host " Removed shortcut `" $shortcut `" from the Public Desktop. "
}
else {
Write-Host " Shortcut `" $shortcut `" does not exist on the Public Desktop, copying over the current shortcut. "
Copy-Item -Path " $dirSupportFiles /FlowJo_v10.10.0.lnk " -Destination $publicDesktopPath -Recurse
}
}
## Display a message at the end of the install
If ( -not $useDefaultMsi ) {
#Show-InstallationPrompt -Message 'You can customize text to appear at the end of an install or remove it completely for unattended installations.' -ButtonRightText 'OK' -Icon Information -NoWait
}
}
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 'iexplore' -CloseAppsCountdown 60
$ProcessActive = Get-Process $ProcessName -ErrorAction SilentlyContinue
if ( $ProcessActive -eq $null )
{
Write-Log " $appName $appVersion is not currently running, continuing with the uninstall. "
}
else
{
Write-Log " $appName $appVersion is currently running, prompting the user to close the application before continuing. "
Show-InstallationWelcome -CloseApps $ProcessName -CloseAppsCountdown 60
}
## Show Progress Message (with the default message)
# If you want the Progress, just remove the # from the Show-InstallationProgress
#Show-InstallationProgress
## <Perform Pre-Uninstallation tasks here>
##*===============================================
##* 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>
Execute-Process -Path " C:\Program Files\FlowJo 10.10.0\Change-FlowJo-Installation.exe " -Parameters '-i silent'
##*===============================================
##* POST-UNINSTALLATION
##*===============================================
[ String ] $installPhase = 'Post-Uninstallation'
## <Perform Post-Uninstallation tasks here>
Write-Log " Removing the shortcut from the Public Desktop. "
$publicDesktopPath = [ System.Environment ] :: GetFolderPath ( " CommonDesktopDirectory " )
Remove-Item -Path " $publicDesktopPath \FlowJo_v10.10.0.lnk " -Recurse
}
ElseIf ( $deploymentType -ieq 'Repair' ) {
##*===============================================
##* PRE-REPAIR
##*===============================================
[ String ] $installPhase = 'Pre-Repair'
## Show Welcome Message, close Internet Explorer with a 60 second countdown before automatically closing
Show-InstallationWelcome -CloseApps 'iexplore' -CloseAppsCountdown 60
## Show Progress Message (with the default message)
Show-InstallationProgress
## <Perform Pre-Repair tasks here>
##*===============================================
##* REPAIR
##*===============================================
[ String ] $installPhase = 'Repair'
## Handle Zero-Config MSI Repairs
If ( $useDefaultMsi ) {
[ Hashtable ] $ExecuteDefaultMSISplat = @ { Action = 'Repair' ; Path = $defaultMsiFile ; } ; If ( $defaultMstFile ) {
$ExecuteDefaultMSISplat . Add ( 'Transform' , $defaultMstFile )
}
Execute-MSI @ExecuteDefaultMSISplat
}
## <Perform Repair tasks here>
##*===============================================
##* POST-REPAIR
##*===============================================
[ String ] $installPhase = 'Post-Repair'
## <Perform Post-Repair 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
}