用于检测 Hyper-V Gen 2 VM 与 Gen 1 VM 的 PowerShell 代码(运行 来自 VM 本身)

PowerShell Code to Detect Hyper-V Gen 2 VM vs. Gen 1 VM (Run from VM Itself)

在 VM 的 PowerShell 脚本 运行 中,我想以编程方式确定该 VM 是第 1 代 Hyper-V VM 还是第 2 代 Hyper-V VM。假设 VM 是 运行 与第 2 代 VM 中的 运行 兼容的 Windows 版本。

这个问题不是关于检测 Hyper-V 的。鉴于脚本在 VM 上是 运行 而 VM 在 Hyper-V 上是 运行,我如何确定 VM 的世代号?

可能的线索:

Sample C++ MSDN code to query VM Generation ID - 也许有一种方法可以将此 C++ 代码转换为 C#,然后在运行时使用 Add-Type 动态编译它?我认为这可能是最好的方法,但它超出了我的技能水平。

VMDE Project on GitHub - 有各种检测VM平台的方法,但不是用PowerShell写的,要实现它超出了我的技能水平

提前致谢!

弗兰克

不像您已经发现的那样是本地的,但解决方法可能是调用远程计算机 运行ning hyper-v,然后 运行 那里的 Get-VM cmdlet 来检查您的来宾代号。

Invoke-Command -ComputerName 'SomeRemoteServerNameWithHyperV' {
    Get-VM -ComputerName 'YourHostName' | 
    Select-Object -Property Name, Generation
}

更新

根据您的 Device Guard 检查。试试这个...

Get-CimInstance –ClassName Win32_DeviceGuard –Namespace root\Microsoft\Windows\DeviceGuard

我假设如果系统是 Hyper-V VM 并且它是 运行ning UEFI(而不是 BIOS),那么它就是 Hyper-V Gen 2 VM。同样,如果它是 Hyper-V VM 而不是 运行ning UEFI,则它必须是 Hyper-V Gen 1 VM。在撰写本文时,这些假设是正确的。

我今天下午参加了编码马拉松比赛,并有一个 可行的解决方案 ,最容易阅读和维护的是我的 GitHub:https://github.com/franklesniak/PowerShell_Resources/blob/master/Get-HyperVVMGenerationNumberFromWithinVM.ps1

不幸的是,代码超出了 Stack Overflow 上 post 的允许限制,因此我无法在 post 中提供代码。但是,感兴趣的函数是 Get-HyperVVMGenerationNumberFromWithinVM 并且我将其包含在下面,尽管 它不会 运行 如果没有加载先决条件函数,包含在GitHublink.

#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
    }
}