MSEndpointMgr

Work around Adobe Flash upgrade 1603 issues with PowerShell

Maintaining Adobe Flash

Although as we all know Adobe Flash is a product which has caused quite a lot of security related news over the past number and years, and Adobe is to discontinue it in 2020, however for some organisations there is still a requirement to maintain the product.

Exit Code 1603

Recently I was asked to push out an upgraded version of the Flash PPAPI for use with Google Chrome, and quickly came up against the 1603 exit code issue that Nickolaj covers in an earlier post from 2013 (https://msendpointmgr.com/2013/05/23/upgrade-adobe-flash-player-11-7-x-fails-with-error-1603-in-configmgr-2012/).

AppEnforce Log Contents

I decided to write a PowerShell script to cater for upgrading Flash. The script perform the following actions:

  • Search the registry for Uninstall strings for versions earlier than the detected MSI version from both the “HKLM:SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall” and “HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” locations
  • Run the MSIEXEC command silently with the uninstall string
  • Query WMI to obtain a list of registered versions
    Legacy Adobe Flash PPAPI Example – Listed in WMI
  • Remove earlier registered Flash versions from the Regsitry
  • Install the MSI contained within the package.
Prerequisite’s
PowerShell Script
<#
.SYNOPSIS
    Adobe Flash Upgrade Script.
.DESCRIPTION
    This script will uninstall and remove entries for Adobe Flash installers. Package the script up with 
  the installer MSI and it will remove previous versions and install the version contained within the 
  pacakge.
  If the same version is found, no action will be taken.
.EXAMPLE
    .\AdobeFlashUpgrade.ps1
.NOTES
    FileName:    AdobeFlashUpgrade.ps1
    Authors:     Maurice Daly 
    Contact:     @modaly_it
    Created:     2017-08-18
    Updated:     2017-08-22
    
    Version history:
    1.0.0 - (2017-08-18) Script created (Maurice Daly)
  1.0.1 - (2017-08-22) Updated old product detection method to check registry entries as opposed WMI
             and attempt to locate the legacy installer to uninstall the product. Added 
             command to close all browsers prior to the uninstall/installation
#>
function GetMSIFileInformation {
  param (
    

[parameter(Mandatory = $true)]

[ValidateNotNullOrEmpty()] [System.IO.FileInfo]$Path,

[parameter(Mandatory = $true)]

[ValidateNotNullOrEmpty()] [ValidateSet(“ProductCode”, “ProductVersion”, “ProductName”, “Manufacturer”, “ProductLanguage”, “FullVersion”)] [string]$Property ) Process { try { # Read property from MSI database $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer $MSIDatabase = $WindowsInstaller.GetType().InvokeMember(“OpenDatabase”, “InvokeMethod”, $null, $WindowsInstaller, @($Path.FullName, 0)) $Query = “SELECT Value FROM Property WHERE Property = ‘$($Property)'” $View = $MSIDatabase.GetType().InvokeMember(“OpenView”, “InvokeMethod”, $null, $MSIDatabase, ($Query)) $View.GetType().InvokeMember(“Execute”, “InvokeMethod”, $null, $View, $null) $Record = $View.GetType().InvokeMember(“Fetch”, “InvokeMethod”, $null, $View, $null) $Value = $Record.GetType().InvokeMember(“StringData”, “GetProperty”, $null, $Record, 1) # Commit database and close view $MSIDatabase.GetType().InvokeMember(“Commit”, “InvokeMethod”, $null, $MSIDatabase, $null) $View.GetType().InvokeMember(“Close”, “InvokeMethod”, $null, $View, $null) $MSIDatabase = $null $View = $null # Return the value return $Value } catch { Write-Warning -Message $_.Exception.Message; break } } End { # Run garbage collection and release ComObject [System.Runtime.Interopservices.Marshal]::ReleaseComObject($WindowsInstaller) | Out-Null [System.GC]::Collect() } } function Uninstall { param (

[parameter(Mandatory = $true)]

[ValidateNotNullOrEmpty()] $Installations ) foreach ($Installation in $Installations) { if ($Installation -ne $null) { try { $UninstallArgs = $((($Installation.UninstallString).Split(” “) | Select -Last 1) + ” /qn”) Start-Process msiexec.exe -ArgumentList $UninstallArgs -Wait } catch { Write-Warning -Message $_.Exception.Message; break } } } } function Install { param (

[parameter(Mandatory = $true)]

[ValidateNotNullOrEmpty()] $AdobeMSI ) if ($AdobeMSI -ne $null) { try { Start-Process msiexec.exe -ArgumentList (“/i” + $AdobeMSI.fullName + ” /qn”) -Wait } catch { Write-Warning -Message $_.Exception.Message; break } } } # Get OS Architecture $OSArchitecture = (Get-WmiObject -Query “Select OSArchitecture from Win32_OperatingSystem”).OSArchitecture # Get Adobe Flash Full Product Name $AdobeMSI = Get-ChildItem -Filter *.msi | Sort-Object LastWriteTime -Descending | select -First 1 $AdobeProductName = ([string](GetMSIFileInformation -Path $AdobeMSI.FullName -Property ProductName)).Trim() $AdobeProductVersion = ([string](GetMSIFileInformation -Path $AdobeMSI.FullName -Property ProductVersion)).Trim() # Attempt Uninstall $32BitInstallations = Get-ChildItem -Path “HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall” | Get-ItemProperty | Where-Object { ($_.DisplayName -match ($AdobeProductName.Split(” “) | select -Last 1)) -and ($_.DisplayName -match “Adobe”) } if (($32BitInstallations -ne $null) -and ($32BitInstallations.DisplayVersion -ne $AdobeProductVersion)) { Get-Process | Where-Object { ($_.ProcessName -eq “MicrosoftEdge”) -or ($_.ProcessName -eq “Chrome”) -or ($_.ProcessName -eq “Iexplore”) -or ($_.ProcessName -eq “Firefox”) } | Stop-Process -Force Uninstall -Installations $32BitInstallations } if ($OSArchitecture -match “64”) { $64BitInstallations = Get-ChildItem -Path “HKLM:SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall” | Get-ItemProperty | Where-Object { ($_.DisplayName -match ($AdobeProductName.Split(” “) | select -Last 1)) -and ($_.DisplayName -match “Adobe”) } if (($64BitInstallations -ne $null) -and ($64BitInstallations.DisplayVersion -ne $AdobeProductVersion)) { Get-Process | Where-Object { ($_.ProcessName -eq “MicrosoftEdge”) -or ($_.ProcessName -eq “Chrome”) -or ($_.ProcessName -eq “Iexplore”) -or ($_.ProcessName -eq “Firefox”) } | Stop-Process -Force Uninstall -Installations $64BitInstallations } } # List all Adobe Flash Installs $FlashInstallations = Get-ChildItem -Path “HKLM:\SOFTWARE\Classes\Installer\Products” | Get-ItemProperty | Where-Object { ($_.ProductName -notmatch $AdobeProductName) -and ($_.Name -match ($AdobeProductName.Split(” “) | select -Last 1)) } # Remove Adobe Flash product entries from the Registry foreach ($FlashInstallation in $FlashInstallations) { if (!([string]::IsNullOrEmpty($FlashInstallation.PSChildName))) { $RegistryBase = “HKLM:\SOFTWARE\Classes\Installer\Products\” $RegistryEntry = $RegistryBase + $FlashInstallation.PSChildName $InstallerDetails = Get-ChildItem -Path (“HKLM:\SOFTWARE\Classes\Installer\Products\” + $FlashInstallation.PSChildName) | Get-ItemProperty $InstallerSource = ($InstallerDetails.LastUsedSource).Split(“;”) | select -Last 1 if ((Test-Path -Path $InstallerSource) -eq $true) { $LegacyUninstallArgs = “/X ” + $InstallerSource + ” /qn” try { Start-Process msiexec.exe -ArgumentList $LegacyUninstallArgs } catch { Write-Warning -Message $_.Exception.Message; break } } if (($RegistryEntry -ne $RegistryBase) -and (test-path $RegistryEntry -eq $true)) { Write-Host “Removing Registry Entries” $RegistryEntry | Remove-Item -Recurse -Force } } } # Install Adobe Flash if (($32BitInstallations -eq $null) -or ($32BitInstallations.DisplayVersion -ne $AdobeProductVersion) -and ($OSArchitecture -match “32”)) { # Install latest Adobe Flash component Install $AdobeMSI } elseif (($64BitInstallations -eq $null) -or ($64BitInstallations.DisplayVersion -ne $AdobeProductVersion) -and ($OSArchitecture -match “64”)) { # Install latest Adobe Flash component Install $AdobeMSI }

Creating the Application Package

Now let’s go about creating the Application package using the script installer method. First things first is to create a location where both the MSI and PS1 are stored, then proceed with the below;

  1. Open the Systems Center Configuration Manager Console
  2. Click on the Software Library tab
  3. Expand Application Management and right click on Applications 
  4. Right click and click Create Application
  5. Select the option to “Manually specify the application information
  6. Name your package and make sure to include the Software Version as this will be used to cross reference against the GUID used for detection and uninstalling the software

  7. Add in an Icon to make it look good in the Software Center
  8. On the Deployment Types screen click on the Add button
  9. Select Script Installer as the type
  10. Specify the content location and enter the following details
  11. You should now have something that looks similar to the below
  12. For the Detection Method use the Setting Type “Windows Installer” and enter the GUID obtained previously
  13. Finish the Wizard
  14. Deploy the Application
Software Center

Refresh the computer policy on a machine within the collection you deployed the application to. Select the Adobe Flash Player app and click install.

FUTURE DEPLOYMENTS

Using this method the only thing you need to do is change the detection and uninstall GUID values, as the script will take care of uninstalling the currently installed version.

(3358)

Maurice Daly

Maurice has been working in the IT industry for the past 20 years and currently working in the role of Senior Cloud Architect with CloudWay. With a focus on OS deployment through SCCM/MDT, group policies, active directory, virtualisation and office 365, Maurice has been a Windows Server MCSE since 2008 and was awarded Enterprise Mobility MVP in March 2017. Most recently his focus has been on automation of deployment tasks, creating and sharing PowerShell scripts and other content to help others streamline their deployment processes.

4 comments

Sponsors