Skip to content

Instantly share code, notes, and snippets.

@michaeltlombardi
Last active October 3, 2015 15:22
Show Gist options
  • Save michaeltlombardi/e852d01ebbf9eaa8b7c7 to your computer and use it in GitHub Desktop.
Save michaeltlombardi/e852d01ebbf9eaa8b7c7 to your computer and use it in GitHub Desktop.
Update VMWare Tools from Unpacked ISO in Repository
Function Update-VMWareTools {
<#
.Synopsis
Update VMWare Tools from an unpacked ISO file on a shared repository.
.Description
Update VMWare Tools from an unpacked ISO file on a shared repository. As of
VMWare Tools Version 10, the VMWare releases the tools separately from the
ESXi patches and does so as individual ISO files. In order to use this function,
copy the ISO to a shared repository in your environment, and extract it into a
folder named for the version of the tools being installed. This function does
assume that you have CredSSP and WinRM enabled for second-hop remoting.
.Parameter ComputerName
The computername of the machines you want to upgrade the VMWare tools on.
.Parameter VMWareToolsVersion
The version of the VMWare Tools you are want to upgrade to.
.Parameter SharePath
The UNC path of your VMWare Tools repository. If one is not specified, a
default will be provided.
.Parameter LocalPath
The local path on the targeted computers where the VMWare Tools installation
files will be copied to. If one is not specified, a default will be provided.
.Parameter Credential
The credential needed to authenticate via CredSSP to the remote computers. If
one is not specified, the function will prompt for credentials.
.Parameter AsJob
If this parameter is specified the function will launch a job for each ComputerName
specified, attempting to upgrade the VMWare Tools on each of them asynchronously.
.Example
Update-VMWareTools -ComputerName Server1 -VMWareToolsVersion 10.1 -SharePath \\Server9\Repository\VMWareTools -LocalPath D:\VMT -Credential $Cred
This command will attempt to upgrade the VMWare Tools on Server1 to version 10.1.
It will launch a remote connection to Server1 using the credentials in the variable $Cred.
It will copy all the files found at \\Server9\Repository\VMWareTools\10.1 to D:\VMT\10.1 before
attempting to upgrade the tools. After the process executes, it will delete the local copy of
the installation files and return an object with the properties PSComputerName and ExitCode.
.Example
Update-VMWareTools -ComputerName -Server1,Server2,Server3, -VMWareToolsVersion 10.1
This command will attempt to upgrade the VMWare Tools on each of the specified servers one at
a time. It will prompt for a credential to be entered and then use that credential to connect
to each computer. It will use the default paths for both the SharePath and the LocalPath. It
will return an array of objects, one for each computer. Each object will have two properties:
PSComputerName and ExitCode.
.Example
Update-VMWareTools -ComputerName $Servers -VMWareToolsVersion 10.1 -AsJob
This command will attempt to upgrade the VMWare Tools on each of the computers in the $Servers
variable asynchronously. It will prompt for a credential and then use that credential to connect
to each of the computers. It will use the default paths for both the SharePath and the LocalPath.
It will return an array of objects, one for each computer. Each object will represent the job
launched against that computer, *not* the results of the operation.
.Notes
This functions assumes that: you have enabled CredSSP and WinRM in your environment; that you have
expanded the VMWare Tools ISO to folder in a shared repository; that the folder the installtion files
reside in is named for the Version of the tools inside; and that you are running powershell 2.0 or higher.
#>
[cmdletbinding()]
param(
[Parameter(Mandatory=$true,
Position=0,
HelpMessage="Enter the names of the computers whose VMWare Tools you want to update separated by commas.",
Alias="CN")]
[string[]]$ComputerName,
[Parameter(Mandatory=$true,
Position=1
HelpMessage="Enter the version of the VMWare Tools you want to update to. This should also be the name of the folder in your repository where the tools can be found",
Alias="Version","V")]
[string]$VMWareToolsVersion
[Parameter(Mandatory=$false,
Position=2,
Alias="RepositoryPath","Share","SP")]
# NB: You *will* want to change this default path to match your environment!
[string]$SharePath = "\\Server\UNCPath\To\VMWareTools\Repository"
[Parameter(Mandatory=$false,
Position=3,
Alias="Local","LP")]
# NB: You *will* want to change this default path if computers in your environment don't have a D:\ drive!
[string]$LocalPath
[Parameter(Mandatory=$false,
Position=4,
Alias="Cred","C")]
[pscredential]$Credential = (Get-Credential -Message "Enter your credentials for CredSSP Remote Management"),
[Parameter(Mandatory=$false,
Position=5,
Alias="AJ")]
[switch]$AsJob
)
#region Set Path Information
# This section will build the repository path as the concatenation of the SharePath and the version of
# the tools to be installed. If the local path was not specified, the function will create a folder on
# the D:\ drive by default. If you don't have a D:\ drive on computers in your environment, change this!
$RepositoryPath = "$SharePath\$VMWareToolsVersion"
If(-not $LocalPath){$LocalPath = D:\VMWareTools}
#endregion Set Path INformation
#region Test Repository Path
# If the script can't find the setup file in the Repository, it throws a terminating error. If the
# repository path doesn't contain the specified version, you do *not* want to continue.
If(-not (Test-Path -FilePath $RepositoryPath\Setup64.exe)){
Throw "$RepositoryPath does not contain the upgrade for the VMWare Tools version specified or does not exist."
}
#endregion Test Repository Path
#region Default DisplaySet Variables
# This region is used to configure the variables necessary to alter the default display set of the
# process objects generated with this function. Most of the processes will be generated on remote
# machines. We are mostly concerned with two properties: the PSComputerName (the computer on which
# the process was run) and the Exit Code (used to determine if the install was successful or not).
# By default, the Process object will not show the Exit Code, but will show extraneous information.
# This function returns only the PSComputerName and Exit Code; by default they will be returned in
# table format. The objects can still be manipulated as normal; because the function does not call
# any format cmdlets, it does not distort the data. The code for this section was discovered at
# http://learn-powershell.net/2013/08/03/quick-hits-set-the-default-property-display-in-powershell-on-custom-objects/
# and was authored by Boe Prox. See his blog for more excellent information.
$defaultDisplaySet = 'PSComputerName','ExitCode'
# Ceate a PSPropertySet object with those properties listed above.
$defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet(‘DefaultDisplayPropertySet’,[string[]]$defaultDisplaySet)
# Create the standard members property to be applied to the object.
$PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet)
#endregion Default DisplaySet Variables
# The script block variable defined here does the heavy lifting for this function. This is the script
# block where the files are copied from the repository to the target machine and where the upgrade is
# initiated. Whether the script is called as a job or not, this scriptblock will be called once for
# each computer name specified. Because it is invoked on remote machines both the Repository path and
# the Local path must be specified as parameters. It will return the process object for the upgrade.
$VMWareToolsUpgradeScriptBlock = {
param(
[string]$RepositoryPath,
[string]$LocalPath,
)
# Ensure that, if the default localpath is being used, the target computer has a D:\ drive. If it
# does not, this will throw a terminating error.
If(($LocalPath -eq "D:\VMWareTools") -and (-not (Test-Path -Path (Split-Path -Path $LocalPath -Parent))){
Throw "The default LocalPath was used, but this computer does not have a D:\ drive!"
}
# Ensure that the upgrade files are all copied to the target machine.
Copy-Item -Path $RepositoryPath -Destination $LocalPath -Container -Recurse -Force
# Initiate the process for the upgrade.
$Process = Start-Process -FilePath $LocalPath\Setup64.exe -ArgumentList "/s /v /qn" -PassThru
# Force the function to wait for the process to complete before continuing. Without
# this step, the process will not have an exit code.
Wait-Process $Process
# Ensure that the Process is cleanly terminated before removing the installation files.
Start-Sleep -Seconds 3
Remove-Item $LocalPath -Recurse -Force
# Return the process as an object.
Return $Process
}
# If AsJob is not specified, the function will attempt to upgrade the VMWare Tools on each remote machine
# one at a time in serial. This is only advised for small batches and tests, as it can take a *long* time
# in an enterprise environment.
If(-not $AsJob){
$Processes = @()
# The following section will execute the VMWareToolsUpgradeScriptBlock once on each specified computer.
# It will concatenate the process returned from each of these actions to the Processes variable.
ForEach($Computer in $ComputerName) {
$Processes += Invoke-Command -ComputerName $Computer -Authentication "CredSSP" -Credential $Credential `
-ScriptBlock $VMWareToolsUpgradeScriptBlock `
-ArgumentList $RepositoryPath,$LocalPath
}
# The following section will check each process returned above and write a message regarding whether or not
# the process was sucessful and if it requires a reboot on the target computer. Common Windows process exit
# codes can be found at http://www.symantec.com/connect/articles/windows-system-error-codes-exit-codes-description
ForEach($Process in $Processes){
If($Process.ExitCode -eq 0){
Write-Verbose "VMWare Tools successfully upgraded to version $VMWareToolsVersion on $($Process.PSComputerName)"
}
ElseIf($Process.ExitCode -eq 3010){
Write-Verbose "VMWare Tools successfully upgraded to version $VMWareToolsVersion on $($Process.PSComputerName)"
Write-Verbose "$($Process.PSComputerName) requires a reboot."
}
Else{
Write-Verbose "VMWare Tools failed to upgrade to version $VMWareToolsVersion on $($Process.PSComputerName)"
Write-Verbose "$($Process.PSComputerName) Exit Code: $($Process.ExitCode)"
}
# Create the custom object containing only the desired data, then add the default view to it.
$ProcessProperties = @{
"PSComputerName" = $Process.PSComputerName;
"ExitCode" = $Process.ExitCode
}
$SpecificProcessData = New-Object -TypeName PSCustomObject -Property $ProcessProperties
$SpecificProcessData | Add-Member MemberSet PSStandardMembers $PSStandardMembers
$ProcessData += $SpecificProcessData
}
# Here the function will return the objects to the pipeline.
Return $ProcessData
}
# If the AsJob switch is specified, the function will instead attempt to upgrade the VMWare Tools on each machine
# asynchronously. This will be much, much faster in an enterprise environment. By default, the function itself will
# return the list of jobs started. Each job will return the results of it's operation.
Else {
ForEach($Computer in $ComputerName){
Start-Job -ScriptBlock {
$Process = Invoke-Command -ComputerName $Computer -Authentication "CredSSP" -Credential $Credential `
-ScriptBlock $VMWareToolsUpgradeScriptBlock `
-ArgumentList $RepositoryPath,$LocalPath
# As above, the function will check on the success or failure of the process based on the exit code.
# See above for the link to common exit codes.
If($Process.ExitCode -eq 0){
Write-Verbose "VMWare Tools successfully upgraded to version $VMWareToolsVersion on $($Process.PSComputerName)"
}
ElseIf($Process.ExitCode -eq 3010){
Write-Verbose "VMWare Tools successfully upgraded to version $VMWareToolsVersion on $($Process.PSComputerName)"
Write-Verbose "$($Process.PSComputerName) requires a reboot."
}
Else{
Write-Verbose "VMWare Tools failed to upgrade to version $VMWareToolsVersion on $($Process.PSComputerName)"
Write-Verbose "$($Process.PSComputerName) Exit Code: $($Process.ExitCode)"
}
# Create the custom object containing only the desired data, then add the default view to it.
$ProcessProperties = @{
"PSComputerName" = $Process.PSComputerName;
"ExitCode" = $Process.ExitCode
}
$ProcessData = New-Object -TypeName PSCustomObject -Property $ProcessProperties
$ProcessData | Add-Member MemberSet PSStandardMembers $PSStandardMembers
# Return the Process object as the result of the Job.
Return $ProcessData
}
}
}
}
Set-Alias -Name uvmwt -Value Update-VMWareTools
@michaeltlombardi
Copy link
Author

Updated to include some safety catching for use in environments where target machines do not have a D:\ drive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment