#requires -version 3.0 #### Check for updates #### Version 1.36 #### Last updated 2017-02-07 #### The canonical version of this script is at http://tallguyracing.com/wiki/doku.php?id=powershell_check_for_updates $appsToCheck = @{ 'Dummy' = 'Dummy' ; 'ThisScript' = '1.31' ; 'Anki' = '2.0.36' ; 'ConEmu' = '160619' ; 'Paint.NET' = '4.0.9' # ; 'Rockbox' = '3.13' # ; 'DokuWiki' = '2013-05-10' ; 'Notepad++' = '6.9.2' # Hopefully, this can be reverted to a fully automatic check in the future. # ; 'Notepad++' = 'Notepad++\notepad++.exe' ; 'GIMP' = 'GIMP 2\bin\gimp-2.8.exe' ; '7zip' = '7-Zip\7z.exe' ; 'WinMerge' = 'WinMerge\WinMergeU.exe' # ; 'Foobar2000' = 'foobar2000\foobar2000.exe' ; 'Fiddler' = 'Fiddler2\fiddler.exe' ; 'Process Explorer' = 'C:\tools\sysinternals\procexp.exe' ; 'Process Monitor' = 'C:\tools\sysinternals\procmon.exe' # ; 'VLC' = 'VideoLAN\VLC\vlc.exe' ; 'FileZilla' = 'FileZilla FTP Client\filezilla.exe' # ; 'ImageMagick' = 'ImageMagick\magick.exe' # ; 'TortoiseSVN' = 'TortoiseSVN\bin\TortoiseSVN.dll' ; 'WinDirStat' = 'WinDirStat\windirstat.exe' # ; 'LibreOffice' = 'LibreOffice 5\program\soffice.exe' # ; 'VirtualBox' = 'Oracle\VirtualBox\VBoxSVC.exe' # ; 'Tixati' = 'tixati\tixati.exe' # ; 'VeraCrypt' = 'VeraCrypt\VeraCrypt.exe' # ; 'IrfanView' = 'IrfanView\i_view32.exe' } function WebRequest ($url) { [net.httpwebrequest]$httpwebrequest = [net.webrequest]::create($url) [net.httpWebResponse]$httpwebresponse = $httpwebrequest.getResponse() if (!$httpwebresponse) { return $null } $reader = new-object IO.StreamReader($httpwebresponse.getResponseStream()) $WSResponse = $reader.ReadToEnd() $reader.Close() return $WSResponse } function WebRequest ($url) { [net.httpwebrequest]$httpwebrequest = [net.webrequest]::create($url) [net.httpWebResponse]$httpwebresponse = $httpwebrequest.getResponse() if (!$httpwebresponse) { return $null } $reader = new-object IO.StreamReader($httpwebresponse.getResponseStream()) $WSResponse = $reader.ReadToEnd() $reader.Close() return $WSResponse } function GetVersionNumberFromWeb ($appName, $url, $regexPattern) { $response = WebRequest $url if (!$response) { Write-Host "FAILED: ${appName}: Could not get the web page." -ForegroundColor Red return } Out-File -filepath (Join-path $env:temp "$appName.html") -inputobject $response if ($regexPattern.EndsWith('/s')) { # Use a bit of a hack to get singleline mode. $regexPattern = $regexPattern.Substring(0, $regexPattern.Length - 2) $response = $response.Replace("`n", " ") } $versionNumberMatches = ([regex]$regexPattern).matches($response) if ($versionNumberMatches.Count -eq 0) { Write-Host "FAILED: ${appName}: Could not get version number from the web page. Nothing matched the regex." -ForegroundColor Red return } if ($versionNumberMatches.Count -ne 1) { Write-Host "FAILED: ${appName}: Could not get version number from the web page. The regex had more than one match." -ForegroundColor Red return } if (! $versionNumberMatches[0].Success) { Write-Host "FAILED: ${appName}: Could not get version number from the web page. The regex match was not successful." -ForegroundColor Red return } if (! $versionNumberMatches[0].Groups["versionNumber"].Success) { Write-Host "FAILED: ${appName}: Could not get version number from the web page. The regex group was not successful." -ForegroundColor Red return } $latestVersionNumber = $versionNumberMatches[0].Groups["versionNumber"].Value Write-Host "${appName}: The latest version number is $LatestVersionNumber." return $latestVersionNumber } function CheckLocalFile ($appName, $url, $regexPattern, $localFilename, $extraFormatting) { if (Test-Path $localFilename) { $fullLocalFilename = $localFilename } elseif (Test-Path "C:\Program Files (x86)\$localFilename") { $fullLocalFilename = "C:\Program Files (x86)\$localFilename" } elseif (Test-Path "C:\Program Files\$localFilename") { $fullLocalFilename = "C:\Program Files\$localFilename" } else { Write-Host "FAILED: The filename ${localFilename} or any of its variants does not exist." -ForegroundColor Red return } $appInfo = Get-Command $fullLocalFilename $currentVersionNumber = $appInfo.FileVersionInfo.ProductVersion if ($extraFormatting.Contains(';CommaToFullStop;')) { $currentVersionNumber = $currentVersionNumber.Replace(',', '.') } if ($extraFormatting.Contains(';RemoveSpaces;')) { $currentVersionNumber = $currentVersionNumber.Replace(' ', '') } if ($extraFormatting.Contains(';TrimTrailingZero;') -and $currentVersionNumber.EndsWith('0')) { $currentVersionNumber = $currentVersionNumber.Substring(0, $currentVersionNumber.Length - 1) } if ($extraFormatting.Contains(';TrimTrailingDotZero;') -and $currentVersionNumber.EndsWith('.0')) { $currentVersionNumber = $currentVersionNumber.Substring(0, $currentVersionNumber.Length - 2) } while ($extraFormatting.Contains(';TrimTrailingDotZeros;') -and $currentVersionNumber.EndsWith('.0')) { $currentVersionNumber = $currentVersionNumber.Substring(0, $currentVersionNumber.Length - 2) } if ($extraFormatting.Contains(';FirstThreeDigitsOnly;')) { if (! ($currentVersionNumber -match "\d+(?:\.\d+){2}")) { Write-Host "FAILED: ${appName}: Could not get the first three digits of the version number from '$currentVersionNumber'." -ForegroundColor Red return } $currentVersionNumber = $Matches.Values } CheckCurrentVersionNumber $appName $url $regexPattern $currentVersionNumber } function CheckCurrentVersionNumber ($appName, $url, $regexPattern, $currentVersionNumber) { $latestVersionNumber = GetVersionNumberFromWeb $appName $url $regexPattern if (! $latestVersionNumber) { return } Write-Host "${appName}: The current version number is $currentVersionNumber." if ($currentVersionNumber -ne $latestVersionNumber) { Write-Host "${appName}: Update required!" -ForegroundColor Green } else { Write-Host "${appName}: No update required." } } function CheckAppCurrentVersionNumber ($appName) { switch ($appName) { 'Dummy' { } #### Semi-automatic checks #### 'ThisScript' { CheckCurrentVersionNumber 'ThisScript' 'http://tallguyracing.com/wiki/doku.php?id=powershell_check_for_updates' ` '>#### Version (?<versionNumber>\d+\.\d+)<' ` $appsToCheck['ThisScript'] } 'Anki' { CheckCurrentVersionNumber 'Anki' 'http://ankisrs.net/' ` '>Download Anki for Windows Vista/7/8/10 \((?<versionNumber>\d+(?:\.\d+){2})\)<' ` $appsToCheck['Anki'] } 'ConEmu' { CheckCurrentVersionNumber 'ConEmu' 'http://conemu.github.io/version.ini' ` '\[ConEmu_Preview_2\]\s*version=(?<versionNumber>\w+)' ` $appsToCheck['ConEmu'] } 'Paint.NET' { CheckCurrentVersionNumber 'Paint.NET' 'http://www.getpaint.net/index.html' ` '>paint\.net\s*(?<versionNumber>\d+(?:\.\d+){2})<' ` $appsToCheck['Paint.NET'] } 'Rockbox' { CheckCurrentVersionNumber 'Rockbox' 'http://www.rockbox.org/download/' ` '<h1>Rockbox (?<versionNumber>\d+(?:\.\d+){1,2}) Download</h1>' ` $appsToCheck['Rockbox'] } 'DokuWiki' { CheckCurrentVersionNumber 'DokuWiki' 'http://download.dokuwiki.org/' ` '<a href="src/dokuwiki/dokuwiki-stable\.tgz">\(direct link\)</a>\s*<span class="hint">(?<versionNumber>\d{4}-\d{2}-\d{2}).+?</span>' ` $appsToCheck['DokuWiki'] } 'Notepad++' { CheckCurrentVersionNumber 'Notepad++' 'http://notepad-plus-plus.org/' ` '>Current Version:\s*(?:<\w+>\s*)*(?<versionNumber>\d+(?:\.\d+){1,3})<' ` $appsToCheck['Notepad++'] } 'Inkscape' { CheckCurrentVersionNumber 'Inkscape' 'http://inkscape.org/en/download/windows' ` '>Latest stable version: Inkscape ?(?<versionNumber>\d+(?:\.\d+){1,2})<' ` $appsToCheck['Inkscape'] } 'Hugin' { CheckCurrentVersionNumber 'Hugin' 'http://sourceforge.net/projects/hugin/' ` '>hugin-(?<versionNumber>\d+(?:\.\d+){2})\.tar\.bz2<' ` $appsToCheck['Hugin'] } 'Stellarium' { CheckCurrentVersionNumber 'Stellarium' 'http://stellarium.org/' ` '>latest version is (?<versionNumber>\d+(?:\.\d+){2})<' ` $appsToCheck['Stellarium'] } 'Gmvault' { CheckCurrentVersionNumber 'Gmvault' 'http://gmvault.org/' ` 'Download\s+Gmvault<small>\s*\((?<versionNumber>\d+(?:\.\d+){1,2})\s*\)\s*</small>' ` $appsToCheck['Gmvault'] } #### Fully-automatic checks #### 'GIMP' { CheckLocalFile 'GIMP' 'http://www.gimp.org/downloads/' ` '>The current stable release of GIMP is <(b|strong)>(?<versionNumber>\d+(?:\.\d+){2})<\/(b|strong)>' ` $appsToCheck['GIMP'] '' } '7zip' { CheckLocalFile '7zip' 'http://www.7-zip.org/' ` 'Download 7-Zip (?<versionNumber>\d+(?:\.\d+){1,2}) \(\d+-\d+-\d+\) for Windows' ` $appsToCheck['7zip'] '' } 'WinMerge' { CheckLocalFile 'WinMerge' 'http://winmerge.org/' ` 'href="http://downloads.sourceforge.net/winmerge/WinMerge-(?<versionNumber>\d+(?:\.\d+){2})-Setup.exe"' ` $appsToCheck['WinMerge'] '' } 'Foobar2000' { CheckLocalFile 'Foobar2000' 'http://www.foobar2000.org/download' ` 'href="/getfile/[^/]+/foobar2000_v(?<versionNumber>\d+(?:\.\d+){1,2}).exe">foobar2000 v\d+(?:\.\d+){1,2}' ` $appsToCheck['Foobar2000'] ` ';TrimTrailingDotZero;' } 'Fiddler' { CheckLocalFile 'Fiddler' 'https://chocolatey.org/packages/fiddler4' ` '<title>\s*Chocolatey\s+Gallery\s*\|\s*Fiddler\s*(?<versionNumber>\d+(?:\.\d+){2})' ` $appsToCheck['Fiddler'] ` ';FirstThreeDigitsOnly;' } 'Process Explorer' { CheckLocalFile 'Process Explorer' 'http://technet.microsoft.com/en-US/sysinternals/bb896653' ` '<h1>Process Explorer v(?<versionNumber>\d+\.\d+)</h1>' ` $appsToCheck['Process Explorer'] '' } 'Process Monitor' { CheckLocalFile 'Process Monitor' 'http://technet.microsoft.com/en-US/sysinternals/bb896645' ` '<h1>Process Monitor v(?<versionNumber>\d+\.\d+)</h1>' ` $appsToCheck['Process Monitor'] ';TrimTrailingZero;' } # Next time the version changes, try using this rather than the Semi-automatic check. # 'Notepad++' # { # CheckLocalFile 'Notepad++' 'http://notepad-plus-plus.org/download/' ` # '<title>Notepad\+\+ v(?<versionNumber>\d+(?:\.\d+){1,2}) - Current Version</title>' ` # $appsToCheck['Notepad++'] '' # } 'VLC' { CheckLocalFile 'VLC' 'http://videolan.org/vlc/' ` 'href=''//get.videolan.org/vlc/(?:\d+(?:\.\d+){2})/win32/vlc-(?<versionNumber>\d+(?:\.\d+){2})-win32.exe''>' ` $appsToCheck['VLC'] ` ';CommaToFullStop;TrimTrailingDotZero;' } 'FileZilla' { CheckLocalFile 'FileZilla' 'http://filezilla-project.org/download.php?type=client' ` '>The latest stable version of FileZilla Client is (?<versionNumber>\d+(?:\.\d+){2,3})<' ` $appsToCheck['FileZilla'] ` ';CommaToFullStop;RemoveSpaces;TrimTrailingDotZero;' } 'ImageMagick' { CheckLocalFile 'ImageMagick' 'http://www.imagemagick.org/script/binary-releases.php' ` '>ImageMagick-(?<versionNumber>\d+(?:\.\d+){2})(?:-\d+)?-Q16-x64-dll\.exe<' ` $appsToCheck['ImageMagick'] '' } 'TortoiseSVN' { CheckLocalFile 'TortoiseSVN' 'http://tortoisesvn.net/downloads.html' ` '>The current version is (?<versionNumber>\d+(?:\.\d+){2})<' ` $appsToCheck['TortoiseSVN'] ` ';FirstThreeDigitsOnly;' } 'WinDirStat' { CheckLocalFile 'WinDirStat' 'http://windirstat.info/' ` '>Latest version: (?<versionNumber>\d+(?:\.\d+){2})<' ` $appsToCheck['WinDirStat'] ` ';FirstThreeDigitsOnly;' } 'WinDirStat' { CheckLocalFile 'WinDirStat' 'http://windirstat.info/' ` '>Latest version: (?<versionNumber>\d+(?:\.\d+){2})<' ` $appsToCheck['WinDirStat'] ` ';FirstThreeDigitsOnly;' } 'Expresso' { CheckLocalFile 'Expresso' 'http://www.ultrapico.com/ExpressoDownload.htm' ` '\(Version (?<versionNumber>\d+(?:\.\d+){2}) - ' ` $appsToCheck['Expresso'] ` ';FirstThreeDigitsOnly;' } 'LibreOffice' { CheckLocalFile 'LibreOffice' 'http://www.libreoffice.org/download/libreoffice-fresh/' ` '>Download Version (?<versionNumber>\d+(?:\.\d+){2})<' ` $appsToCheck['LibreOffice'] ` ';FirstThreeDigitsOnly;' } 'VirtualBox' { CheckLocalFile 'VirtualBox' 'http://www.virtualbox.org/wiki/Downloads' ` '\>\s*VirtualBox\s*(?<versionNumber>\d+(?:\.\d+){1,2})\s*platform\s*packages\s*\<' ` $appsToCheck['VirtualBox'] ` ';FirstThreeDigitsOnly;' } 'Tixati' { CheckLocalFile 'Tixati' 'http://www.tixati.com/download/' ` '>Download Tixati v(?<versionNumber>\d+\.\d+)<' ` $appsToCheck['Tixati'] '' } 'VeraCrypt' { CheckLocalFile 'VeraCrypt' 'https://veracrypt.codeplex.com/wikipage?title=Downloads' ` '>Latest Stable Release - (?<versionNumber>\d+\.\d+)' ` $appsToCheck['VeraCrypt'] '' } 'IrfanView' { CheckLocalFile 'IfranView' 'http://www.irfanview.com/checkversion.php' ` 'Current IrfanView version is: <b>(?<versionNumber>\d+\.\d+)' ` $appsToCheck['IrfanView'] '' } 'Deluge' { CheckLocalFile 'Deluge' 'http://deluge-torrent.org/' ` '\>\s*(?<versionNumber>\d+(?:\.\d+)+)\s*\<' ` $appsToCheck['Deluge'] ` ';FirstThreeDigitsOnly;' } default { Write-Host "FAILED: ${appName}: Unknown app." -ForegroundColor Red } } } cls foreach ($appName in $AppsToCheck.Keys) { CheckAppCurrentVersionNumber ($appName) } #CheckAppCurrentVersionNumber 'Fiddler'