private/Install-SoftwareMicrosoftHyperV.ps1

function Install-SoftwareMicrosoftHyperV {
    <#
    .SYNOPSIS
        Enables Hyper-V on Windows 11
 
    .DESCRIPTION
        Verifies that the host runs Windows 11 with Administrator rights, reads the configured
        Hyper-V feature name from module metadata when available, and checks its current state.
        The function enables a disabled feature and reports whether a restart is required.
 
        Already enabled and enable-pending states are left unchanged. WhatIf and Confirm apply
        to enabling the Windows optional feature.
 
    .EXAMPLE
        PS> Install-SoftwareMicrosoftHyperV
 
        Enables the configured Hyper-V feature when needed and returns its resulting state.
 
    .INPUTS
        None. This function does not accept pipeline input.
 
    .OUTPUTS
        System.Management.Automation.PSCustomObject. Returns the feature name, previous and
        current states, enablement status, skip status, and restart requirement.
 
    .NOTES
        Author: David Segura
        Company: Recast Software
        Version: 1.0.0
        Date: 2026-08-28
 
        Requires Windows 11, Administrator rights, Get-WindowsOptionalFeature, and
        Enable-WindowsOptionalFeature. The default feature name is Microsoft-Hyper-V-All.
 
        Change Summary:
            - Initial implementation.
 
    .LINK
        https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/quick-start/enable-hyper-v
    #>

    [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')]
    [OutputType([pscustomobject])]
    param ()

    if (-not $IsWindows) {
        throw "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] Install-SoftwareMicrosoftHyperV is supported only on Windows 11."
    }

    $os = Get-CimInstance -ClassName Win32_OperatingSystem -ErrorAction SilentlyContinue
    if (-not $os -or $os.Caption -notlike '*Windows 11*') {
        throw "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] Install-SoftwareMicrosoftHyperV is supported only on Windows 11."
    }

    if (-not (Test-IsAdministrator)) {
        throw "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] Install-SoftwareMicrosoftHyperV requires Administrator rights. Re-run PowerShell as Administrator and try again."
    }

    $featureName = 'Microsoft-Hyper-V-All'
    if ($global:OSDeployModule -and $global:OSDeployModule.Software.hyperv -and $global:OSDeployModule.Software.hyperv.featurename) {
        $featureName = [string]$global:OSDeployModule.Software.hyperv.featurename
    }

    $getFeatureCommand = Get-Command -Name 'Get-WindowsOptionalFeature' -ErrorAction SilentlyContinue
    $enableFeatureCommand = Get-Command -Name 'Enable-WindowsOptionalFeature' -ErrorAction SilentlyContinue
    if (-not $getFeatureCommand -or -not $enableFeatureCommand) {
        throw "[$(Get-Date -Format s)] [$($MyInvocation.MyCommand.Name)] Get-WindowsOptionalFeature and Enable-WindowsOptionalFeature are required but were not found."
    }

    $featureState = Get-WindowsOptionalFeature -Online -FeatureName $featureName -ErrorAction Stop

    if ($featureState.State -in @('Enabled', 'EnablePending')) {
        Write-Host "[$(Get-Date -Format s)] Hyper-V is already enabled (state: $($featureState.State))." -ForegroundColor Green
        return [pscustomobject]@{
            FeatureName    = $featureName
            PreviousState  = $featureState.State
            CurrentState   = $featureState.State
            WasEnabled     = $false
            SkippedInstall = $false
            RestartNeeded  = ($featureState.RestartNeeded -eq $true)
        }
    }

    if ($PSCmdlet.ShouldProcess($featureName, 'Enable Hyper-V optional feature')) {
        $enableResult = Enable-WindowsOptionalFeature -Online -FeatureName $featureName -All -NoRestart -ErrorAction Stop
        $updatedState = (Get-WindowsOptionalFeature -Online -FeatureName $featureName -ErrorAction Stop).State

        Write-Host "[$(Get-Date -Format s)] Hyper-V enable operation completed (state: $updatedState)." -ForegroundColor Green

        if ($enableResult.RestartNeeded -eq $true) {
            Write-Warning "[$(Get-Date -Format s)] A system restart is required before Hyper-V will be operational."
        }

        return [pscustomobject]@{
            FeatureName    = $featureName
            PreviousState  = $featureState.State
            CurrentState   = $updatedState
            WasEnabled     = $true
            SkippedInstall = $false
            RestartNeeded  = ($enableResult.RestartNeeded -eq $true)
        }
    }

    [pscustomobject]@{
        FeatureName    = $featureName
        PreviousState  = $featureState.State
        CurrentState   = $featureState.State
        WasEnabled     = $false
        SkippedInstall = $true
        RestartNeeded  = ($featureState.RestartNeeded -eq $true)
    }
}