Private/InstallHyperVFeatures.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
function InstallHyperVFeatures {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory=$False)]
        [switch]$AllowRestarts,

        [Parameter(Mandatory=$False)]
        [string]$ParentFunction
    )
    
    # Import the Dism Module
    if (![bool]$(Get-Module Dism)) {
        try {
            if ($PSVersionTable.PSEdition -eq "Core") {
                Import-WinModule Dism -ErrorAction Stop
            }
            else {
                Import-Module Dism -ErrorAction Stop
            }
        }
        catch {
            if ($PSVersionTable.PSEdition -eq "Core") {
                $DismModuleManifestPaths = Invoke-WinCommand -ScriptBlock {$(Get-Module -ListAvailable -Name Dism).Path}
            }
            else {
                # Using full path to Dism Module Manifest because sometimes there are issues with just 'Import-Module Dism'
                $DismModuleManifestPaths = $(Get-Module -ListAvailable -Name Dism).Path
            }

            foreach ($MMPath in $DismModuleManifestPaths) {
                try {
                    if ($PSVersionTable.PSEdition -eq "Core") {
                        Import-WinModule $MMPath -ErrorAction Stop
                        break
                    }
                    else {
                        Import-Module $MMPath -ErrorAction Stop
                        break
                    }
                }
                catch {
                    Write-Verbose "Unable to import $MMPath..."
                }
            }
        }
    }
    if ($(Get-Module).Name -notcontains "Dism") {
        Write-Error "Problem importing the Dism PowerShell Module! Unable to proceed with Hyper-V install! Halting!"
        $global:FunctionResult = "1"
        return
    }

    $HyperVFeaturesOSAgnostic = $(Get-WindowsOptionalFeature -Online | Where-Object {$_.FeatureName -match "Hyper"}).FeatureName
    
    [System.Collections.ArrayList]$HyperVFeaturesInstallResults = @()
    [System.Collections.ArrayList]$HyperVFeatureInstallFailures = @()
    foreach ($FeatureToInstall in $HyperVFeaturesOSAgnostic) {
        try {
            $HyperVFeatureInstallResult = InstallFeatureDism -Feature $FeatureToInstall -ParentFunction $ParentFunction
            if ($HyperVFeatureInstallResult.RestartNeeded -eq $True) {
                $null = $HyperVFeaturesInstallResults.Add($HyperVFeatureInstallResult)
            }
        }
        catch {
            Write-Error $_
            Write-Warning "The InstallFeatureDism function failed to install the Feature $FeatureToInstall!"
            $null = $HyperVFeatureInstallFailures.Add($FeatureToInstall)
        }
    }

    if ($HyperVFeatureInstallFailures.Count -gt 0) {
        Write-Warning "The following Hyper-V Features failed to install:`n$($HyperVFeatureInstallFailures -join "`n")"
    }

    if ($HyperVFeaturesInstallResults.Count -gt 0 -or $HyperVFeatureInstallFailures.Count -gt 0) {
        if ($AllowRestarts) {
            Restart-Computer -Confirm:$false -Force
        }
        else {
            Write-Warning "You must restart $env:ComputerName before proceeding!"
        }
    }

    if ($HyperVFeaturesInstallResults.Count -eq 0 -and $HyperVFeatureInstallFailures.Count -eq 0) {
        Write-Warning "All Hyper-V features are already installed. No action taken!"
    }
    else {
        [pscustomobject]@{
            InstallResults      = $HyperVFeaturesInstallResults
            InstallFailures     = $HyperVFeatureInstallFailures
        }
    }
}