= Scripts: PowerCLI: Detect and Change Guest Selected OS =
**Summary**: How to bulk change the guest selected OS in your VMware VMs. \\
**Date**: Around 2017 \\
**Refactor**: 21 February 2025: Checked links and formatting. \\
{{tag>vmware powershell}}
The Guest Selected OS is the VM value to determine how the VMware Tools should work. If this setting is not correct then weird issues may occur on your VMs from errors and BSOD to performance issues. These scripts will help you correct this issue:
Manually this can be done like this, but be aware that the VM needs to be turned off:
# In the vSphere Client inventory, right-click the virtual machine and select Edit Settings.
# Click the Options tab and select General Options.
# Select a guest operating system type and version.
# Click OK to save your changes and close the dialog box.
But scripted everything can be done automatically, which is useful when a lot of VMs are configured wrong.
= Make an Overview =
# Make an overview of all VMs that have the wrong OS configured
ForEach ($VM in (Get-VM)){
$vmview = Get-VM $VM | Get-View
$GuestFamily = $vmview.Guest.GuestFamily
$GuestSelectedOS = $vmview.Summary.Config.GuestFullName
$GuestRunningOS = $vmview.Guest.GuestFullname
if (($GuestFamily -eq "windowsGuest") -and ($GuestSelectedOS -ne $GuestRunningOS)){
# Choose your output: The first will give you a pretty but further useless output, the second one can be used to save as a cvs file, and the third can be directly used as input in the next script.
#Write-Host "VM = $VM `n`t Guest Family = $GuestFamily `n`t Set OS = $GuestSelectedOS `n`t Running OS = $GuestRunningOS"
#Write-Host "$vm,$GuestFamily,$GuestSelectedOS,$GuestRunningOS"
#Write-Host "$vm"
}
}
= Change the Guest Selected OS =
# Change the Guest selected OS for all VMs from an inputfile
## The inputfile needs to have one VM per line
## The VM will be turned off, and this will be checked before the change is made
## Afterwards the VM will be started again
# Start directory for the input file
$startdir = "D:\sjoerd"
# Creating Source List
$sourcename = "$startdir\inputfile.txt"
$vms = Get-Content $sourcename | Foreach-Object {Get-VM $_ }
# Scipt functions
# Note that you can suppress output from commands using | Out-Null
Function logger ($message) {Write-Host -ForegroundColor Green (Get-Date -format "yyyyMMdd-HH.mm.ss") `n "$message" `n}
Function loggeralert ($message) {Write-Host -ForegroundColor Red (Get-Date -format "yyyyMMdd-HH.mm.ss") `n "$message" `n}
Function PowerOn-VM($vm){
Start-VM -VM $vm -Confirm:$false -RunAsync | Out-Null
logger "$vm is starting!"
sleep 5
$time = 1
# Now check if the VM is started within 120 loops with each 5 seconds of waittime
do {
$vmview = Get-VM $VM | Get-View
$getvm = Get-VM $vm
$powerstate = $getvm.PowerState
$toolsstatus = $vmview.Guest.ToolsRunningStatus
logger "$vm is starting, powerstate is $powerstate and toolsstatus is $toolsstatus!"
sleep 5
$time++
# Adjust the timer $time to wait longer or shorter for the VM to start up. Lowering this value will not break anything, you'll just have to check manually whether the VM started successfully.
}until((($powerstate -match "PoweredOn") -and ($toolsstatus -match "guestToolsRunning")) -or ($time -eq 2))
if ($toolsstatus -match "guestToolsRunning"){
logger "$vm is started and has ToolsStatus $toolsstatus"
}
else{$Startup = "ERROR"}
return $Startup
}
Function PowerOff-VM($vm){
Shutdown-VMGuest -VM $vm -Confirm:$false | Out-Null
Logger "$vm is stopping!"
sleep 5
$shutdown = "starting"
$time = 1
# Now check if the VM is shutdown in 60 loops with each 5 seconds of waittime, and if not perform a hard shutdown
do {
$vmview = Get-VM $vm | Get-View
$getvm = Get-VM $vm
$powerstate = $getvm.PowerState
$toolsstatus = $vmview.Guest.ToolsStatus
logger "$vm is stopping with powerstate $powerstate and toolsStatus $toolsstatus!"
sleep 5
$time++
if($time -eq 60){
loggeralert "$vm is taking more than 5 minutes to shutdown. Hard powering off the VM."
Stop-VM -VM $vm -Confirm:$false | Out-Null
}
}until(($powerstate -match "PoweredOff") -or ($time -eq 120))
if ($powerstate -match "PoweredOff"){
logger "$vm is powered-off"
}
else{$shutdown = "ERROR"}
return $shutdown
}
# Handle each VM
foreach($item in $vms){
$vm = $item.Name
# ForEach ($VM in (Get-VM)){
$vmview = Get-VM $VM | Get-View
$GuestFamily = $vmview.Guest.GuestFamily
$GuestSelectedOS = $vmview.Summary.Config.GuestFullName
$GuestRunningOS = $vmview.Guest.GuestFullname
if (($GuestFamily -eq "windowsGuest") -and ($GuestSelectedOS -ne $GuestRunningOS)){
#logger "VM = $VM `n`t Guest Family = $GuestFamily `n`t Set OS = $GuestSelectedOS `n`t Running OS = $GuestRunningOS"
#logger "$vm,$GuestFamily,$GuestSelectedOS,$GuestRunningOS"
if ($GuestRunningOS -eq "Microsoft Windows Server 2008 R2 (64-bit)"){
$poweroff = PowerOff-VM $vm
if ($poweroff -ne "ERROR"){
Get-VM $vm | Set-VM -GuestId "windows7Server64Guest" -Confirm:$false
PowerOn-VM $vm
}
}
}
}