Notepad++ 8.4.4

Scintilla

About

Notepad++ is a text and source code editor for use with Microsoft Windows.
This package includes the Compare plugin.

Main executable

C:\Program Files\Notepad++\notepad++.exe

deployInfo.xml

This file is referred to by the script. The variables in the script are called from this file. For each updated version, simply change the version number in the appropriate field, and the script will find the installer based on that. This file is stored in the SupportFiles directory.

<Metadata>
	<Publisher>DonHo</Publisher>
	<DisplayName>Notepad++</DisplayName>
	<DisplayVersion>8.4.4</DisplayVersion>
	<Architecture>x64</Architecture>
	<Revision>R1</Revision>
	<Date>11/08/2022</Date>
	<Author>njholmes.com</Author>
</Metadata>

Install

The installer is run with the following parameters:

npp.8.4.4.Installer.x64.exe /S

Suppress Updates

The C:\Program Files\Notepad++\updater folder should be renamed to C:\Program Files\Notepad++\updater_disabled.

Additional configuration

For this package, the Compare plugin was also required. This is downloaded as a zip file and extracted to the Install directory. See script for specifics.

Uninstall

The Uninstaller is usually located in the Install directory. The Uninstall script will extract the uninstaller from the registry to ensure the correct filename is called.

The uninstaller is run with the following parameters:

<InstallDir>\uninstall.exe /S

Logging

Can be found at C:\Windows\Logs\Software. This location is readable by all but not writeable for non-admin users.
Additionally, every time the package is run, start and finish times are written to a custom registry key.
Since this key is overwritten each time the package is run, it is also written to a CSV file in the logs location, on a new line each time.

Uninstall registry key

Useful for Endpoint Manager detection.

DisplayName                         : Notepad++ (64-bit x64)
Publisher                           : Notepad++ Team
MajorVersion                        : 8
MinorVersion                        : 44
UninstallString                     : "C:\Program Files\Notepad++\uninstall.exe"
QuietUninstallString                : "C:\Program Files\Notepad++\uninstall.exe" /S
DisplayIcon                         : C:\Program Files\Notepad++\notepad++.exe
DisplayVersion                      : 8.4.4
URLInfoAbout                        : https://notepad-plus-plus.org/
VersionMajor                        : 8
VersionMinor                        : 44
NoModify                            : 1
NoRepair                            : 1
EstimatedSize                       : 13819
MementoSectionUsed                  : 
MementoSection_C                    : 1
MementoSection_C++                  : 1
MementoSection_Java                 : 1
MementoSection_C#                   : 1
MementoSection_HTML                 : 1
MementoSection_RC                   : 1
MementoSection_SQL                  : 1
MementoSection_PHP                  : 1
MementoSection_CSS                  : 1
MementoSection_VB                   : 1
MementoSection_Perl                 : 1
MementoSection_JavaScript           : 1
MementoSection_Python               : 1
MementoSection_ActionScript         : 1
MementoSection_LISP                 : 1
MementoSection_VHDL                 : 1
MementoSection_TeX                  : 1
MementoSection_DocBook              : 1
MementoSection_NSIS                 : 1
MementoSection_CMAKE                : 1
MementoSection_BATCH                : 1
MementoSection_CoffeeScript         : 1
MementoSection_BaanC                : 1
MementoSection_Lua                  : 1
MementoSection_AutoIt               : 1
MementoSection_COBOL                : 1
MementoSection_TypeScript           : 1
MementoSection_C_FL                 : 1
MementoSection_C++_FL               : 1
MementoSection_Java_FL              : 1
MementoSection_C#_FL                : 1
MementoSection_Assembly_FL          : 1
MementoSection_Bash_FL              : 1
MementoSection_SQL_FL               : 1
MementoSection_PHP_FL               : 1
MementoSection_COBOL-section-free   : 1
MementoSection_COBOL_FL             : 1
MementoSection_Perl_FL              : 1
MementoSection_JavaScript_FL        : 1
MementoSection_Python_FL            : 1
MementoSection_Lua_FL               : 1
MementoSection_ini_FL               : 1
MementoSection_Innosetup_FL         : 1
MementoSection_VHDL_FL              : 1
MementoSection_KRL_FL               : 1
MementoSection_NSIS_FL              : 1
MementoSection_PowerShell_FL        : 1
MementoSection_BATCH_FL             : 1
MementoSection_Ruby_FL              : 1
MementoSection_BaanC_FL             : 1
MementoSection_Sinumerik_FL         : 1
MementoSection_AutoIt_FL            : 1
MementoSection_UniVerseBASIC_FL     : 1
MementoSection_XML_FL               : 1
MementoSection_Ada_FL               : 1
MementoSection_Fortran_FL           : 1
MementoSection_Fortran77_FL         : 1
MementoSection_Haskell_FL           : 1
MementoSection_Rust_FL              : 1
MementoSection_TypeScript_FL        : 1
MementoSection_OverrideMap_FL       : 1
MementoSection_NppExport            : 1
MementoSection_MimeTools            : 1
MementoSection_Converter            : 1
MementoSection_AutoUpdater          : 1
MementoSection_PluginsAdmin         : 1
MementoSection_abkhazian            : 0
MementoSection_afrikaans            : 0
MementoSection_albanian             : 0
MementoSection_arabic               : 0
MementoSection_aragonese            : 0
MementoSection_aranese              : 0
MementoSection_azerbaijani          : 0
MementoSection_basque               : 0
MementoSection_belarusian           : 0
MementoSection_bengali              : 0
MementoSection_bosnian              : 0
MementoSection_brazilian_portuguese : 0
MementoSection_breton               : 0
MementoSection_bulgarian            : 0
MementoSection_catalan              : 0
MementoSection_chineseSimplified    : 0
MementoSection_corsican             : 0
MementoSection_croatian             : 0
MementoSection_czech                : 0
MementoSection_danish               : 0
MementoSection_dutch                : 0
MementoSection_english_customizable : 0
MementoSection_esperanto            : 0
MementoSection_estonian             : 0
MementoSection_extremaduran         : 0
MementoSection_farsi                : 0
MementoSection_finnish              : 0
MementoSection_french               : 0
MementoSection_friulian             : 0
MementoSection_galician             : 0
MementoSection_georgian             : 0
MementoSection_german               : 0
MementoSection_greek                : 0
MementoSection_gujarati             : 0
MementoSection_hebrew               : 0
MementoSection_hindi                : 0
MementoSection_hongKongCantonese    : 0
MementoSection_hungarian            : 0
MementoSection_indonesian           : 0
MementoSection_irish                : 0
MementoSection_italian              : 0
MementoSection_japanese             : 0
MementoSection_kannada              : 0
MementoSection_kazakh               : 0
MementoSection_korean               : 0
MementoSection_kurdish              : 0
MementoSection_kyrgyz               : 0
MementoSection_latvian              : 0
MementoSection_ligurian             : 0
MementoSection_lithuanian           : 0
MementoSection_luxembourgish        : 0
MementoSection_macedonian           : 0
MementoSection_malay                : 0
MementoSection_marathi              : 0
MementoSection_mongolian            : 0
MementoSection_nepali               : 0
MementoSection_norwegian            : 0
MementoSection_nynorsk              : 0
MementoSection_occitan              : 0
MementoSection_piglatin             : 0
MementoSection_polish               : 0
MementoSection_portuguese           : 0
MementoSection_punjabi              : 0
MementoSection_romanian             : 0
MementoSection_russian              : 0
MementoSection_samogitian           : 0
MementoSection_sardinian            : 0
MementoSection_serbian              : 0
MementoSection_serbianCyrillic      : 0
MementoSection_sinhala              : 0
MementoSection_slovak               : 0
MementoSection_slovenian            : 0
MementoSection_spanish              : 0
MementoSection_spanish_ar           : 0
MementoSection_swedish              : 0
MementoSection_tagalog              : 0
MementoSection_chineseTraditional   : 0
MementoSection_tajik                : 0
MementoSection_tamil                : 0
MementoSection_tatar                : 0
MementoSection_telugu               : 0
MementoSection_thai                 : 0
MementoSection_turkish              : 0
MementoSection_ukrainian            : 0
MementoSection_urdu                 : 0
MementoSection_uyghur               : 0
MementoSection_uzbek                : 0
MementoSection_uzbekCyrillic        : 0
MementoSection_venetian             : 0
MementoSection_vietnamese           : 0
MementoSection_welsh                : 0
MementoSection_zulu                 : 0
MementoSection_BlackBoard           : 1
MementoSection_Choco                : 1
MementoSection_HelloKitty           : 1
MementoSection_MonoIndustrial       : 1
MementoSection_Monokai              : 1
MementoSection_Obsidian             : 1
MementoSection_PlasticCodeWrap      : 1
MementoSection_RubyBlue             : 1
MementoSection_Twilight             : 1
MementoSection_VibrantInk           : 1
MementoSection_DeepBlack            : 1
MementoSection_vimDarkBlue          : 1
MementoSection_Bespin               : 1
MementoSection_Zenburn              : 1
MementoSection_Solarized            : 1
MementoSection_Solarized-light      : 1
MementoSection_HotFudgeSundae       : 1
MementoSection_khaki                : 1
MementoSection_MossyLawn            : 1
MementoSection_Navajo               : 1
MementoSection_DansLeRuSHDark       : 1
MementoSection_explorerContextMenu  : 1
PSPath                              : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Notepad++
PSParentPath                        : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
PSChildName                         : Notepad++
PSProvider                          : Microsoft.PowerShell.Core\Registry

PSADT script

This is the full PSADT script.

<#
.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]$currentPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
	[XML]$infoXML = (Get-Content "$currentPath\SupportFiles\deployInfo.xml")
	[string]$appVendor = $infoXML.Metadata.Publisher
	[string]$appName = $infoXML.Metadata.DisplayName
	[string]$appVersion = $infoXML.Metadata.DisplayVersion
	[string]$appArch = $infoXML.Metadata.Architecture
	[string]$appLang = 'EN'
	[string]$appRevision = $infoXML.Metadata.Revision
	[string]$appScriptVersion = '1.0.0'
	[string]$appScriptDate = $infoXML.Metadata.Date
	[string]$appScriptAuthor = $infoXML.Metadata.Author
	[string]$appFullName = "$appVendor $appName $appVersion"
	[string]$installDate = (Get-Date -f "yyyyMMdd")
	[string]$logPath = "$env:WinDir\Logs\Software"
	[string]$histFile = $env:ComputerName + '_history.csv'
	[string]$envStartMenu = "$env:ProgramData\Microsoft\Windows\Start Menu\Programs"
	[string]$logRegKey = "HKLM:\SOFTWARE\Applications\$appFullName"
	[string]$appPath = "$env:ProgramFiles\Notepad++"
	[string]$nameWild = '*' + $appName + '*'
	[string]$Parms = '/S'
	[string]$pkgInstaller = 'npp.' + $appVersion + '.Installer.x64.exe'
	##*===============================================
	## 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.4'
	[string]$deployAppScriptDate = '26/01/2021'
	[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>

		# Start Support Logs
		$StartTime = (Get-Date -f "dd/MM/yyyy HH:mm:ss")
		Set-RegistryKey -Key $logRegKey -Name 'StartTime' -Value $StartTime
		Write-Log -Message "Start Time: $StartTime" -LogType 'CMTrace'
		Set-RegistryKey -Key $logRegKey -Name 'AppName' -Value $appFullName
		Write-Log -Message "Name: $appFullName" -LogType 'CMTrace'
		Set-RegistryKey -Key $logRegKey -Name 'MachineName' -Value $env:ComputerName
		Write-Log -Message "Machine Name: $env:ComputerName" -LogType 'CMTrace'
		Set-RegistryKey -Key $logRegKey -Name 'InstalledBy' -Value $ProcessNTAccount
		Write-Log -Message "Installed by: $ProcessNTAccount" -LogType 'CMTrace'
		Set-RegistryKey -Key $logRegKey -Name 'InstalledFrom' -Value $scriptParentPath
		Write-Log -Message "Installed from: $scriptParentPath" -LogType 'CMTrace'
		Set-RegistryKey -Key $logRegKey -Name 'Revision' -Value $appRevision

		# Remove legacy versions if exist
		ForEach ($regKey in $regKeyApplications)
			{
			$appVer = Get-ChildItem -Path $regKey |
				Get-ItemProperty |
					Where-Object {$_.DisplayName -like $nameWild } |
						Select-Object -Property DisplayName, DisplayVersion, UninstallString
			ForEach ($ver in $appVer)
				{
				If ($ver.UninstallString)
					{
					[string]$appRemove = $ver.DisplayName
					[string]$oldVersion = $ver.DisplayVersion
					[string]$Uninst = $ver.UninstallString
					If ($Uninst -notlike "*MsiExec*")
						{
						Write-Log -Message "Uninstalling $appRemove $oldVersion" -LogType 'CMTrace'
						Write-Log -Message "Executing $Uninst $Parms" -LogType 'CMTrace'
						Start-Process $Uninst -ArgumentList $Parms -Wait -PassThru -NoNewWindow -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
						}
					Else
						{Write-Log -Message "Ignoring MsiExec Uninstall for $appRemove $oldVersion" -LogType 'CMTrace'}
					}
				}
			}


		##*===============================================
		##* 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
		Execute-Process -Path $pkgInstaller -Parameters $Parms -WindowStyle Hidden

		# Install Compare plugin
		Write-Log -Message "Installing Compare plugin" -LogType 'CMTrace'
		Expand-Archive -Force "$dirFiles\ComparePlugin.zip" "$appPath\plugins\"

		# Disable updates
		If (Test-Path "$appPath\updater")
			{
			Write-Log -Message "Disabling updates folder" -LogType 'CMTrace'
			Rename-Item -Path "$appPath\updater" -NewName "$appPath\updater_disabled" -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
			}


		##*===============================================
		##* POST-INSTALLATION
		##*===============================================
		[string]$installPhase = 'Post-Installation'

		## <Perform Post-Installation tasks here>

		# End Support Logs
		If ($LastExitCode -eq $null)
			{
			Set-RegistryKey -Key $logRegKey -Name 'ErrorLevel' -Value '0'
			Write-Log -Message "ErrorLevel: 0" -LogType 'CMTrace'
			}
		Else
			{
			Set-RegistryKey -Key $logRegKey -Name 'ErrorLevel' -Value $LastExitCode
			Write-Log -Message "ErrorLevel: $LastExitCode" -LogType 'CMTrace'
			}
		$finishTime = (Get-Date -f "dd/MM/yyyy HH:mm:ss")
		Set-RegistryKey -Key $logRegKey -Name 'FinishTime' -Value $finishTime
		Write-Log -Message "Finish Time: $finishTime" -LogType 'CMTrace'

		$results = @()
		$keys = Get-Item $logRegKey |
		ForEach {
			$obj = New-Object psobject
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'AppName' -Value $_.GetValue("AppName")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'MachineName' -Value $_.GetValue("MachineName")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'StartTime' -Value $_.GetValue("StartTime")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'InstalledBy' -Value $_.GetValue("InstalledBy")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'InstalledFrom' -Value $_.GetValue("InstalledFrom")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'ErrorLevel' -Value $_.GetValue("ErrorLevel")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'FinishTime' -Value $_.GetValue("finishTime")
			$results += $obj
			}
		$results | Export-Csv -Path $logPath\$histFile -Append -Force -NoTypeInformation

		## 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

		## 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 any version if exist
		ForEach ($regKey in $regKeyApplications)
			{
			$appVer = Get-ChildItem -Path $regKey |
				Get-ItemProperty |
					Where-Object {$_.DisplayName -like $nameWild } |
						Select-Object -Property DisplayName, DisplayVersion, UninstallString
			ForEach ($ver in $appVer)
				{
				If ($ver.UninstallString)
					{
					[string]$appRemove = $ver.DisplayName
					[string]$oldVersion = $ver.DisplayVersion
					[string]$Uninst = $ver.UninstallString
					If ($Uninst -notlike "*MsiExec*")
						{
						Write-Log -Message "Uninstalling $appRemove $oldVersion" -LogType 'CMTrace'
						Write-Log -Message "Executing $Uninst $Parms" -LogType 'CMTrace'
						Start-Process $Uninst -ArgumentList $Parms -Wait -PassThru -NoNewWindow -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
						}
					Else
						{Write-Log -Message "Ignoring MsiExec Uninstall for $appRemove $oldVersion" -LogType 'CMTrace'}
					}
				}
			}
		
		# Cleanup
		Remove-Folder -Path $appPath


		##*===============================================
		##* 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>

		$StartTime = (Get-Date -f "dd/MM/yyyy HH:mm:ss")
		Set-RegistryKey -Key $logRegKey -Name 'StartTime' -Value $StartTime
		Write-Log -Message "Start Time: $StartTime" -LogType 'CMTrace'
		Set-RegistryKey -Key $logRegKey -Name 'AppName' -Value $appFullName
		Write-Log -Message "Name: $appFullName" -LogType 'CMTrace'
		Set-RegistryKey -Key $logRegKey -Name 'MachineName' -Value $env:ComputerName
		Write-Log -Message "Machine Name: $env:ComputerName" -LogType 'CMTrace'
		Set-RegistryKey -Key $logRegKey -Name 'InstalledBy' -Value $ProcessNTAccount
		Write-Log -Message "Installed by: $ProcessNTAccount" -LogType 'CMTrace'
		Set-RegistryKey -Key $logRegKey -Name 'InstalledFrom' -Value $scriptParentPath
		Write-Log -Message "Installed from: $scriptParentPath" -LogType 'CMTrace'
		Set-RegistryKey -Key $logRegKey -Name 'Revision' -Value $appRevision

		##*===============================================
		##* 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>

		ForEach ($regKey in $regKeyApplications)
			{
			$appVer = Get-ChildItem -Path $regKey |
				Get-ItemProperty |
					Where-Object {$_.DisplayName -like $nameWild } |
						Select-Object -Property DisplayName, DisplayVersion, UninstallString
			ForEach ($ver in $appVer)
				{
				If ($ver.UninstallString)
					{
					[string]$appRemove = $ver.DisplayName
					[string]$oldVersion = $ver.DisplayVersion
					[string]$Uninst = $ver.UninstallString
					If ($Uninst -notlike "*MsiExec*")
						{
						Write-Log -Message "Uninstalling $appRemove $oldVersion" -LogType 'CMTrace'
						Write-Log -Message "Executing $Uninst $Parms" -LogType 'CMTrace'
						Start-Process $Uninst -ArgumentList $Parms -Wait -PassThru -NoNewWindow -ErrorAction SilentlyContinue -WarningAction SilentlyContinue | Out-Null
						}
					Else
						{Write-Log -Message "Ignoring MsiExec Uninstall for $appRemove $oldVersion" -LogType 'CMTrace'}
					}
				}
			}
		Execute-Process -Path $pkgInstaller -Parameters $Parms -WindowStyle Hidden
		Write-Log -Message "Installing Compare plugin" -LogType 'CMTrace'
		Expand-Archive -Force "$dirFiles\ComparePlugin.zip" "$appPath\plugins\"
		If (Test-Path "$appPath\updater")
			{
			Write-Log -Message "Disabling updates folder" -LogType 'CMTrace'
			Rename-Item -Path "$appPath\updater" -NewName "$appPath\updater_disabled" -Force -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
			}

		##*===============================================
		##* POST-REPAIR
		##*===============================================
		[string]$installPhase = 'Post-Repair'

		## <Perform Post-Repair tasks here>

		If ($LastExitCode -eq $null)
			{
			Set-RegistryKey -Key $logRegKey -Name 'ErrorLevel' -Value '0'
			Write-Log -Message "ErrorLevel: 0" -LogType 'CMTrace'
			}
		Else
			{
			Set-RegistryKey -Key $logRegKey -Name 'ErrorLevel' -Value $LastExitCode
			Write-Log -Message "ErrorLevel: $LastExitCode" -LogType 'CMTrace'
			}
		$finishTime = (Get-Date -f "dd/MM/yyyy HH:mm:ss")
		Set-RegistryKey -Key $logRegKey -Name 'FinishTime' -Value $finishTime
		Write-Log -Message "Finish Time: $finishTime" -LogType 'CMTrace'

		$results = @()
		$keys = Get-Item $logRegKey |
		ForEach {
			$obj = New-Object psobject
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'AppName' -Value $_.GetValue("AppName")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'MachineName' -Value $_.GetValue("MachineName")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'StartTime' -Value $_.GetValue("StartTime")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'InstalledBy' -Value $_.GetValue("InstalledBy")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'InstalledFrom' -Value $_.GetValue("InstalledFrom")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'ErrorLevel' -Value $_.GetValue("ErrorLevel")
			Add-Member -InputObject $obj -MemberType NoteProperty -Name 'FinishTime' -Value $_.GetValue("finishTime")
			$results += $obj
			}
		$results | Export-Csv -Path $logPath\$histFile -Append -Force -NoTypeInformation


    }
	##*===============================================
	##* 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
}