Create a Report of MTU Settings on All Hyper-V Hosts in the Domain/Forest

# mtuReportAllHyperVHosts.ps1

# Ensure that AD management module is available for PS Session
function includeRSAT{
    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
    $rsat1709 = ""
    $rsat1803 = ""
    $rsatWs2016 = ""
    # This command does not work on Windows 2012R2
    #$releaseId=(Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Name ReleaseId).ReleaseId
    #Get-ItemProperty : Property ReleaseId does not exist at path HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows
    #At line:1 char:2
    #+ (Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" -Na ...
    #+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    #    + CategoryInfo          : InvalidArgument: (ReleaseId:String) [Get-ItemProperty], PSArgumentException
    #    + FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.PowerShell.Commands.GetItemPropertyCommand
    $releaseId=(Get-Item "HKLM:SOFTWARE\Microsoft\Windows NT\CurrentVersion").GetValue('ReleaseID')
    $osName=(Get-WmiObject Win32_OperatingSystem).Name
    #$osType=switch ((Get-CimInstance -ClassName Win32_OperatingSystem).ProductType){
    #    1 {'client'}
    #    2 {'domaincontroller'}
    #    3 {'memberserver'}
    #    }
    $windowsVersion=(Get-CimInstance Win32_OperatingSystem).Version
    switch ($releaseId){
        1607{write-host 'Windows Server 2016 Release 1607 detected';$link=$rsatWs2016;break}
        1709{write-host 'Windows Server 2016 Release 1709 detected';$link=$rsat1709;break}
        1803{write-host 'Windows Server 2016 Release 1803 detected';$link=$rsat1803}
    switch ($osVersionMajorMinor){
        {$_ -eq 6.0}{write-host 'Windows Server 2008 or Windows Vista detected';$link=$rsat1709;break}
        {$_ -eq 6.1}{write-host 'Windows Server 2008 R2 or Windows 7 detected';$link=$rsatWindows7x64;break}
        {$_ -eq 6.2}{write-host 'Windows Server 2012 or Windows 8.1 detected';$link=$rsatWindows81;break}
        {$_ -eq 6.3}{write-host 'Windows Server 2012 R2 detected';$link=$rsatWindows81}

    if (!(Get-Module -ListAvailable -Name ActiveDirectory -EA SilentlyContinue)){
        Write-host "Module ActiveDirectory NOT currently available on this system. Please wait while the program adds that plugin..."
            # If OS is Windows Server, then install RSAT using a different method
            if ($osName -match "^Microsoft Windows Server") {
                # This sequence has confirmed to be valid on Windows Server 2008 R2 and above
                Write-Verbose "Importing Windows Feature: RSAT-AD-PowerShell"
                Import-Module ServerManager
                Add-WindowsFeature RSAT-AD-PowerShell
                Write-Verbose "This sequence targets Windows Client versions"
                $destinationFile= ($ENV:USERPROFILE) + "\Downloads\" + (split-path $link -leaf)
                Write-Host "Downloading RSAT from $link..."
                Start-BitsTransfer -Source $link -Destination $destinationFile
                $fileCheck=Get-AuthenticodeSignature $destinationFile
                if($fileCheck.status -ne "valid") {write-host "$destinationFile is not valid. Please try again...";break}
                $wusaCommand = $destinationFile + " /quiet"
                Write-host "Installing RSAT - please wait..."
                Start-Process -FilePath "C:\Windows\System32\wusa.exe" -ArgumentList $wusaCommand -Wait
            return $true
            write-warning "$($error[0].Exception)"
            return $false
        Write-host "Module ActiveDirectory IS currently available on this system." -ForegroundColor Green
        return $true

function ListHyperVHosts {            
      try {            
       Import-Module ActiveDirectory -ErrorAction Stop            
      } catch {            
       Write-Warning "Failed to import Active Directory module. Exiting program..."           
      $domains=(Get-ADForest -Identity $forest).Domains 
      foreach ($domain in $domains){
      [string]$dc=(get-addomaincontroller -DomainName $domain -Discover -NextClosestSite).HostName
      try {             
       $hyperVs = Get-ADObject -Server $dc -Filter 'ObjectClass -eq "serviceConnectionPoint" -and Name -eq "Microsoft Hyper-V"' -ErrorAction Stop;
       write-warning "Failed to query $dc of $domain";         
      foreach($hyperV in $hyperVs) {            
         $x = $hyperV.DistinguishedName.split(",")            
         $HypervDN = $x[1..$x.Count] -join "," 
         if ( !($HypervDN -match "CN=LostAndFound")) {     
         $computer = Get-ADComputer -Id $HypervDN -Prop *
         $thisObject = New-Object PSObject -Prop (
                 hostname = $computer.Name
                 operatingSystem = $($computer.operatingSystem)

function listForests{
    $GLOBAL:forests=Get-ADForest | select Name;
    if ($forests.length -gt 1){
        return $forests | %{$_.Name;}
        return $forests.Name;

function mtuReport($computernames){
    write-host "Please wait while we scan $($computernames.count) nodes."
        write-host "Scanning $_..."
            $result=invoke-command -computername $_ -ScriptBlock{
                return $adapters|select name,mtusize
                }|select @{name='computerName';e={$_.PSComputerName}},@{name='adapterName';e={$_.Name}},MtuSize
            write-warning $error[0].Exception.Message
    $mtuReport=$report|select-object computerName,adapterName,MtuSize,@{Name='highlight';e={$highLights[$_.MtuSize -eq 1500]}}
    $mtuReport|%{write-host $($_|select-object -Property * -ExcludeProperty highlight) -ForegroundColor $_.highlight}
    return $report

function sortArrayStringAsNumbers([string[]]$names){
    foreach ($name in $names){
        [int]$x=.{[void]($name -match '(?:.(\d+))+$');$matches[1]}
    $sorted=foreach($item in $hashTable.GetEnumerator() | Sort Value,Name){$item.Name}
    return $sorted

$hyperVHosts=listForests|%{ListHyperVHosts $_}
$hyperVHostNames=sortArrayStringAsNumbers $hyperVHosts.hostname
$mtuReport=mtuReport $hyperVHostNames
# Bonus round: get all clusters in the domain - this takes a long time for a large network
$clustersInDomain=Get-Cluster -domain $env:USERDNSDOMAIN|Get-ClusterGroup
# Filter down to VirtualMachine groups
$clustersInDomain|?{$_.GroupType -eq 'VirtualMachine'}
$vmClustersInDomain=$clustersInDomain|Group-Object Cluster|Select-Object Name

Leave a Reply

Your email address will not be published. Required fields are marked *