Skip to content

Instantly share code, notes, and snippets.

@Bill-Stewart
Last active March 24, 2025 20:20
Show Gist options
  • Save Bill-Stewart/5ed0fedc85e4190326074c9ca59e2302 to your computer and use it in GitHub Desktop.
Save Bill-Stewart/5ed0fedc85e4190326074c9ca59e2302 to your computer and use it in GitHub Desktop.
# Update-VirtualBoxWindowsAdditions.ps1
# Written by Bill Stewart (bstewart AT iname.com)
#
# Updates the VirtualBox Guest Additions on a VirtualBox VM.
#
# Prerequisites:
# * The VirtualBox Guest Additions ISO must be mounted in a VM optical drive
# * The Guest Additions must already be installed
#
# Version history:
#
# 2024-03-24
# * Moved package check before CIM (improve performance)
# * Cleaned up error handling and transcript termination
#
# 2024-03-19
# * Initial release
#requires -version 5
#requires -RunAsAdministrator
#------------------------------------------------------------------------------
# Update global values as needed
#------------------------------------------------------------------------------
$INSTALLER_FILE_NAME = 'VBoxWindowsAdditions.exe'
$INSTALLER_FILE_SILENT_ARGS = '/S'
$INSTALL_REGISTRY_PATH = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Oracle VirtualBox Guest Additions'
$INSTALL_REGISTRY_VERSION_VALUE = 'DisplayVersion'
#------------------------------------------------------------------------------
#------------------------------------------------------------------------------
# Record transcript to <systemroot>\Logs\<scriptname>.log
#------------------------------------------------------------------------------
$TranscriptFilePath = Join-Path `
([Environment]::GetFolderPath([Environment+SpecialFolder]::Windows)) `
'Logs'
$TranscriptFileName = '{0}.log' -f
[IO.Path]::GetFileNameWithoutExtension($MyInvocation.MyCommand.Name)
Start-Transcript (Join-Path $TranscriptFilePath $TranscriptFileName)
#------------------------------------------------------------------------------
# If package is installed, get its version number; terminate script if unable
# to determine installed package version
#------------------------------------------------------------------------------
$InstalledVersion = Get-ItemProperty $INSTALL_REGISTRY_PATH `
-ErrorAction SilentlyContinue |
Select-Object -ExpandProperty $INSTALL_REGISTRY_VERSION_VALUE `
-ErrorAction SilentlyContinue
if ( $null -ne $InstalledVersion ) {
$InstalledVersion = ([Version] $InstalledVersion)
if ( $null -eq $InstalledVersion ) {
Stop-Transcript
exit
}
Write-Host ('Installed version: {0}' -f $InstalledVersion.ToString())
}
else {
Write-Host 'Package must be installed before it can be updated.'
Stop-Transcript
exit
}
Write-Host 'Checking for updates to VirtualBox Windows Additions'
#------------------------------------------------------------------------------
# Locate installer executable; terminate script if not found
#------------------------------------------------------------------------------
$CimInstances = Get-CimInstance Win32_CDROMDrive
foreach ( $CimInstance in $CimInstances ) {
$InstallerFile = Get-Item (Join-Path (Join-Path $CimInstance.Drive '\') `
$INSTALLER_FILE_NAME) -ErrorAction SilentlyContinue
if ( $null -ne $InstallerFile ) {
break
}
}
if ( $null -eq $InstallerFile ) {
Write-Host ('Could not find file "{0}" on any optical drive(s).' -f
$INSTALLER_FILE_NAME)
Stop-Transcript
exit
}
Write-Host ('Found installer executable: {0}' -f $InstallerFile.FullName)
#------------------------------------------------------------------------------
# Get file version of installer executable; terminate script if unable
#------------------------------------------------------------------------------
$InstallerVersion = ([Version] $InstallerFile.VersionInfo.FileVersion)
if ( $null -eq $InstallerVersion ) {
Stop-Transcript
exit
}
Write-Host ('Installer version: {0}' -f $InstallerVersion.ToString())
#------------------------------------------------------------------------------
# Terminate script if installer file version is <= installed version
#------------------------------------------------------------------------------
if ( $InstallerVersion -le $InstalledVersion ) {
Write-Host 'Installer version is <= installed version (no action needed).'
Stop-Transcript
exit
}
#------------------------------------------------------------------------------
# Execute installer silently and wait for it to terminate
#------------------------------------------------------------------------------
$StartArgs = @{
FilePath = $InstallerFile.FullName
ArgumentList = $INSTALLER_FILE_SILENT_ARGS
PassThru = $true
Wait = $true
}
Write-Host ('Execute command: "{0}" {1}' -f $StartArgs.FilePath,
($StartArgs.ArgumentList -join ' '))
Write-Host -NoNewline 'Please wait: '
$Process = Start-Process @StartArgs
if ( $Process.ExitCode -eq 0 ) {
Write-Host 'Update completed successfully'
}
else {
Write-Host ('Update failed; exit code = 0x{0:X8}' -f $Process.ExitCode)
}
Stop-Transcript
exit $Process.ExitCode
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment