VideoLan Player (vlc) update status

When I launch the Videolan Player (vlc), I get the following update prompt whenever a new version is available.

I was actually using the following detection based on the target link of the “last” version redirect:

$foundLatestOnlineVersion = $latestOnlineVer  = $null
$HT = @{
 Uri = 'http://download.videolan.org/pub/videolan/vlc/last' ;
 UseBasicParsing = $true ;
 ErrorAction = 'SilentlyContinue'
}
if ( 
 ($latestOnlineVer = (Invoke-WebRequest @HT).Links | 
 Where href -match '\.sha256$')
) { 
 $foundLatestOnlineVersion = (
  [regex]'vlc-(?<version>\d{1,2}\.\d{1,2}\.\d{1,2}(\.\d{1,2})?)\..*\.sha256'
 ).Match($latestOnlineVer.href).Groups | Select -Last 1 -Expand Value
 Write-Verbose -Message "Found latest VLC version online: $foundLatestOnlineVersion" -Verbose
}

As you can see my version detection approach fails. It shows 2.2.5.1 instead of 2.2.6 šŸ˜¦

I started looking around what vlc does to check when a new version has been released.

Fortunately, I found their updater source code on this page: https://github.com/videolan/vlc/blob/master/src/misc/update.c

The interesting line is where they show how they build the target status url based on the platform.

define UPDATE_VLC_STATUS_URL "http://update.videolan.org/vlc/status" UPDATE_OS_SUFFIX

I tried to do the same in PowerShell but the reply from their web server is an octet-stream

I can quickly convert the bytes array into something meaningful like this:

$HT.Uri = 'http://update.videolan.org/vlc/status-win-x64'
[char[]][int[]](Invoke-WebRequest @HT).Content  -join ''

Yeah, you can do this, it’s quick and dirty šŸ˜›

But, it would be nice to get an object returned instead of a multi line string.
I’ll use the char 10 (a line feed) as a separator.
The first line is the version, the second line the URL, the third line the title and the rest is the full text.

(Invoke-WebRequest @HT).Content | 
ForEach-Object -Begin {
 $Version = $URI = $Title = $null
 $i = 0
 $sb  = New-Object System.Text.StringBuilder
} -Process {
 if ($_ -eq 10) {
  $i++
  Switch ($i) {
   1 {
    $Version = $sb.ToString() ;
    break ;
   }
   2 {
    $URI = $sb.ToString() ;
    break ;
   }
   3 {
    $Title = $sb.ToString() ;
    break ;
   }
   4 {
    $Text = $sb.ToString() ;
    break ;
   }
   default {}
  }

  # reset the string builder
  $sb  = New-Object System.Text.StringBuilder
 } else {
  $null = $sb.Append([char][int]$_)
 }
} -End {
 [PSCustomObject]@{
  Version = [version]$Version ;
  URI = [uri]$URI ;
  Title = $Title ;
  Text = $Text ;
 }
} | fl

Let me quickly explain this approach. Btw, if you’ve got a better one please share it šŸ™‚
I use the Begin block of the Foreach-Object cmdet to initialize a counter and an empty string builder.
Inside the Process block, I test if the encountered byte is char 10, the line feed separator.
If it is, it means I reached a milestone. I increment the counter to know if it’s the first, second, third or fourth line. Then inside the switch block, based on this counter value, I create temporary variables where I store the result of the string builder.
If the character isn’t 10, I just append it to the string I’m building.
In the End block of the Foreach-Object cmdet, I can now create a single custom object using the temporary variables used in the process block.
This approach is rock solid until they change lines returned when you query the status URL šŸ™‚

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