Get-VMwareTools

I’ve seen recently that you can download VMware tools directly from the editor instead of the internal server.

This gave me the idea of writing a function to enumerate either the latest or a known version of these tools based on the processor architecture.

To retrieve data using regular expressions, I’ve been using the awsome function ‘Get-Matches’ from Herr Dr. Tobias Weltner that I’ve already presented when analysing WordPress stats or getting Windows updates installation history.

# Requires -Version 3.0            
Function Get-VMwareLatestTools {            
[CmdletBinding()]            
Param(            
    [ValidateSet("latest","5.1","4.0","5.0")]            
    [system.string[]]$Version='latest',            
            
    [ValidateSet("x86","amd64","x64","x86_64")]            
    [system.string[]]$Architecture=$env:PROCESSOR_ARCHITECTURE            
)            
Begin {}            
Process {            
    $Version | ForEach-Object -Process {            
        $Ver = $_            
        Write-Verbose -Message "Handling version $Ver"            
        $rooturl = $null            
        Switch ($Ver) {            
            '5.1'    { $rooturl = 'http://packages.vmware.com/tools/esx/5.1latest'}            
            '5.0'    { $rooturl = 'http://packages.vmware.com/tools/esx/5.0latest'}            
            '4.0'    { $rooturl = 'http://packages.vmware.com/tools/esx/4.1latest'}            
            'latest' { $rooturl = 'http://packages.vmware.com/tools/esx/latest'   }            
        }            
        Write-Verbose -Message "Setting root URL to $rooturl"            
        if ($rooturl) {            
            $Architecture | ForEach-Object -Process {            
                $purl = $wr = $FileName = $FileSize = $FileDate = $null            
                $Arch = $_            
                Write-Verbose -Message "Handling architecture $Arch"            
                Switch ($Arch) {            
                    'x64' {             
                        if ($Ver -in @('5.1','latest')) {            
                            $purl = $rooturl + '/windows/x64/index.html'            
                        } else {            
                            $purl = $rooturl + '/windows/x86_64/index.html'            
                        }            
                    }            
                    'x86' {            
                        $purl = $rooturl + '/windows/x86/index.html'            
                    }            
                    'amd64' {            
                        if ($Ver -in @('5.1','latest')) {            
                            $purl = $rooturl + '/windows/x64/index.html'            
                        } else {            
                            $purl = $rooturl + '/windows/x86_64/index.html'            
                        }            
                    }            
                    'x86_x64' {            
                        $purl = $rooturl + '/windows/x86_64/index.html'            
                    }            
                }            
                Write-Verbose -Message "Full url set to $purl"            
                if ($purl -match "/index.html") {            
                    try {            
                        $wr = Invoke-WebRequest -UseBasicParsing -Uri $purl -ErrorAction Stop            
                    } catch {            
                        Write-Warning -Message "Web request of URI failed: $purl"            
                    }            
                    if ($wr) {            
                        # Get the filename            
                        $FileName = ($wr.Links |            
                            Where -FilterScript {            
                                $_.HREF -match '^VMware\-tools\-((windows\-)?)(?(\d{1,2}\.){2}\d{1,2})\-\d{6,8}((\-i386|\-x86_64)?)\.(exe|iso)$'            
                            })[0].HREF            
                        # Get the file size            
                        $FileSize = ($wr.Content|            
                        Get-Matches -Pattern ('\s?\s<A\sHREF=\"' + $FileName + '\">VMware\-tools\-((windows\-)?)((\d{1,2}\.){2}\d{1,2})\-\d{2,8}((\-i386|\-x86_)?)\.\.>\s\d{1,2}-\w{3}\-\d{4}\s\d{2}\:\d{2}\s{2,4}(?.*)')).Size            
            
                        $FileSize = ([double]($FileSize -split 'M')[0])*1024*1024            
                        # Get the file date            
                        $FileDate = ($wr.Content |             
                        Get-Matches -Pattern ('\s?\s<A\sHREF=\"' + $FileName + '\">VMware\-tools\-((windows\-)?)((\d{1,2}\.){2}\d{1,2})\-\d{2,8}((\-i386|\-x86_)?)\.\.>\s(?\d{1,2}-\w{3}\-\d{4}\s\d{2}\:\d{2})\s{2,4}')).Date            
            
                        New-Object -TypeName psobject -Property @{            
                            'Size(M)' = ($FileSize/1MB) ;            
                            Size = $FileSize            
                            Name = $FileName ;            
                            URI = "$purl/../$FileName" ;            
                            Date = ([System.DateTime]::ParseExact($FileDate,"dd-MMM-yyyy HH:mm",[System.Globalization.CultureInfo]::InvariantCulture));            
                        }            
                    }            
                } else {            
                    Write-Warning -Message "Architecture specified is unknown"            
                }            
            }            
        } else {            
            Write-Warning -Message "Version specified is unknown"            
        }            
    }            
}            
End {}            
}

Now I can with this function do the following:

# Get the latest tools for x86 and amd64 platforms            
Get-VMwareLatestTools -Version latest -Architecture x86,amd64 |  Select-Object Name,Date,'Size(M)' | ft -AutoSize            

Get-VMwareTools 1

I can also:

# Filter by size and display the formatted size in MB            
Get-VMwareLatestTools -Version latest,'5.0','4.0',5.1 -Architecture x64,x86,amd64 |             
Where Size -gt 50MB | Select-Object Name,Date,'Size(M)' | ft -AutoSize

Get-VMwareTools 2

And I can even launch a download like this:

# Get the latest VMware tools for the current processor architecture            
# and download the file in the temp directory            
Get-VMwareLatestTools -Version latest -Architecture $env:PROCESSOR_ARCHITECTURE|             
 ForEach-Object -Process {            
 'Downloading {0} with size {1}MB' -f $_.Name,$_.'Size(M)'            
  try {            
   Invoke-WebRequest -Uri $_.URI -OutFile "$env:temp\$($_.Name)" -ErrorAction Stop            
  } catch {            
   Write-Warning -Message "Failed to download VMware tools because $($_.Exception.Message)"            
  }            
 }
Advertisements

One thought on “Get-VMwareTools

  1. Here is the full source code w/o missing characters in regular expressions

    
    Function Get-VMwareLatestTools {
    [CmdletBinding()]
    Param(
        [ValidateSet("latest","5.1","4.0","5.0")]
        [system.string[]]$Version='latest',
    
        [ValidateSet("x86","amd64","x64","x86_64")]
        [system.string[]]$Architecture=$env:PROCESSOR_ARCHITECTURE
    )
    Begin {}
    Process {
        $Version | ForEach-Object -Process {
            $Ver = $_
            Write-Verbose -Message "Handling version $Ver"
            $rooturl = $null
            Switch ($Ver) {
                '5.1'    { $rooturl = 'http://packages.vmware.com/tools/esx/5.1latest'}
                '5.0'    { $rooturl = 'http://packages.vmware.com/tools/esx/5.0latest'}
                '4.0'    { $rooturl = 'http://packages.vmware.com/tools/esx/4.1latest'}
                'latest' { $rooturl = 'http://packages.vmware.com/tools/esx/latest'   }
            }
            Write-Verbose -Message "Setting root URL to $rooturl"
            if ($rooturl) {
                $Architecture | ForEach-Object -Process {
                    $purl = $wr = $FileName = $FileSize = $FileDate = $null
                    $Arch = $_
                    Write-Verbose -Message "Handling architecture $Arch"
                    Switch ($Arch) {
                        'x64' { 
                            if ($Ver -in @('5.1','latest')) {
                                $purl = $rooturl + '/windows/x64/index.html'
                            } else {
                                $purl = $rooturl + '/windows/x86_64/index.html'
                            }
                        }
                        'x86' {
                            $purl = $rooturl + '/windows/x86/index.html'
                        }
                        'amd64' {
                            if ($Ver -in @('5.1','latest')) {
                                $purl = $rooturl + '/windows/x64/index.html'
                            } else {
                                $purl = $rooturl + '/windows/x86_64/index.html'
                            }
                        }
                        'x86_x64' {
                            $purl = $rooturl + '/windows/x86_64/index.html'
                        }
                    }
                    Write-Verbose -Message "Full url set to $purl"
                    if ($purl -match "/index.html") {
                        try {
                            $wr = Invoke-WebRequest -UseBasicParsing -Uri $purl -ErrorAction Stop
                        } catch {
                            Write-Warning -Message "Web request of URI failed: $purl"
                        }
                        if ($wr) {
                            # Get the filename
                            $FileName = ($wr.Links |
                                Where -FilterScript {
                                    $_.HREF -match '^VMware\-tools\-((windows\-)?)(?<version>(\d{1,2}\.){2}\d{1,2})\-\d{6,8}((\-i386|\-x86_64)?)\.(exe|iso)$'
                                })[0].HREF
                            # Get the file size
                            $FileSize = ($wr.Content|
                            Get-Matches -Pattern ('\s?<IMG\sSRC=\"/icons/generic\.gif\"\sALT="\[FILE\]">\s<A\sHREF=\"' + $FileName + '\">VMware\-tools\-((windows\-)?)((\d{1,2}\.){2}\d{1,2})\-\d{2,8}((\-i386|\-x86_)?)\.\.&gt;</A>\s\d{1,2}-\w{3}\-\d{4}\s\d{2}\:\d{2}\s{2,4}(?<size>.*)')).Size
    
                            $FileSize = ([double]($FileSize -split 'M')[0])*1024*1024
                            # Get the file date
                            $FileDate = ($wr.Content | 
                            Get-Matches -Pattern ('\s?<IMG\sSRC=\"/icons/generic\.gif\"\sALT="\[FILE\]">\s<A\sHREF=\"' + $FileName + '\">VMware\-tools\-((windows\-)?)((\d{1,2}\.){2}\d{1,2})\-\d{2,8}((\-i386|\-x86_)?)\.\.&gt;</A>\s(?<date>\d{1,2}-\w{3}\-\d{4}\s\d{2}\:\d{2})\s{2,4}')).Date
    
                            New-Object -TypeName psobject -Property @{
                                # Size = "${FileSize}MB" ;
                                'Size(M)' = ($FileSize/1MB) ;
                                Size = $FileSize
                                Name = $FileName ;
                                URI = "$purl/../$FileName" ;
                                Date = ([System.DateTime]::ParseExact($FileDate,"dd-MMM-yyyy HH:mm",[System.Globalization.CultureInfo]::InvariantCulture));
                            }
                        }
                    } else {
                        Write-Warning -Message "Architecture specified is unknown"
                    }
                }
            } else {
                Write-Warning -Message "Version specified is unknown"
            }
        }
    }
    End {}
    }
    

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