Update Adobe Flash Player on remote computers

Adobe frequently updates the Flash player in order to remove security flaws and prevent attacks on the computers running this software. As a new version of a software package is released, you might need to update the existing copies of Flash player on your remote machines. These updates can be carried out using a PowerShell script with the Get-WmiObject cmdlet which can be run against remote computers. This means that you can use Windows PowerShell as a management tool.

By default, Get-WmiObject binds to the root\cimv2 namespace on a local computer, making it very easy to return property values for just about any class found in cimv2. Here, two WMI classes will be used:

  • The first one is the Win32_Product WMI class that represents products as they are installed by Windows Installer; in my PowerShell script example, this class uses the Uninstall method with the purpose to uninstall the application/software (i.e. Flash Player) as displayed by win32_product instance.
  • The second one is the Win32_Process WMI class that represents a process on an operating system. The Create method of this class will be used to install Flash player in a form of a Command line to be passed to this method and executed as a new process on remote machine.

Here are the steps in a nutshell:

  • Download the flash player distribution file from the official Adobe site;
  • Create a text file called mms.cfg with purpose to disable auto update of Flash player software;
  • Copy with a script all (distribution and configuration) files to the remote computers;
  • Select the computers that you’d like to deploy software to (in my script example, it is an OU container in Active Directory);
  • Ensure that you have privileged access permissions to the remote computer.

Additional info about disabling auto-update of Adobe Flash player

The following table describes settings in the mms.cfg file:

Parameter Default Description
AutoUpdateDisable 0 0 allows auto-update based on user settings.
1 disables auto-update.
AutoUpdateInterval <0 (or absent)

Takes a numeric value.

<0 (or absent) uses value from player settings.
0 checks for updates every time the player launches.
> 0 specifies the minimum number of days between check for updates.

SilentAutoUpdateEnable 1 1 allows background update.
0 disables background update.

Open Notepad on your computer; create a text file called mms.cfg and type in the following command line:

AutoUpdateDisable=1

Place this file in the same network location with the downloaded flash player distribution file. The PowerShell script will copy mms.cfg file in the following path:  C:\windows\system32\macromed\flash\ on the remote computers.

Once the mms.cfg file is applied, the auto update setting is disabled as shown in the picture below.

FlashPlayerUpdateDisabled

Figure 01: Flash Player is configured to never check for updates.

The PowerShell script example

You have to run this script by ensuring that the administrative access to the remote computers has been set.  It will uninstall Adobe Flash Player 13 ActiveX” and install “Adobe Flash Player 19 ActiveX”.


<# 
.SYNOPSIS 
Update-FlashPlayerApp.ps1 Updates Adobe Flash Player software on remote computers. 
.OUTPUTS 
One .csv file to record all installed Flash Player software. 
One .log file to record errors/problems encountered while installing software. 
.PARAMETER 
ouName (Mandatory) specifies the computers' container in AD. 
.PARAMETER 
logPath (Mandatory) specifies the path to the log file. 
.EXAMPLE 
Update-FlashPlayerApp.ps1 -ouName "AFL" 
Update-FlashPlayerApp.ps1 -ouName "AFL" -WhatIf Update-FlashPlayerApp.ps1 -logPath C:\Log\Update-FlashPlayerLog.log Update-FlashPlayerApp01.ps1 -logPath "C:\Log\FlashProduct.csv" 
.DESCRIPTION 
Updates Adobe Flash Player software on remote computers. 
.NOTES 
Written by: Alex Dujakovic, Jan 2016 Requires PowerShell Version 3.0 
#>
            
[CmdletBinding(SupportsShouldProcess=$True,DefaultParametersetName="UpdateSoftware")]
 
param( 
[Parameter(ParameterSetName="UpdateSoftware", Mandatory=$True, Position=0)] 
[string]$ouName, 

[Parameter(ParameterSetName="ViewLogFile", Mandatory=$True, Position=0)] 
[string]$logPath

)

Import-Module ActiveDirectory

# ---------------------------------------------|LOG FILES|---------------------------
# EDIT THESE LINES ACCORDING TO YOUR ENVIRONMENT

# Log files locations:
$Script:logFile = "C:\PScontainer\Software\Update-FlashPlayerLog.log"
$Script:csvFilePath = "C:\PScontainer\Software\FlashProduct.csv"
# Installation file location:
$Script:installFlashPlayerFile = "\\Server\Share\install_flash_player_19_active_x.msi"

# Check if .CSV file exist, and create empty one with column names
if (!(Test-Path -path $csvFilePath)) { ""|Select Name, Comment | 
Export-Csv -Path $csvFilePath -NoTypeInformation}

# ---------------------------------------------|FUNCTIONS|---------------------------
# UPDATE SOFTWARE FUNCTION

Function Update-Software($ouName){
$findOU = (Get-ADOrganizationalUnit -LDAPFilter "(Name=$ouName)")
$myOU = [ADSI]"LDAP://$($findOU.DistinguishedName)"

$outputArray = New-Object -TypeName System.Collections.ArrayList

$PCcollection = ($myOU.psbase.Children | 
Where  -FilterScript{$_.ObjectCategory -Like "*Computer*"} | 
Select-Object -ExpandProperty Name)
$reachedPCs = (Import-Csv -Path $Script:csvFilePath | 
Select-Object -ExpandProperty Name)

# COPY INSTALLATION FILE FUNCTION

Function CopyAppFile($computer,$path,$destination){
 Write-Host "$($Computer): COPYING INSTALLATION FILES..." -ForegroundColor Green
 if (Test-Path "$($destination)"){
   try {
         $ErrorActionPrefference = "STOP"
         Copy-Item -Path $path -Destination $destination -Force | Out-Null 
         "$($Computer),Copy File From: $path" | 
         Out-file -FilePath $Script:logFile -Encoding ascii -Append
       }

   catch{
         "$($Computer),ERROR Copy-File Error - $($_.Exception.GetType().FullName)`
          - $($_.Exception.Message)" | Out-file -FilePath $logFile -Encoding ascii -Append
        }      
   }

 else{
        
   try{
          $ErrorActionPrefference = "STOP"
          New-Item "$($destination)" -ItemType directory -Force | Out-Null
          "$($Computer),Create Folder: $destination" | 
          Out-file -FilePath $Script:logFile -Encoding ascii -Append
          Copy-Item -Path $path -Destination $destination -Force | Out-Null
          "$($Computer),Copy File From: $path" |
           Out-file -FilePath $Script:logFile -Encoding ascii -Append
       }

   catch{
         "$($Computer),ERROR Create-Folder-Copy File 
         - $($_.Exception.GetType().FullName) - $($_.Exception.Message)" | 
         Out-file -FilePath $Script:logFile -Encoding ascii -Append
       }
   }
}

# UNINSTALL APPLICATION FUNCTION

Function UnInstallApp($computer, $appName){
   Write-Host "$($Computer): UNINSTALLING APPLICATION..." -ForegroundColor Green
    try{
        $ErrorActionPrefference = "STOP"
        $uninstallActiveX = Get-WmiObject -ComputerName $computer`
        -Class 'Win32_Product' -Filter "Name = ""$($appName)"""
        $uninstallActiveX.Uninstall() | Out-Null
         "$($Computer),Application uninstalling ..." | 
         Out-file -FilePath $Script:logFile -Encoding ascii -Append
    }
    catch{
        "$($Computer),ERROR Uninstalling App `
        - $($_.Exception.GetType().FullName - $_.Exception.Message)" | 
        Out-file -FilePath $Script:logFile -Encoding ascii -Append
    }
}

# TERMINATING INTERNET EXPLORER FUNCTION

Function TerminateProcess($computer, $processToTerminate){
Write-Host "$($Computer): TERMINATING IEXPLORE PROCESS..." -ForegroundColor Green
    try{
        $ErrorActionPrefference = "STOP"
        $Processes = (Get-WmiObject -Class Win32_Process -ComputerName $computer)
        foreach($process In $processes){
            if($process.Name -match $processToTerminate){
                $process.Terminate() | Out-Null
            }
        }
         "$($Computer),IE process terminating ..." | 
         Out-file -FilePath $Script:logFile -Encoding ascii -Append
    }
    catch{
        "$($Computer),ERROR Terminating IE 
        - $($_.Exception.GetType().FullName) - $($_.Exception.Message)" | 
        Out-file -FilePath $Script:logFile -Encoding ascii -Append
    }
}

# INSTALL APPLICATION FUNCTION

Function InstallApp($computer,$installString){
Write-Host "$($Computer): SILENTLY INSTALLING APPLICATION..." -ForegroundColor Green
    Try{
        $ErrorActionPrefference = "STOP"
        ([WMICLASS]"\\$computer\ROOT\CIMV2:Win32_Process").Create($InstallString) | 
        Out-Null
        "$($Computer),Aplication installing ..." | 
        Out-file -FilePath $Script:logFile -Encoding ascii -Append
    }
    catch{
        "$($Computer),ERROR Installing App 
        - $($_.Exception.GetType().FullName) - $($_.Exception.Message)" | 
        Out-file -FilePath $Script:logFile -Encoding ascii -Append
    }
}

# CONFIGURE APPLICATION

Function CopyConfigFile($computer,$path,$destination){
   Write-Host "$($Computer): COPYING CONFIGURATION FILES..." -ForegroundColor Green
        try {
               $ErrorActionPrefference = "STOP"
               Copy-Item -Path $path -Destination $destination -Force #| Out-Null
               "$($Computer),Copy Config File From: $path" | 
               Out-file -FilePath $Script:logFile -Encoding ascii -Append
            }

       catch{
             "$($Computer),ERROR Copying Config File - 
             $($_.Exception.GetType().FullName) - $($_.Exception.Message)" | 
             Out-file -FilePath $Script:logFile -Encoding ascii -Append
            }      
}

# FIND OUT AND INSTALL/LOG

Function FlashProduct($computer){
    $FlashProduct = (Get-WmiObject -Class "Win32_Product" -ComputerName $Computer | 
    ? {$_.Name -like "*Adobe*Flash*"})
    # We need info abut  $($FlashProduct.Name) and $($FlashProduct.IdentifyingNumber)
        
switch ("$($FlashProduct.Name)"){
 "Adobe Flash Player 19 ActiveX" {
	  Write-Host "$($computer): FP 19"
	  "$($Computer),Adobe Flash Player 19 Installed " | 
	  Out-file -FilePath $Script:logFile -Encoding ascii -Append
	  $row = ""|Select Name, Comment
	  $row.Name = $Computer.ToString()
	  $row.Comment  = "Adobe Flash Player 19 ActiveX"

	  $outputArray.Add($row)
    break
}
 "Adobe Flash Player 18 ActiveX" {
	  Write-Host "$($computer): FP 18"
	  "$($Computer),Adobe Flash Player 18 Installed " | 
	  Out-file -FilePath $Script:logFile -Encoding ascii -Append
	  $row = ""|Select Name, Comment
	  $row.Name = $Computer.ToString()
	  $row.Comment  = "Adobe Flash Player 18 ActiveX"

	  $outputArray.Add($row)
    break                                        
}
 "Adobe Flash Player 13 ActiveX" {
	  Write-Host "$($computer): Flash Player 13 - reinstalling..."

	  # COPY INSTALLATION FILE FUNCTION
	  CopyAppFile -computer $computer `
	  -path $Script:installFlashPlayerFile -destination "\\$Computer\c$\sw\FlashPlayer19"

	  # UNINSTALL APPLICATION FUNCTION
	  UnInstallApp -computer $computer -appName "Adobe Flash Player 13 ActiveX"

	  # TERMINATING INTERNET EXPLORER FUNCTION
	  TerminateProcess -computer $computer -processToTerminate "iexplore.exe"

	  # INSTALL APPLICATION FUNCTION
	  InstallApp -computer $computer `
	  -installString "msiexec.exe /i \\$Computer\c$\sw\FlashPlayer19\install_flash_player_19_active_x.msi /qn"

	  # CONFIGURE APPLICATION
	  CopyConfigFile -computer $computer `
	  -path "\\W12-gpn-c001\d$\GPOUpdates\Adobe\FlashPlayer19\mms.cfg"`
	  -destination "\\$Computer\c$\Windows\System32\Macromed\Flash"

	  $row = ""|Select Name, Comment
	  $row.Name = $Computer.ToString()
	  $row.Comment  = "Adobe Flash Player 19 ActiveX"

	  $outputArray.Add($row)
    break
	}
 }
}
# -----------------------------------|COMPARE AND LOOP|--------------------------------------------------

$newQueryCollection = (Compare-Object -ReferenceObject $PCcollection -DifferenceObject $reachedPCs |
Where-Object -FilterScript {$_.SideIndicator -eq "<="} |Select-Object -ExpandProperty InputObject | 
Sort InputObject)
 $pcCount = 0
foreach ($Computer In $newQueryCollection){
If (Test-Connection -ComputerName $Computer -ea silentlycontinue -Count 1) {
    "$($Computer),Ping Successful" |Out-file -FilePath $Script:logFile -Encoding ascii -Append 
    Write-Host "$($pcCount). $($Computer) - Ping Successful" -ForegroundColor Green
 try {
     (Get-WmiObject -computerName $Computer Win32_Service `
     -Filter "Name='LanmanServer'" -ErrorAction Stop).StartService() | 
      Out-Null
                
      FlashProduct -computer $computer

    }
 catch{
      "$($Computer),Server Service Error: $($_.Exception.GetType().FullName) 
      - $($_.Exception.Message)" |
      Out-file -FilePath $Script:logFile -Encoding ascii -Append
      Write-Host "$($Computer) - Server Service Error" -ForegroundColor Yellow
    }
 }
else{
     "$($Computer),Ping Failed" | Out-file -FilePath $Script:logFile -Encoding ascii -Append 
     Write-Host "$($pcCount). $($Computer) - Ping Failed" -ForegroundColor Red
    }
 $pcCount ++    
}
$outputArray | Export-Csv -Path $csvFilePath -NoTypeInformation -Append
Write-Host "Script finished execution" -ForegroundColor Red

}

# LOG FUNCTION

Function View-LogFile($logPath){

Import-Csv -Delimiter "," -Path $logPath -Header "Name", "Comment" |
Select -Property Name, Comment | Sort -Property Name, Comment -Unique | 
Out-GridView -Title "Flash Player Update Log"

}

# ---------------------------|END OF FUNCTIONS|-------------------------------------------------------

switch ($PsCmdlet.ParameterSetName) 
    { 
    "UpdateSoftware" {Update-Software $ouName;break} 
    "ViewLogFile"  {View-LogFile $logPath;break} 
}

The output of the Update-FlashPlayerApp.ps1 script is shown in the figure 02.

UpdateFlashPlayerAppFigure 02: Displays the output of Update-FlashPlayerApp.ps1 script

This script could be found in the download section – under PowerShell folder.


 

DiskPart GUI – Update

Almost two years ago I wanted to create a DiskPart graphic user interface (GUI) tool for all of my colleagues that do not like command line as much as I do. I used PowerShell to build a DISKPART script to automatically format USB drives as bootable. This script has been posted in a blog with title “DiskPart GUI PowerShell”  and since then it has been downloaded more than 1000 times.

Today, in this blog, I give you an updated script that I hope will be a nice addition to your existing PowerShell scripts and tools, particularly for your Bootable Windows PE USB Drives.

The start page is shown in the picture 1; on the left side you can view the information about detected computer’s drives and on the right side you can select one – and just one – option from a set of partition alternatives.

DiskPartGUI_StartPicture 1: Format Disk Utility start page

To format a drive with selected partition style, please select a drive and then select one partition option as shown in the picture 2. In my example, I selected drive 2 and recommended UEFI\GPT partition to format my external USB drive.

DiskPartGUI_SelectDrivePicture 2: Select disk drive and partition layout MBR or GPT

You have to click on Format Disk button and confirm you choice to start DiskPart and formatting process (as shown in the picture below).

DiskPartGUI_ConfirmSelectionPicture 3: confirm drive selection and partition style

Finally, the second text box becomes visible on the left side and displays the result of all actions produced by DiskPart application.

DiskPartGUI_FormatDrivePicture 4: the second rich text box displays the result of DiskPart actions

This script could be found in the downloaded section – folder Application. Hopefully it will reach thousand downloads just as its predecessor.