397 lines
19 KiB
PowerShell
397 lines
19 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
This script performs the installation or uninstallation of an application(s).
|
|
# LICENSE #
|
|
PowerShell App Deployment Toolkit - Provides a set of functions to perform common application deployment tasks on Windows.
|
|
Copyright (C) 2017 - Sean Lillis, Dan Cunningham, Muhammad Mashwani, Aman Motazedian.
|
|
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/>.
|
|
.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 functions required to install or uninstall an application.
|
|
.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 Destkop 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"
|
|
.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
|
|
http://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 = 'Brady'
|
|
[string]$appName = 'All Driver Packages'
|
|
[string]$appVersion = ''
|
|
[string]$appArch = 'x86'
|
|
[string]$appLang = 'EN'
|
|
[string]$appRevision = '01'
|
|
[string]$appScriptVersion = '1.0.0'
|
|
[string]$appScriptDate = '05/01/2025'
|
|
[string]$appScriptAuthor = 'John Palmer'
|
|
##*===============================================
|
|
## 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.8.3'
|
|
[string]$deployAppScriptDate = '30/09/2020'
|
|
[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>
|
|
|
|
#$ProcessActive = Get-Process NanoDrop2000 -ErrorAction SilentlyContinue
|
|
|
|
#if($ProcessActive -eq $null)
|
|
#{
|
|
#Write-Log "NanoDrop 2000 is not currently running, continuing with the installation."
|
|
#}
|
|
#else
|
|
#{
|
|
#Write-Log "NanoDrop 2000 is currently running, prompting the user to close the application before continuing."
|
|
#Show-InstallationWelcome -CloseApps 'NanoDrop2000' -AllowDefer -DeferTimes 3 -CheckDiskSpace -PersistPrompt
|
|
#}
|
|
|
|
#Import-Certificate -FilePath "$dirSupportFiles\<Certificate>.cer" -CertStoreLocation Cert:\LocalMachine\TrustedPublisher
|
|
|
|
|
|
#Import-Certificate -FilePath "$dirSupportFiles\brady_2019.cer" -CertStoreLocation Cert:\LocalMachine\TrustedPublisher
|
|
Write-Log "Import the Brady Trusted Publisher Certificate if it doesn't already exist on the system."
|
|
$Brady = Test-Path "Get-ChildItem Cert:\LocalMachine\TrustedPublisher\BC20359746139AA35E229F19925696D7321B4A8E"
|
|
|
|
If ($Brady -eq $False)
|
|
{
|
|
Write-Log "The Trusted Publisher certificate does not currently exist on this machine, importing it now."
|
|
Import-Certificate -FilePath "$dirFiles\Brady_Trusted_Certificate.cer" -CertStoreLocation Cert:\LocalMachine\TrustedPublisher
|
|
}
|
|
|
|
Else
|
|
{
|
|
Write-Output "The Trusted Publisher Certificate already exists for this printer."
|
|
|
|
}
|
|
|
|
##*===============================================
|
|
##* 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>
|
|
|
|
#Execute-Process -Path 'i3300.exe' -Parameters '/S'
|
|
|
|
#Execute-Process -Path "$dirSupportFiles\Setup.exe" -Parameters '/S'
|
|
|
|
#Pnputil -i -a %InstallDriver%
|
|
|
|
Write-Log "Registering the printer drivers..."
|
|
Write-Log "Registering the i5300-300 drivers..."
|
|
Execute-Process -Path 'PnPutil.exe' -Parameters "-a `"$dirFiles\i5300-300\i5300300.INF`""
|
|
Write-Log "Registering the i5300-600 drivers..."
|
|
Execute-Process -Path 'PnPutil.exe' -Parameters "-a `"$dirFiles\i5300-600\i5300600.INF`""
|
|
Write-Log "Registering the BBP33 drivers..."
|
|
Execute-Process -Path 'PnPutil.exe' -Parameters "-a `"$dirFiles\BBP33\BradyBBP33.INF`""
|
|
Write-Log "Registering the i5100-300 drivers..."
|
|
Execute-Process -Path 'PnPutil.exe' -Parameters "-a `"$dirFiles\i5100-300\i5100300.INF`""
|
|
Write-Log "Registering the i5100-600 drivers..."
|
|
Execute-Process -Path 'PnPutil.exe' -Parameters "-a `"$dirFiles\i5100-600\i5100600.INF`""
|
|
Write-Log "Registering the i3300 drivers..."
|
|
Execute-Process -Path 'PnPutil.exe' -Parameters "-a `"$dirFiles\i3300\Bradyi3300.INF`""
|
|
|
|
##*===============================================
|
|
##* POST-INSTALLATION
|
|
##*===============================================
|
|
[string]$installPhase = 'Post-Installation'
|
|
|
|
## <Perform Post-Installation tasks here>
|
|
Write-Log "Importing the drivers into the DriverStore."
|
|
|
|
# Helper function for adding printer drivers with logging
|
|
function Import-PrinterDriver {
|
|
param (
|
|
[string]$Name,
|
|
[string]$InfPath
|
|
)
|
|
|
|
# Write-Log "Importing the $Name printer."
|
|
try {
|
|
Add-PrinterDriver -Name $Name -InfPath $InfPath -ErrorAction Stop
|
|
# Write-Log "Successfully imported $Name printer driver."
|
|
} catch {
|
|
# Write-Log "Failed to import $Name printer driver: $_"
|
|
}
|
|
}
|
|
|
|
Import-PrinterDriver -Name "i5300-300" -InfPath "C:\Windows\System32\DriverStore\FileRepository\i5300300.inf_amd64_5e24f8c083c2c7a3\i5300300.INF"
|
|
Import-PrinterDriver -Name "i5300-600" -InfPath "C:\Windows\System32\DriverStore\FileRepository\i5300600.inf_amd64_46d1e66cd4d3ee74\i5300600.INF"
|
|
Import-PrinterDriver -Name "BBP33" -InfPath "C:\Windows\System32\DriverStore\FileRepository\bradybbp33.inf_amd64_85add8597af2864e\BradyBBP33.INF"
|
|
Import-PrinterDriver -Name "i5100-300" -InfPath "C:\Windows\System32\DriverStore\FileRepository\i5100300.inf_amd64_a6ddc00be80b8e7f\i5100300.INF"
|
|
Import-PrinterDriver -Name "i5100-600" -InfPath "C:\Windows\System32\DriverStore\FileRepository\i5100600.inf_amd64_0ee055ad24c7fe07\i5100600.INF"
|
|
Import-PrinterDriver -Name "i3300" -InfPath "C:\Windows\System32\DriverStore\FileRepository\bradyi3300.inf_amd64_9f91ea43338cfa8b\Bradyi3300.INF"
|
|
|
|
Write-Log "Importing the i3300 printer."
|
|
# Use the older driver as requested under SCTASK01079075 for Nicelabel compatibility
|
|
#Import-PrinterDriver -Name "i3300" -InfPath "C:\Windows\System32\DriverStore\FileRepository\bradyi3300.inf_amd64_fae4c0fd31aec947\Bradyi3300.INF"
|
|
Import-PrinterDriver -Name "i3300" -InfPath "C:\Windows\System32\DriverStore\FileRepository\bradyi3300.inf_amd64_9f91ea43338cfa8b\Bradyi3300.INF"
|
|
|
|
|
|
|
|
|
|
## Display a message at the end of the install
|
|
If (-not $useDefaultMsi) { #Show-InstallationPrompt -Message 'Brady i5100-600 Print Driver installation is compplete.' -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
|
|
|
|
## Show Progress Message (with the default message)
|
|
#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>
|
|
|
|
# Remove the Brady Drivers.
|
|
|
|
# Set log file path
|
|
$LogFile = "C:\Windows\Logs\Software\BradyLabelDriversRemoval.log"
|
|
|
|
# Ensure log directory exists
|
|
$logDir = Split-Path -Path $LogFile
|
|
if (-not (Test-Path $logDir)) {
|
|
New-Item -Path $logDir -ItemType Directory -Force | Out-Null
|
|
}
|
|
|
|
function Write-Log {
|
|
param (
|
|
[string]$Message,
|
|
[string]$Level = "INFO"
|
|
)
|
|
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
|
|
$logEntry = "[$timestamp] [$Level] $Message"
|
|
Write-Host $logEntry
|
|
Add-Content -Path $LogFile -Value $logEntry
|
|
}
|
|
|
|
function Remove-PrinterDriverSafe {
|
|
param (
|
|
[string]$Name
|
|
)
|
|
|
|
Write-Log "Attempting to remove printer driver: $Name"
|
|
|
|
try {
|
|
$existingDriver = Get-PrinterDriver -Name $Name -ErrorAction SilentlyContinue
|
|
if ($existingDriver) {
|
|
Remove-PrinterDriver -Name $Name -ErrorAction Stop
|
|
Write-Log "Successfully removed printer driver: $Name"
|
|
} else {
|
|
Write-Log "Printer driver $Name not found. Skipping removal."
|
|
}
|
|
} catch {
|
|
Write-Log "Failed to remove printer driver $Name $_" -Level "ERROR"
|
|
}
|
|
}
|
|
|
|
# Remove drivers
|
|
Remove-PrinterDriverSafe -Name "i5300-300"
|
|
Remove-PrinterDriverSafe -Name "i5300-600"
|
|
Remove-PrinterDriverSafe -Name "BBP33"
|
|
Remove-PrinterDriverSafe -Name "i5100-300"
|
|
Remove-PrinterDriverSafe -Name "i5100-600"
|
|
Remove-PrinterDriverSafe -Name "i3300"
|
|
|
|
# List of specific directories to remove from DriverStore
|
|
$foldersToRemove = @(
|
|
"i5300600.inf_amd64_46d1e66cd4d3ee74",
|
|
"i5100300.inf_amd64_a6ddc00be80b8e7f",
|
|
"i5100600.inf_amd64_0ee055ad24c7fe07",
|
|
"bradybbp33.inf_amd64_85add8597af2864e",
|
|
"bradyi3300.inf_amd64_9f91ea43338cfa8b"
|
|
)
|
|
|
|
$repoPath = "C:\Windows\System32\DriverStore\FileRepository"
|
|
|
|
foreach ($folderName in $foldersToRemove) {
|
|
$fullPath = Join-Path $repoPath $folderName
|
|
|
|
if (Test-Path $fullPath) {
|
|
try {
|
|
Write-Log "Deleting folder: $fullPath"
|
|
Remove-Item -Path $fullPath -Recurse -Force -ErrorAction Stop
|
|
Write-Log "Successfully deleted: $fullPath"
|
|
} catch {
|
|
$errMsg = $_.ToString()
|
|
Write-Log "Failed to delete $fullPath $errMsg" -Level "ERROR"
|
|
}
|
|
} else {
|
|
Write-Log "Folder not found: $fullPath" -Level "WARNING"
|
|
}
|
|
}
|
|
|
|
|
|
##*===============================================
|
|
##* POST-UNINSTALLATION
|
|
##*===============================================
|
|
[string]$installPhase = 'Post-Uninstallation'
|
|
|
|
## <Perform Post-Uninstallation tasks here>
|
|
|
|
|
|
}
|
|
ElseIf ($deploymentType -ieq 'Repair')
|
|
{
|
|
##*===============================================
|
|
##* PRE-REPAIR
|
|
##*===============================================
|
|
[string]$installPhase = 'Pre-Repair'
|
|
|
|
## 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
|
|
} |