Reputation: 620
In a PowerShell script running from a VM, I'd like to programmatically determine if the VM is a generation 1 Hyper-V VM, or if it is a generation 2 Hyper-V VM. Assume the VM is running a version of Windows compatible with running in a Gen 2 VM.
This question is not about detecting Hyper-V. Given that the script is running on a VM and the VM is running on Hyper-V, how do I determine the VM's generation number?
Possible leads:
Sample C++ MSDN code to query VM Generation ID - perhaps there is a way to convert this C++ code to C#, then dynamically compile it at runtime using Add-Type? I think this might be the best approach, but it's beyond my skill level.
VMDE Project on GitHub - has all kinds of methods for detecting VM platforms, but it's not written in PowerShell, and getting it to work is beyond my skill level
Thanks in advance!
Frank
Upvotes: 1
Views: 1144
Reputation: 16076
Not natively as you have already discovered, but a workaround might be to Invoke to a remote computer running hyper-v, and run the Get-VM cmdlet there to check your guest for the gen number.
Invoke-Command -ComputerName 'SomeRemoteServerNameWithHyperV' {
Get-VM -ComputerName 'YourHostName' |
Select-Object -Property Name, Generation
}
Update
Based on your Device Guard check. Just try this...
Get-CimInstance –ClassName Win32_DeviceGuard –Namespace root\Microsoft\Windows\DeviceGuard
Upvotes: 1
Reputation: 620
I made the assumption that if the system is a Hyper-V VM and if it is running UEFI (instead of BIOS), then it is a Hyper-V Gen 2 VM. Likewise, if it is a Hyper-V VM not running UEFI, then it must be a Hyper-V Gen 1 VM. At the time of writing, these assumptions are true.
I went on a coding marathon this afternoon and have a working solution, most easily read and maintained on my GitHub: https://github.com/franklesniak/PowerShell_Resources/blob/master/Get-HyperVVMGenerationNumberFromWithinVM.ps1
Unfortunately, the code exceeds the allowable limit of a post here on Stack Overflow, so I can't supply the code in this post. But, the function of interest is Get-HyperVVMGenerationNumberFromWithinVM and I've included it below, though it will not run without the prerequisite functions loaded, included in the GitHub link.
#region License
###############################################################################################
# Copyright 2020 Frank Lesniak
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
# and associated documentation files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following conditions:
# The above copyright notice and this permission notice shall be included in all copies or
# substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
###############################################################################################
#endregion License
function Get-HyperVVMGenerationNumberFromWithinVM {
# Returns an integer indicating the Hyper-V VM generation number of this system
# Returns 2 if this system is a Hyper-V VM running as a "Generation 2" Hyper-V VM
# Returns 1 if this system is a Hyper-V VM running as a "Generation 1" Hyper-V VM
# Note: Microsoft Virtual Server and Virtual PC VMs can also return 1
# Returns 0 if this system is a Hyper-V VM, but the generation number could not be
# determined due to an error. Usually this would only occur if the VM is Vista/Windows
# Server 2008 system and the PowerShell script was run without administrative privileges.
# Check the Warning stream for more information.
# Note: Microsoft Virtual Server and Virtual PC VMs can also return 0
# Returns -1 if this system is not a Hyper-V VM
$boolHyperVVM = Test-ThisSystemIsAHyperVVM
if ($null -ne $boolHyperVVM) {
if ($boolHyperVVM) {
$boolUEFI = Test-UEFISystem
if ($null -ne $boolUEFI) {
if ($boolUEFI) {
# Hyper-V VM with UEFI
# Generation 2
2
} else {
# Hyper-V VM not running UEFI
# Generation 1
1
}
} else {
# Is a Hyper-V VM but could not determine whether UEFI is running
# Error condition
0
}
} else {
# Not a Hyper-V VM
-1
}
} else {
$null
}
}
Upvotes: 0