If you work in a large enterprise you will have had to deploy Flash Player to your workstations and if you have, you will know that it has more security holes than swiss cheese and needs updating very often. Trying to keep control of this is the road to madness so let’s automate the sh#! out of it.

In the past I used to disable the auto update as it just annoys the end user and would try to keep it up to date but this causes more problems than it solves.

Controlled automation is the solution.

Broadly what i did

  • Create an application and deployment for Adobe Flash Player(IE and Firefox versions).
  • Create a Configuration item to make sure it’s set to auto update.
  • Create and deploy a Configuration Baseline.
  • Update the Adobe Flash Player scheduled task.
  • Never have to worry about flash again until Adobe retire the product.

Update existing versions

In my environment we use SNOW Licence Manager, this can give a detailed reports of all software and more importantly what versions of said software. What i found was not encouraging, the versions ranged from 9 to 22.

It was important to update all installations to the latest version and that can act as my baseline to work off for the future.

This was before, pretty bad.

Application Name Installation
Adobe Flash Player 9 42
Adobe Flash Player 10 89
Adobe Flash Player 11 368
Adobe Flash Player 14 97
Adobe Flash Player 17 1203
Adobe Flash Player 18 437
Adobe Flash Player 19 868
Adobe Flash Player 20 1489
Adobe Flash Player 22 107

 

Download Flash Player MSI

Go to the flash distribution page found here – https://www.adobe.com/uk/products/flashplayer/distribution5.html

 

1Downloads Flash Player 23.0.0.207 (Win & Mac) Operating System Windows Windows Windows Flash Player Type Internet Explorer-Active X Firefox and Netscape Plug-ln compatible applications WAPI Opera and Chromium based applications — PPAPI Languages All supported languages All supported languages All supported languages Installers Download EXE Installer Download MSI Installer • Import SCCM/ConfigMgr SCUP Catalog* Download EXE Installer Download MS' Installer Download EXE Installer Download MSI Installer

Note:
  • You will need to apply to Adobe for a distribution license to access this site
  • As of windows 8 flash has been embed into IE and Edge
  • Chrome has flash built in and its better to let chrome update itself rather than deploy the PPAPI version

Create and deploy Adobe Flash Player

Using the voodoo power of PowerShell create the adobe applications and deploy them to all workstations, obviously change as needed

Script;
<# 
.NOTES 
=========================================================================== 
Created on: 09/11/2016 10:56 
Created by: Terence Beggs & Maurice Daly 
Organization: 
Filename: AdobeFlashDeployment.ps1 
=========================================================================== 
.DESCRIPTION Adds Adobe Flash Player MSIs to your SCCM Application list. 
The Script assumes the following folder structure exists in your software 
repository path provided - "Adobe\Flash Player" 
.EXAMPLE AdobeFlashDeployment.ps1 -SiteCode SCM -RepositoryPath \\YOURSERVER\UNCSHARE -IconPath \\YOURSERVER\UNCSHARE\ICONS\ADOBEFLASH.ICO 

Note that you do not have to specify an icon .NOTES MSI Database Function 
sourced from http://www.scconfigmgr.com/2014/08/22/how-to-get-msi-file-information-with-powershell/ 
#>

[CmdletBinding(SupportsShouldProcess = $true)]
param (
	[parameter(Mandatory = $true, HelpMessage = "SCCM Site Code Required", Position = 1)]
	[ValidateNotNullOrEmpty()]
	[string]$SiteCode,
	[parameter(Mandatory = $true, HelpMessage = "Base UNC path of your packages")]
	[ValidateNotNullOrEmpty()]
	[ValidateScript({ Test-Path $_ })]
	[string]$RepositoryPath,
	[parameter(Mandatory = $false, HelpMessage = "Please indicate if you wish to specify a custom icon, default is false")]
	[ValidateNotNullOrEmpty()]
	[bool]$SpecifyIcon = $false,
	[parameter(Mandatory = $false, HelpMessage = "Location of .ICO or PNG to use as the application icon")]
	[ValidateNotNullOrEmpty()]
	[ValidateScript({ Test-Path $_ })]
	[string]$IconPath
)

# Import SCCM PowerShell Module
$ModuleName = (get-item $env:SMS_ADMIN_UI_PATH).parent.FullName + "\ConfigurationManager.psd1"
Import-Module $ModuleName

Write-Debug "Site Code In Use : $SiteCode"

# Specify Adobe Flash Folder
$AdobeFlashDir = "\Adobe Systems\Flash Player\"

# Remove back slash if added to the RepositoryPath
$RepositoryPath = $RepositoryPath.Trimend("\")
Write-Debug "Package UNC Base Path In Use : $RepositoryPath"

# Specify SCCM Collection
$AllWksCollection = "All Active Workstations"

function GetMSIDetails ($MSI, $Property)
{
	Process
	{
		Write-Debug "Function $MSI"
		Write-Debug "Fuction $Property"
		try
		{
			# Read property from MSI database
			$WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer
			Write-Debug "FullName = $($MSI.FullName)"
			$MSIDatabase = $WindowsInstaller.GetType().InvokeMember("OpenDatabase", "InvokeMethod", $null, $WindowsInstaller, @($MSI.FullName, 0))
			Write-Debug "MSIDatabase = $MSIDatabase"
			
			# Read properties
			$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)
			Write-Debug "Value = $Value"
			
			# 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()
	}
}

foreach ($MSI in (Get-ChildItem -Path ($RepositoryPath + $AdobeFlashDir) -Filter *.MSI | Sort-Object $_.LastWriteTime | select -First 2))
{
	Write-Debug "Collecting details for $MSI file"
	$Property = "Manufacturer"
	$Manufacturer = (GetMSIDetails ($MSI)($Property))
	$Manufacturer = ([string]$Manufacturer).Trim()
	Write-Debug "Manufacturer: $ProductName"
	$Property = "ProductName"
	$ProductName = (GetMSIDetails ($MSI)($Property))
	$ProductName = ([string]$ProductName).Trim()
	Write-Debug "Product Name: $ProductName"
	$Property = "ProductVersion"
	$ProductVersion = (GetMSIDetails ($MSI)($Property))
	$ProductVersion = ([string]$ProductVersion).Trim()
	Write-Debug "Querying MSI Details"
	
	Set-Location -Path ($SiteCode + ":")
	
	if ((Get-CMApplication -Name $ProductName) -ne $null)
	{
		Write-Debug "Running Application Creation for $ProductName"
		#########################################
		# Create Application with Icon
		#########################################
		
		If ($SpecifyIcon -ne $false)
		{
			Write-Debug "Creating application with icon $IconPath specified"
			# Custom icon specified
			New-CMApplication -Name "$ProductName" -IconLocationFile $IconPath -LocalizedDescription $ProductName -LocalizedName $ProductName -Publisher $Manufacturer -SoftwareVersion $ProductVersion
		}
		else
		{
			Write-Debug "Creating application without optional icon specified"
			#########################################
			# Create Application without Icon
			#########################################
			
			New-CMApplication -Name "$ProductName" -LocalizedDescription $ProductName -LocalizedName $ProductName -Publisher $Manufacturer -SoftwareVersion $ProductVersion
		}
		
		#########################################
		# Create Deployment Types
		#########################################
		
		Add-CMDeploymentType -DeploymentTypeName $ProductName -ApplicationName $ProductName -InstallationFileLocation $MSI.FullName -MsiInstaller -AutoIdentifyFromInstallationFile -ForceForUnknownPublisher $true -InstallationBehaviorType InstallForSystem -Verbose
		
		#########################################
		# Distripute Content
		#########################################
		
		Start-CMContentDistribution -ApplicationName $ProductName -DistributionPointGroupName "All Distribution Points" -Verbose
		
		#########################################
		# Create Application Deployment
		#########################################
		
		Start-CMApplicationDeployment -CollectionName $AllWksCollection -Name $ProductName -AvailableDate (get-date) -AvailableTime (get-date) -DeployAction Install -DeployPurpose Required -TimeBaseOn LocalTime
	}
	else
	{
		Write-Warning -Message "$ProductName already exists. Skipping.."
	}
}

#########################################
# Refresh Policy on collection
#########################################

Start-Sleep -Seconds 10

Invoke-CMClientNotification -DeviceCollectionName $AllWksCollection -NotificationType RequestMachinePolicyNow -Verbose

#########################################
# Run the Deployment Summarization
#########################################

Invoke-CMDeploymentSummarization -CollectionName $AllWksCollection -Verbose

 

Once you have deployed the latest version of flash everywhere you should end up with a baseline to work off, some clients won’t want to update from let’s say version 11 to 23 My buddy MVP Nickolaj Andersen has a good post about this – http://www.scconfigmgr.com/2013/05/23/upgrade-adobe-flash-player-11-7-x-fails-with-error-1603-in-configmgr-2012/

Creating a Configuration Item

Create a Configuration Item to ensure Adobe flash player updates itself:

2-ci-general

3-ci-general-2

 

Discovery Script

This script looks for the existence of the “mms.cfg” file, in this file you can enable or disable update and even more importantly make them silent. More details here http://www.adobe.com/devnet/flashplayer/articles/flash_player_admin_guide.html

4-ci-discovery-script
Script;

if (Test-Path $env:WINDIR\SysWOW64)
{
 if (Test-Path "$env:WINDIR\SysWOW64\Macromed\Flash\mms.cfg")
 {
 $AutoUpdateDisable = Select-String -Path "$env:WINDIR\SysWOW64\Macromed\Flash\mms.cfg" -Pattern AutoUpdateDisable=0 
 If ($AutoUpdateDisable -match "AutoUpdateDisable=0") {Write-Host $True} Else {Write-Host $False}
 $SilentAutoUpdateEnable = Select-String -Path "$env:WINDIR\SysWOW64\Macromed\Flash\mms.cfg" -Pattern SilentAutoUpdateEnable=1 
 If ($SilentAutoUpdateEnable -match "SilentAutoUpdateEnable=1") {Write-Host $True} Else {Write-Host $False}
 }
 else
 {
 "File doesn't exist"
 Write-Host $False
 }
}

if (Test-Path $env:WINDIR\System32)
{
 if (Test-Path "$env:WINDIR\System32\Macromed\Flash\mms.cfg")
 {
 $AutoUpdateDisable = Select-String -Path "$env:WINDIR\System32\Macromed\Flash\mms.cfg" -Pattern AutoUpdateDisable=0 
 If ($AutoUpdateDisable -match "AutoUpdateDisable=0") {Write-Host $True} Else {Write-Host $False}
 $SilentAutoUpdateEnable = Select-String -Path "$env:WINDIR\System32\Macromed\Flash\mms.cfg" -Pattern SilentAutoUpdateEnable=1 
 If ($SilentAutoUpdateEnable -match "SilentAutoUpdateEnable=1") {Write-Host $True} Else {Write-Host $False}
 }
 else
 {
 "File doesn't exist"
 Write-Host $False
 }
}

If the script runs and doesn’t find the files it will return false(this is important later)

4-ps-run

Remediation Script

This script creates the files and writes the entries;

5-ci-remdiation

Script;

if (Test-Path $env:WINDIR\SysWOW64)
{
Write-Host "Creating mms.cfg file"
New-Item "$env:WINDIR\SysWOW64\Macromed\Flash\mms.cfg" -type file -Force
Add-Content "$env:WINDIR\SysWOW64\Macromed\Flash\mms.cfg" "AutoUpdateDisable=0"
Add-Content "$env:WINDIR\SysWOW64\Macromed\Flash\mms.cfg" "SilentAutoUpdateEnable=1"
(Get-Content -path "$env:WINDIR\SysWOW64\Macromed\Flash\mms.cfg") | Set-Content -Encoding UTF8 -Path "$env:WINDIR\SysWOW64\Macromed\Flash\mms.cfg"

}
if (Test-Path $env:WINDIR\System32)
{
Write-Host "Creating mms.cfg file"
New-Item "$env:WINDIR\System32\Macromed\Flash\mms.cfg" -type file -Force
Add-Content "$env:WINDIR\System32\Macromed\Flash\mms.cfg" "AutoUpdateDisable=0"
Add-Content "$env:WINDIR\System32\Macromed\Flash\mms.cfg" "SilentAutoUpdateEnable=1"
(Get-Content -path "$env:WINDIR\System32\Macromed\Flash\mms.cfg") | Set-Content -Encoding UTF8 -Path "$env:WINDIR\System32\Macromed\Flash\mms.cfg"

}

6-mms

 

Compliance Rules

This means if the discovery is false it will run the script to create the files.

7-compliance

 

Creating a Configuration Baseline

Now create a configuration baseline

8-cb-1

9-cb-2

 

Deploy Configuration Baseline

Now deploy the baseline

10-cb-3

Baseline deployment in action

If you delete the mms.cfg file or if you change any settings, discovery will report that something is wrong and the remediation script will repair it.

11-example-1

12-example-2

Click evaluate in the configuration manager client:

13-example-3

Within seconds the file is back:

14-example-4

15-example-5


Scheduling the automatic updates

When you install flash and allow it to update itself it creates a task schedule which runs once an hour every day which is nuts.
So either using a GPO or use PowerShell, for ease i used a GPO to change the schedule task.

Before

This is set to run way too often, adobe reader suffers from the same issue.

16-gpo-1

After

17-gpo-2

Group Policy

I run the updater twice a day three days a week, the reason we need to run it twice is the updating service can only update one component at a time. Use item level targeting as the updating files are located in different areas depending on your OS.

18-gpo-3

19-gpo-4

20-gpo-5
Pat Yourself On The Back!

When you take the steps above you can ensure that flash player is up to date on all workstations until the day Adobe retire the product.

21-finished

Any questions you can catch me on twitter – @terencebeggs

I am originally from Dublin – Ireland but moved to London in 2000 to study for a Computer Science degree. I currently work for London Metropolitan University, It’s a challenging but also a creative environment.

I specialise in system center configuration manager and application packaging, I’m working on increasing my online presence though my website and twitter account so please feel to drop me a line.

(1758)

There are no comments.

Leave a Reply