Automating Download of Google Chrome

If you manage multiple computers, you will want to ensure that Google Chrome is always up to date. This important as Google contains flash built in by default as well as to patch any security vulnerabilities in Chrome. In order to accomplish this, historically you had two options:
1. Allow all your computers to auto – update. This works, but all your computers are downloading approximately 50 MB every time it updates. If you are on a slow connection, or you have lots of computers, this will be an issue.
2. Manually download the Google Chrome for Business msi file and deploy it via Microsoft System Center Configuration manager or group policy

You may also have a situation where neither of these are possible/desirable. May I present a 3rd option:
3. Have a scheduled task (or perhaps an Orchestrator or SMA runbook) check the latest available version and download it if there is a newer version available. Use another scheduled task on each computer to install the update from your central download cache if it is newer than the version installed.

To start, lets check the stable channel feed for Chrome:

$uriChromeReleaseFeed = 'http://googlechromereleases.blogspot.ca/search/label/Stable%20updates'
Function Get-LatestChromeVersion{
    Param([uri]$ChromeReleaseFeed)
    $strReleaseFeed = Invoke-webRequest $ChromeReleaseFeed
    $strReleaseFeed.AllElements | Where-object class -eq 'post-body entry-content' | Where-Object{$_.InnerText -match 'Windows'} | Select-Object{$_.InnerText} | ForEach{[version](($_ | Select-string -allmatches '(\d{1,4}\.){3}(\d{1,4})').matches | Select-Object -first 1).value} | Sort-Object -Descending | Select-Object -first 1
}
[version](Get-LatestChromeVersion -ChromeReleaseFeed $uriChromeReleaseFeed)

Major  Minor  Build  Revision
-----  -----  -----  --------
44     0      2403   107     

So, we now know the latest stable version of Chrome.

Although browsing websites with Powershell is cool, this will run considerably quicker and also be more reliable if we actually use the RSS feed instead of the blog as our source.

This only requires minor modifications and drastically increases the speed of the code:

$uriChromeReleaseRSS = 'http://feeds.feedburner.com/GoogleChromeReleases'

Function Get-LatestChromeVersionViaRSS{
    Param([uri]$ChromeReleaseFeed)
    [xml]$strReleaseFeed = Invoke-webRequest $ChromeReleaseFeed
    ($strReleaseFeed.feed.entry | Where-object{$_.title.'#text' -match 'Stable'}).content | Select-Object{$_.'#text'} | Where-Object{$_ -match 'Windows'} | ForEach{[version](($_ | Select-string -allmatches '(\d{1,4}\.){3}(\d{1,4})').matches | select-object -first 1 -expandProperty Value)} | Sort-Object -Descending | Select-Object -first 1
}

Major  Minor  Build  Revision
-----  -----  -----  --------
44     0      2403   107 

Next, lets download it:

$uriNewChromeURL = 'https://dl.google.com/dl/chrome/install/googlechromestandaloneenterprise64.msi'
$strChromeDownloadFolder = 'C:\Temp\Auto-UpdateApps'
$strChromeSaveAsName = 'googlechromestandaloneenterprise.msi'

Function Download-ChromeMSI{
    Param([uri]$ChromeDownloadPath,[string]$ChromeDownloadFolder,[string]$ChromeSaveAsName)
    If(!(Test-Path $ChromeDownloadFolder)){
        mkdir $ChromeDownloadFolder
    }
    $objWebRequest = Invoke-WebRequest $ChromeDownloadPath -outfile (Join-Path $ChromeDownloadFolder -childpath $ChromeSaveAsName)
}
 Download-ChromeMSI -ChromeDownloadPath $uriNewChromeURL -ChromeDownloadFolder $strChromeDownloadFolder -ChromeSaveAsName $strChromeSaveAsName

This nicely downloads the file to my ‘C:\Temp\Auto-AupdateApps’ folder

This works fine when this is only run one time. The next time we run our script, we’ll want to check which version we have downloaded. Unfortunately, Google decided that the MSI version property shouldn’t match the version of Chrome we are installing. Instead, they have added it to the Comments extended attribute of the MSI file.

Function Get-FileProperties{
    Param([io.fileinfo]$FilePath)
    $objFileProps = Get-item $filepath | Get-ItemProperty | select *

    #Get required Comments extended attribute
    $objShell = New-object -ComObject shell.Application
    $objShellFolder = $objShell.NameSpace((get-item $filepath).Directory.FullName)
    $objShellFile = $objShellFolder.ParseName((get-item $filepath).Name)

    $strComments = $objShellfolder.GetDetailsOf($objshellfile,24)
    $Version = [version]($strComments | Select-string -allmatches '(\d{1,4}\.){3}(\d{1,4})').matches.Value
    $objShellFile = $null
    $objShellFolder = $null
    $objShell = $null
    Add-Member -InputObject $objFileProps -MemberType NoteProperty -Name Version -Value $Version
    Return $objFileProps
}

Here we’ve taken all the file properties and added a filtered version of extended attribute #24 to the list and gave it the name “version”

Putting it all together:

#*******************************************
$LatestAvailableVerison = [version](Get-LatestChromeVersionViaRSS -ChromeReleaseFeed $uriChromeReleaseRSS)

#Test File Versions
$boolNewestDownloaded = $false
ForEach($objfile in (Get-Item $strChromeDownloadFolder).GetFiles() | Where-object -Property Extension -match 'msi'){
    $fileVersion = [version](Get-FileProperties -FilePath $objFile.FullName).Version
    If($fileVersion -ge $LatestAvailableVerison){
        $boolNewestDownloaded = $true
    }
}

#If latest version is not downloaded
If(!($boolNewestDownloaded)){
    Download-ChromeMSI -ChromeDownloadPath $uriNewChromeURL -ChromeDownloadFolder $strChromeDownloadFolder -ChromeSaveAsName $strChromeSaveAsName
}else{
    Write-Output "Latest Version already downloaded"
}

Hopefully this provides some pointers into how we can fully automate a process you would otherwise have to tackle monthly.

Please note however that this example has some flaws as presented.
1. The download function doesn’t check if the file exists. You’ll want to fix that
2. The script doesn’t watch for changes in Google’s methodology of deploying chrome
For Example:
– If the blog feed changes format, this will break.
– If the download path changes, this will break
– If the version number location changes in the blog or in the file, this will break.
These are not insurmountable issues…maybe you want to include an alerting system when these points fail….the sky is the limit!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s