How to Write an Auto-Updater (for Adobe Flash)

In what is sure to be one of my least read posts, I'm going to share with you how to write an auto-updater for upgrading Adobe Flash.

But why on Earth would you want to write your own (other than because your boss told you to cough)? It comes with its own updater! Or you could use a tool such as PDQ Deploy or SCCM to deploy! Well if you have limited internet bandwidth, you probably don't want everyone downloading the same patch all day. Also, tools like PDQ Deploy take time to set up and configure a rollout schedule and I don't have time for that. Plus it's fun writing your own updater and it can be adapted to other software as well - not to mention it's completely free!


We will be building an updater using AutoIt to create an EXE file that queries a file share for the latest version of Adobe Flash. Using Group Policy and Active Directory, we will be deploying the EXE to client machines and creating a scheduled task to run on startup.

If I go too fast through this setup and you have questions, feel free to leave them in the comments!

Preparing the File Server

The first step is to prepare a file share to host your files. I have chosen to use a very basic Linux server running Samba to host the files.

But why? We are actually going to run the updater as the NT AUTHORITY\SYSTEM account. We can configure public share in Samba to avoid any authentication issues.


STEP 1 - Install Ubuntu

Download Ubuntu 14.04 and deploy. This tutorial assumes you have a working knowledge of how to install an OS so I won't cover that. For system specs, I am using 512mb and a dual core CPU to serve ~8000 clients machines and have no performance issues. Don't forget to secure your linux machine if you want to be safe.


STEP 2 - Install Samba

To grab the latest packages, run sudo apt-get update and then sudo apt-get install samba


STEP 3 - Configure Samba

Now we need to configure the share. Create a folder - for my example, I navigated to the root of the drive and did mkdir share. I will be using /share as my directory in this example.

We'll need to edit the Samba conf file so type nano /etc/samba/smb.conf to open up the config file. Comment out the below 5 lines by prepending with a # or ;:

# obey pam restrictions = yes
# unix password sync = yes
# passwd program = /usr/bin/passwd %u
# passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
# pam password change = yes

Also comment out the two printer shares at the bottom of the file:

;[printers]
;   comment = All Printers
;   browseable = no
;   path = /var/spool/samba
;   printable = yes
;   guest ok = no
;   read only = yes
;   create mask = 0700

;[print$]
;   comment = Printer Drivers
;   path = /var/lib/samba/printers
;   browseable = yes
;   read only = yes
;   guest ok = no

Lastly, we need to add these lines to the very bottom of the config - if you didn't use /share like me, make sure to adjust:

[share]
path = /share
available = yes
force user = nobody
read only = no
create mask = 0755
directory mask = 0755
guest ok = yes
browseable = yes
public = yes
writable = yes
oplocks = False
level2 oplocks = False

Save and exit.


STEP 4 - Restart the Service

Restart the Samba service by running sudo service smbd restart

Populate the File Share

Now that we have the share set up, we now need to get the files and folders set up. At this point, you should be able to connect to it in Windows. You should be able to access it by going to \\servername\share in Windows Explorer. If not, make sure the firewall is open to Samba traffic.

STEP 5 - Create the files/folders

We need to set up a folder for each version of flash installers to go in. The folder name should be set to the version number of flash, minus the decimals. At the time of this writing, the latest version of Flash is 21.0.0.197 so you would create a folder named 2100197.

You also need to create a file named latestflash.txt. In the text file, you will simply write the most recent version of flash without the decimals - just like you did the folder name so they should match

This is what my directory looks like:
Flash Directory

And my latestflash.txt:
latestflash.txt


STEP 6 - Download Flash

Download the .MSI installers from the Flash Player distribution website - you'll need to register with Adobe to be officially compliant with their licensing.

Save the installers to your appropriately numbered folder. For instance when downloading version 21.0.0.197, put the two .MSI's in the 2100197 folder. Then rename the files so that they do not have the version in the .MSI filename like so:
flashinstallers

Write the Auto-Updater

The time you have been waiting for has finally arrived!


STEP 7 - Download and Install AutoIt

You can download AutoIt here. With all the rage these days about Powershell, you may not have heard about AutoIt. It's basically a scripting language that is super easy to write and compiles to an .EXE - and it's free.


STEP 8 - Copy and Paste

Open up the SciTE editor in AutoIt and copy and paste the below. I've commented the lines so you understand what is going on. Don't forget to define the 3 variables at the top of the file! Apologies in advance that Google's code highlighting doesn't support AutoIt :(

#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=updateclient.exe
#AutoIt3Wrapper_UseUpx=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <FileConstants.au3>

; DEFINE THESE VARIABLES - NOTHING ELSE NEEDS EDITED
$username = "Administrator" ; replace this with your local user account - should be a local admin
$password = "mypassword" ; password for your local user account
$fileshare = "\\server\share\" ; this is the file share you set up with the flash files

;fetch current version information
$cFirefox = GetFirefox()
$cIE = GetIE()

While 1
	Sleep(60000) ; wait 60 seconds to start
	$lFlash = GetLatest()
   If $lFlash > $cFirefox Then
	  $iResult = RunAsWait($username, @ComputerName, $password, 0, "c:\windows\system32\msiexec.exe /i " & $fileshare & $lFlash & "\install_flash_player_plugin.msi ALLUSERS=1 /qn /norestart RebootYesNo=No") ; install flash for firefox
	  $cFirefox = GetFirefox() ; update variable with just installed version
   Else
	  ;Do nothing
   EndIf
   If $lFlash > $cIE Then
	  $iResult = RunAsWait($username, @ComputerName, $password, 0, "c:\windows\system32\msiexec.exe /i " & $fileshare & $lFlash & "\install_flash_player_active_x.msi ALLUSERS=1 /qn /norestart RebootYesNo=No") ; install flash for IE
	  $cIE = GetIE() ; update variable with just installed version
   Else
	  ;Do nothing
   EndIf
   Sleep(3600000) ; pause and check again in an hour
WEnd

Func GetLatest()
    ; read the text file to find latest version of flash
    Local Const $lFlashFile = $fileshare & "latestflash.txt"
    Local $iFileExists = FileExists($lFlashFile)
   If $iFileExists Then
	  $pFileOpen = FileOpen($lFlashFile, $FO_READ)
	  $line = FileReadLine($pFileOpen)
	  If @error = -1 Then Return "0"
	  FileClose($pFileOpen) ; this line is very important - if you don't have it, you'll kill your file server
   Else
	  Return "0"
   EndIf
   Return $line
EndFunc

Func GetFirefox()
$fileFF = FileFindFirstFile("C:\Windows\System32\Macromed\Flash\*Plugin.exe")
If @error Then Return "0"
$sFileName = FileFindNextFile($fileFF)
$fullFileName = "C:\Windows\System32\Macromed\Flash\" & $sFileName
$fFFv = FileGetVersion($fullFileName,"FileVersion") ; find file version of flash
$fFFv = StringReplace($fFFv,",","") ; remove all commas from version - no idea why commas ever got used in some versions
$fFFv = StringReplace($fFFv,".","") ; remove all periods from version
FileClose($fileFF)
Return $fFFv
EndFunc

Func GetIE()
$fileIE = FileFindFirstFile("C:\Windows\System32\Macromed\Flash\*ActiveX.exe")
If @error Then Return "0"
$sFileName = FileFindNextFile($fileIE)
$fullFileName = "C:\Windows\System32\Macromed\Flash\" & $sFileName
$fIEv = FileGetVersion($fullFileName,"FileVersion")
$fIEv = StringReplace($fIEv,",","")
$fIEv = StringReplace($fIEv,".","")
FileClose($fileIE)
Return $fIEv
EndFunc

**STEP 9 - Compile**
Under Tools, click on Compile. Depending on whether you got the "Lite" version of AutoIt or Full version, you may be prompted with a box with several compilation options (like icon, whether to compress or not, etc). Eventually you should end up with a .EXE file named `updateclient.exe`. Put this on your file share.
**STEP 10 - Test!**
I'll admit right away that, while I've been using this code for almost a year in production, I removed lot of debugging code. Before we deploy it on a wide-scale, please give it a test on a few machines - it never hurts to take the extra time to make sure everything is good to go!
## Deploy **STEP 11 - Deploy via GPO**
The last step is to deploy via GPO. First, create a new GPO and apply it to the computers you want to receive the updater. In the GPO, we need to adjust two settings.

The first setting is to copy the updateclient.exe from our file share to the C:\Temp folder of each machine (or any other folder that makes sense to you).

The second setting is to create a scheduled task. You will want to run the task as the NT AUTHORITY\SYSTEM account, with a trigger to run on computer startup, and the action to be running C:\Temp\updateclient.exe. See below:
schtask


You're all finished!

Updating Flash

When a new update for flash comes out, simply download the .MSI files like you did in step 6. When you are ready to have clients pull the update, simply change the version/folder name you have listed in latestflash.txt to the new version and you'll see clients immediately start downloading and installing.

If everything is working, you should now be able to update all computers in your network within an hour of a Flash update coming out, all via your local LAN network!

comments powered by Disqus