Free PowerShell Script for Hyper-V: Detect MAC Address Conflicts

Save to My DOJO

Free PowerShell Script for Hyper-V: Detect MAC Address Conflicts

All physical network cards ship with a hard-coded unique identifier known as a media access control (MAC) address. These 48-bit identifiers help to ensure that Ethernet traffic finds its intended destination. If you want more information on that, follow our networking series. Here, I want to talk about the virtual MAC addresses that Hyper-V’s virtual network adapters use. I’ve got a script that can help you to quickly identify problems with MAC addresses in Hyper-V.

An Overview of Hyper-V MACs

Virtualization allows us to “fake” just about anything computer-related. Since virtual network adapters participate on Ethernet networks, they get “faked” MAC addresses. Each Hyper-V host generates a default pool. They all use the same first three octets: 00-15-5D, as Microsoft owns that prefix. The host generates the next two octets using an algorithm on its own physical hardware IDs. When virtual adapters start for the first time https://github.com/ejsiron/Posher-V/blob/master/Docs/Get-VMMacConflict.md and have no MAC, the host assigns them the next available number in the final octet.

Unfortunately, only having two octets available for uniqueness can quickly lead to duplicates. Reloaded systems will start over at 0 and might generate an octet set already in use. Virtual machines can move, so without some sort of external arbitration system, you can easily wind up with MAC collisions. Working only with symptoms, you might not even realize you have MAC problems at first. Detecting duplicate MACs can be a difficult process, especially when you don’t have tools built for the job.

Native Tools to Detect MAC Addresses

Hyper-V does not include any tool just for MAC duplicate detection. It does allow you to easily view all of the MACs on a host.

PowerShell code to see the virtual machine MACs:

Get-VMNetworkAdapter -VMName *

It will display all virtual adapters, their virtual machines, their MAC addresses, and some other information:

PowerShell code to see the virtual machine MACs

That only shows virtual machine information, though. For any virtual adapters that belong to the management operating system, use this:

Get-VMNetworkAdapter -ManagementOS

That won’t quite do it, though. You need one more cmdlet to see information for the host’s unbound physical adapters:

Get-NetAdapter

Now you have enough information to figure out if you have locally-conflicting addresses. You’ll have to figure out a way to collate and compare them all, though. And then you’d have to do it across all of your hosts. So, I did that for you.

Script Notes

A couple of points to note:

  • This is the final version of this script that I will post on this article. Any future updates will appear on its Github page.
  • This is my first script that uses the CIM cmdlets exclusively. I still use Windows PowerShell because it works perfectly well for me, but I believe that this script will also work with PowerShell Core.
  • Because I use CIM and not any add-in cmdlet packs (e.g. Hyper-V or VMM), this script will run on any PowerShell system. It can target remote systems. I tested against 2012 R2 and 2016 (simultaneously, even). It might work on 2012.
  • I built the script to look for collisions, not duplicates. MACs in distinct VLANs do not collide. Note these things:
    • You can use the -ExcludeVlans switch to ignore VLANs. That will uncover duplicate MACs no matter their VLAN.
    • The script cannot reliably detect VLAN membership of physical adapters. It will treat them as members of the untagged VLAN.
    • During testing, I discovered that a host’s virtual adapter has the same MAC as a virtual machine’s adapter on the same switch, it will cause collisions even if they do not share a VLAN. Due to the script’s architecture, that’s a difficult thing to capture using defaults. Use the -ExcludeVlans switch for now.
  • The script does work against vNICs in private VLANs and trunking vNICs. Each combination will appear as PrimaryVLAN:SecondaryVLAN, ex: 2:5.
  • The script has full help, including examples. Use the -Online switch to access a browser-friendly version of help.
  • If the script outputs nothing, that means that it didn’t find any duplicates.
  • You can pipe the output to Out-GridView or any of the CSV or HTML cmdlets.

Script File Listing

The text of the script’s initial release appears below:

<# .SYNOPSIS Locate conflicting Hyper-V virtual network adapter MAC addresses. .DESCRIPTION Locate conflicting Hyper-V virtual network adapter MAC addresses. With default settings, will scan the indicated hosts and generate a report of all adapters, virtual and physical, that use the same MAC in the same VLAN. Skips physical adapters bound by a virtual switch or team as these generate false positives. .PARAMETER ComputerName Name of one or more hosts running Hyper-V. If -HostFile is also set, uses both sources. If neither is set, uses the local system. .PARAMETER ExcludeHost If set, will not examine host MAC addresses for conflicts. .PARAMETER ExcludeVlan If set, will treat identical MAC addresses in distinct subnets as conflicts. .PARAMETER IncludeAllZero If set, will include virtual NICs with an all-zero MAC. .PARAMETER IncludeDisconnected If set, will include enabled but unplugged management operating system adapters. No effect if ExcludeHost is set. .PARAMETER IncludeDisabled If set, will include disabled management operating system adapters. No effect if ExcludeHost is set. .PARAMETER HostFile If provided, reads host names from the specified file. If -ComputerName is also set, uses both sources. If neither is set, uses the local system. .PARAMETER FileHasHeader If set, the first row in the file will be treated as a header row. If not set, the parser will assume the first column contains host names. Ignored if HostFile is not specified. .PARAMETER HeaderColumn If HostFile is a delimited type, use this to indicate which column contains the host names. If -HeaderColumn is set, but -FileHeader is NOT set, then this value will be treated as a column header AND a host name. If not set and the file is delimited, the first column will be used. Ignored if HostFile is not specified. .PARAMETER Delimiter The parser will treat this character as the delimiter in -HostFile. Defaults to the separator defined in the local machine's current culture. Ignored if HostFile is not specified. .NOTES Author: Eric Siron Version 1.0a, December 7, 2018 Released under MIT license .INPUTS String[] .EXAMPLE PS C:> Get-VMMacConflict
Checks the local machine for duplicate Hyper-V virtual machine MAC addresses. Includes active host adapters.
.EXAMPLE
PS C:> Get-VMMacConflict -ComputerName svhv1
Checks the Hyper-V system named "svhv1" for duplicate Hyper-V virtual machine MAC addresses. Includes active host adapters.
.EXAMPLE
PS C:> Get-VMMacConflict -ComputerName svhv1, svhv2, svhv3, svhv4
Checks all of the named Hyper-V systems for duplicate Hyper-V virtual machine MAC addresses. Includes active host adapters.
.EXAMPLE
PS C:> Get-VMMacConflict -HostFile C:hostnames.txt
Reads host names from C:hostnames.txt; it must be a single-column file of host names or all host names must be in the first column. VMs on these hosts are scanned for duplicate MAC addresses.
.EXAMPLE
PS C:> Get-VMMacConflict -HostFile C:hostnames.txt -FileHasHeader -HeaderColumn HostName
Reads host names from C:hostnames.txt; host names must be in a column named "HostName". VMs on these hosts are scanned for duplicate MAC addresses.
.EXAMPLE
PS C:> Get-VMMacConflict -HostFile C:hostnames.txt -HeaderColumn svhv1
Reads host names from C:hostnames.txt; looks for host names in a header-less column starting with svhv1. VMs on these hosts are scanned for duplicate MAC addresses.
.EXAMPLE
PS C:> Get-VMMacConflict -ExcludeVlan
Checks the local machine for duplicate Hyper-V virtual machine MAC addresses, even if they are in distinct VLANs. Includes active host adapters.
.EXAMPLE
PS C:> Get-VMMacConflict -IncludeDisconnected -IncludeDisabled
Checks the local machine for duplicate Hyper-V virtual machine MAC addresses. Includes active host adapters, even if they are disconnected or disabled.
.LINK
https://github.com/ejsiron/Posher-V/blob/master/Docs/Get-VMMacConflict.md
#>
[CmdletBinding()]
[OutputType([psobject[]])]
param
(
	[Parameter(ValueFromPipeline = $true, Position = 1)][String[]]$ComputerName = [String]::Empty,
	[Parameter()][Switch]$ExcludeHost,
	[Parameter()][Switch]$ExcludeVlan,
	[Parameter()][Switch]$IncludeAllZero,
	[Parameter()][Switch]$IncludeDisconnected,
	[Parameter()][Switch]$IncludeDisabled,
	[Parameter()][String]$HostFile = [String]::Empty,
	[Parameter()][Switch]$FileHasHeader,
	[Parameter()][String]$HeaderColumn = [String]::Empty,
	[Parameter()][Char]$Delimiter = (Get-Culture).TextInfo.ListSeparator
)

begin
{
	Set-StrictMode -Off	# script uses .Count to determine if an item is a collection and sometimes passes empty parameters intentionally
	$ErrorActionPreference = [System.Management.Automation.ActionPreference]::Continue	# ensure that, even if errors occur, PSDefaultParameters is reset
	$ExistingDefaultParams = $PSDefaultParameterValues.Clone()
	$PSDefaultParameterValues['Get-CimInstance:Namespace'] = 'root/virtualization/v2'
	$PathToHostSwitchPort = 'Msvm_LANEndpoint/Msvm_LANEndpoint/Msvm_EthernetSwitchPort'
	$PathToHostVlanSettings = 'Msvm_EthernetPortAllocationSettingData/Msvm_EthernetSwitchPortVlanSettingData'

	$MacList = New-Object -TypeName System.Collections.ArrayList

	$SuppliedHostNames = New-Object -TypeName System.Collections.ArrayList
	$VerifiedHostNames = New-Object -TypeName System.Collections.ArrayList
	$ProcessedHostNames = New-Object -TypeName System.Collections.ArrayList
	if (-not $ComputerName -and [String]::IsNullOrEmpty($HostFile))
	{
		$OutNull = $SuppliedHostNames.Add($env:COMPUTERNAME)
	}

	if ($HostFile)
	{
		Write-Verbose -Message ('Importing host names from "{0}"' -f $HostFile)
		$HostListFile = (Resolve-Path -Path $HostFile).Path
		$FileData = Import-Csv -Path $HostFile -Delimiter $Delimiter
		if ($FileData)
		{
			if ([String]::IsNullOrEmpty($HeaderColumn))
			{
				$HeaderColumn = ($FileData | Get-Member -MemberType NoteProperty)[0].Name
			}
			if ($FileHasHeader.ToBool() -eq $false)
			{
				$OutNull = $SuppliedHostNames.Add($HeaderColumn)	# Import-CSV ALWAYS treats line 1 as a header
			}
			$SuppliedHostNames.AddRange($FileData.$HeaderColumn)
		}
	}

	function Get-CimPathedAssociation
	{
		param
		(
			[Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true)][Microsoft.Management.Infrastructure.CimInstance]$CimInstance,
			[Parameter(Mandatory = $true, Position = 2)][String]$PathToInstance,
			[Parameter()][Switch]$KeyOnly
		)
		$PathNodes = $PathToInstance.Split('/')
		$SearchInstances = New-Object System.Collections.ArrayList
		$OutNull = $SearchInstances.Add($CimInstance)
		for ($i = 0; $i -lt $PathNodes.Length; $i++)
		{
			$ChildCounter = 1
			if ($SearchInstances.Count)
			{
				$OnlyKeys = [bool]($KeyOnly -or $i -ne ($PathNodes.Count - 1))
				$TemporarySearchInstances = New-Object System.Collections.ArrayList
				foreach ($SearchInstance in $SearchInstances)
				{
					Write-Progress -Id 2 -Activity 'Querying CIM instances' -Status ('At distance {0} of {1}' -f ($i + 1), $PathNodes.Count) -CurrentOperation ('Loading {0} instances related to {1}' -f $SearchInstances.Count, $SearchInstance.CimClass.CimClassName) -PercentComplete (($ChildCounter++) / $SearchInstances.Count * 100)
					$AssociatedInstances = Get-CimAssociatedInstance -InputObject $SearchInstance -ResultClassName $PathNodes[$i]
					if ($AssociatedInstances)
					{
						if ($AssociatedInstances.Count)
						{
							$OutNull = $TemporarySearchInstances.AddRange($AssociatedInstances)
						}
						else
						{
							$OutNull = $TemporarySearchInstances.Add($AssociatedInstances)
						}
					}
				}
				Write-Progress -Id 2 -Activity 'Querying CIM instances' -Completed
				if ($TemporarySearchInstances.Count)
				{
					$SearchInstances = $TemporarySearchInstances
				}
				else
				{
					$SearchInstances.Clear()
				}
			}
		}
		$SearchInstances
	}

	function New-MacReportItem
	{
		param
		(
			[Parameter(Mandatory = $true)][String]$MacAddress,
			[Parameter()][String]$VMName = [String]::Empty,
			[Parameter()][String]$VmID = [String]::Empty,
			[Parameter(Mandatory = $true)][String]$ComputerName,
			[Parameter(Mandatory = $true)][String]$AdapterName,
			[Parameter(Mandatory = $true)][String]$AdapterID,
			[Parameter()][bool]$IsStatic = $false,
			[Parameter()][String]$SwitchName = [String]::Empty,
			[Parameter()][String]$VlanInfo
		)
		$MacReportItem = New-Object psobject
		$MacReportItemNoteProperties = [ordered]@{
			VMName       = $VMName;
			VmID         = $VmID;
			ComputerName = $ComputerName;
			AdapterName  = $AdapterName;
			AdapterID    = $AdapterID;
			MacAddress   = $MacAddress;
			IsStatic     = $IsStatic;
			SwitchName   = $SwitchName;
			Vlan         = $VlanInfo
		}
		$AddMemberInvariants = @{
			InputObject         = $MacReportItem;
			NotePropertyMembers = $MacReportItemNoteProperties;
		}
		$OutNull = Add-Member @AddMemberInvariants
		$MacReportItem
	}

	function Get-VlanInfoArray
	{
		param
		(
			[Parameter()][Microsoft.Management.Infrastructure.CimInstance]$VlanInfo
		)
		$VlanInfoArray = New-Object -TypeName System.Collections.ArrayList
		$OutNull = $VlanInfoArray.Add('ph')	# prevent PS from decaying the arraylist
		if ($VlanInfo)
		{
			switch ($VlanInfo.OperationMode)
			{
				2
				{
					# Trunk
					$OutNull = $VlanInfoArray.Add($VlanInfo.NativeVlanId)
					foreach ($VlanId in $VlanInfo.TrunkVlanIdArray)
					{
						if ($VlanId -ne $VlanInfo.NativeVlanId)
						{
							$OutNull = $VlanInfoArray.Add($VlanId)
						}
					}
				}
				3
				{
					# Private
					if ($VlanInfo.PvlanMode -eq 3)	# promiscuous; allows multiple secondaries
					{
						foreach ($SecondaryVlan in $VlanInfo.SecondaryVlanIdArray)
						{
							$OutNull = $VlanInfoArray.Add("$($VlanInfo.PrimaryVlanId):$SecondaryVlan")
						}
					}
					else	# community & isolated; one secondary
					{
						$OutNull = $VlanInfoArray.Add("${$VlanInfo.PrimaryVlanId}:${$VlanInfo.SecondaryVlanId}")
					}
				}
				default # 1 is access mode; 0 should never occur but if it does, treat it as access
				{
					$OutNull = $VlanInfoArray.Add($VlanInfo.AccessVlanId)
				}
			}
		}
		else
		{
			$OutNull = $VlanInfoArray.Add("0")
		}
		$VlanInfoArray
	}

	function IsDuplicate
	{
		param(
			[Parameter(Mandatory = $true)][psobject]$Left,
			[Parameter(Mandatory = $true)][psobject]$Right,
			[Parameter()][bool]$ExcludeVlan
		)
		[bool](
			$Left.MacAddress -eq $Right.MacAddress -and
			(
				$Left.ComputerName -ne $Right.ComputerName -or
				$Left.VmID -ne $Right.VmID -or
				$Left.AdapterID -ne $Right.AdapterID
			) -and
			($ExcludeVlan -or $Left.Vlan -eq $Right.Vlan)
		)
	}
}

process
{
	foreach ($HostName in $ComputerName)
	{
		if (-not $SuppliedHostNames.Contains($HostName))
		{
			$OutNull = $SuppliedHostNames.Add($HostName)
		}
	}

	if ($SuppliedHostNames.Count)
	{
		$Activity = 'Verifying hosts lists'
		foreach ($HostName in $SuppliedHostNames)
		{
			if (-not $HostName)
			{
				continue
			}
			Write-Progress -Activity $Activity -Status $HostName
			if (-not $VerifiedHostNames.Contains($HostName))
			{
				$DiscoveredName = $HostName
				try
				{
					$DiscoveredName = (Get-CimInstance -ComputerName $HostName -Namespace 'root/cimv2' -ClassName 'Win32_ComputerSystem' -ErrorAction Stop).Name
					if (-not $VerifiedHostNames.Contains($HostName))
					{
						$OutNull = $VerifiedHostNames.Add($DiscoveredName)
					}
				}
				catch
				{
					Write-Error -Exception $_.Exception -ErrorAction Continue
					continue
				}
			}
		}
		Write-Progress -Activity $Activity -Completed

		$Activity = 'Discovering MAC addresses'
		foreach ($HostName in $VerifiedHostNames)
		{
			if ($ProcessedHostNames.Contains($HostName))
			{
				continue
			}
			else
			{
				$OutNull = $ProcessedHostNames.Add($HostName)
			}

			$Session = $null
			try
			{
				Write-Progress -Activity $Activity -Status ('Connecting to host "{0}"' -f $HostName)
				$Session = New-CimSession -ComputerName $HostName -ErrorAction Stop
			}
			catch
			{
				Write-Warning -Message ('Cannot connect to {0}' -f $HostName)
				Write-Error -Exception $_.Exception -ErrorAction Continue
				continue
			}

			foreach ($VM in Get-CimInstance -CimSession $Session -ClassName Msvm_ComputerSystem)
			{
				$CurrentOperation = 'Querying {0}' -f $VM.ElementName
				if ($HostName -eq $VM.Name)
				{
					if (-not $ExcludeHost)
					{
						Write-Progress -Activity $Activity -Status 'Loading host adapters' -CurrentOperation $CurrentOperation
						$AdapterList = New-Object System.Collections.ArrayList

						$ExternalPorts = Get-CimAssociatedInstance -InputObject $VM -ResultClassName Msvm_ExternalEthernetPort -ErrorAction SilentlyContinue
						$InternalPorts = Get-CimAssociatedInstance -InputObject $VM -ResultClassName Msvm_InternalEthernetPort -ErrorAction SilentlyContinue

						if ($ExternalPorts)
						{
							if ($ExternalPorts.Count) { $AdapterList.AddRange($ExternalPorts) }
							else { $OutNull = $AdapterList.Add($ExternalPorts) }
						}
						if ($InternalPorts)
						{
							if ($InternalPorts.Count) { $AdapterList.AddRange($InternalPorts) }
							else { $OutNull = $AdapterList.Add($InternalPorts) }
						}

						foreach ($Adapter in $AdapterList)
						{
							if ($Adapter.IsBound)
							{
								continue
							}
							$TargetDeviceId = $null
							if ($Adapter.DeviceId -match '{.*}')
							{
								$TargetDeviceId = $Matches[0]
							}
							$VLAN = 0
							$SwitchName = [String]::Empty
							Write-Progress -Activity $Activity -Status 'Loading host adapter information' -CurrentOperation $CurrentOperation
							$MSAdapter = Get-CimInstance -CimSession $Session -Namespace root/StandardCimv2 -ClassName MSFT_NetAdapter -Filter ('DeviceId="{0}"' -f $TargetDeviceId)
							$AdapterID = $TargetDeviceId
							$Enabled = $MSAdapter.State -eq 2 -or $IncludeDisabled
							$Connected = $MSAdapter.MediaConnectState -eq 1 -or ($IncludeDisconnected -or ($MSAdapter.State -ne 2 -and $IncludeDisabled))
							if ($Enabled -and $Connected)
							{
								if ($Adapter.CimClass.CimClassName -eq 'Msvm_InternalEthernetPort')
								{
									Write-Progress -Activity $Activity -Status 'Loading host adapter switch information' -CurrentOperation $CurrentOperation
									$SwitchPort = Get-CimPathedAssociation -CimInstance $Adapter -PathToInstance $PathToHostSwitchPort
									if ($SwitchPort)
									{
										$AdapterID = ('Microsoft:{0}{1}' -f $SwitchPort.SystemName, $SwitchPort.Name)
										$VMSwitch = Get-CimAssociatedInstance -InputObject $SwitchPort -ResultClassName Msvm_VirtualEthernetSwitch
										if ($VMSwitch)
										{
											$SwitchName = $VMSwitch.ElementName
										}
										$VlanSettings = Get-CimPathedAssociation -CimInstance $SwitchPort -PathToInstance $PathToHostVlanSettings
										if ($VlanSettings)
										{
											$VLAN = $VlanSettings.AccessVlanId
										}
										else
										{
											$VLAN = $MSAdapter.VlanID
										}
									}
								}
								$OutNull = $MacList.Add((New-MacReportItem -MacAddress $Adapter.PermanentAddress -ComputerName $HostName -AdapterName $MSAdapter.Name -AdapterID $AdapterID -IsStatic $true -SwitchName $SwitchName -Vlan $VLAN))
							}
						}
					}
				}
				else
				{
					Write-Progress -Activity $Activity -Status 'Loading virtual machine settings' -CurrentOperation $CurrentOperation
					$VMSettings = Get-CimAssociatedInstance -InputObject $VM -ResultClassName Msvm_VirtualSystemSettingData | where -Property VirtualSystemType -eq 'Microsoft:Hyper-V:System:Realized'
					if ($VMSettings)
					{
						Write-Progress -Activity $Activity -Status 'Loading virtual machine vNIC settings' -CurrentOperation $CurrentOperation
						foreach ($EthPortSettings in Get-CimAssociatedInstance -InputObject $VMSettings -ResultClassName Msvm_EthernetPortAllocationSettingData)
						{
							$VMSwitchName = [String]::Empty
							if ($EthPortSettings.EnabledState -eq 2)
							{
								$VMSwitchName = $EthPortSettings.LastKnownSwitchName
							}
							$VNICPortSettings = Get-CimAssociatedInstance -InputObject $EthPortSettings -ResultClassName Msvm_SyntheticEthernetPortSettingData
							if (-not $VNICPortSettings)
							{
								$VNICPortSettings = Get-CimAssociatedInstance -InputObject $EthPortSettings -ResultClassName Msvm_EmulatedEthernetPortSettingData
							}

							if ($VNICPortSettings -and ($IncludeAllZero -or $VNICPortSettings.Address -ne '0' * 12))
							{
								$VlanSettings = Get-CimAssociatedInstance -InputObject $EthPortSettings -ResultClassName Msvm_EthernetSwitchPortVlanSettingData

								foreach ($VlanSet in (Get-VlanInfoArray $VlanSettings | where { $_ -ne 'ph'}))
								{
									$OutNull = $MacList.Add((New-MacReportItem -MacAddress $VNICPortSettings.Address -VMName $VM.ElementName -VmID $VM.Name -ComputerName $HostName -AdapterName $VNICPortSettings.ElementName -AdapterID $VNICPortSettings.InstanceID -IsStatic $VNICPortSettings.StaticMacAddress -VlanInfo $VlanSet -SwitchName $VMSwitchName))
								}
							}
						}
					}
				}
			}
			$Session.Close()
		}
		Write-Progress -Activity $Activity -Completed
	}
}

end
{
	$Duplicates = New-Object -TypeName System.Collections.ArrayList
	foreach ($OuterItem in $MacList)
	{
		foreach ($InnerItem in $MacList)
		{
			if (-not $Duplicates.Contains($InnerItem))
			{
				if (IsDuplicate -Left $InnerItem -Right $OuterItem -ExcludeVlan $ExcludeVlan.ToBool())
				{
					$OutNull = $Duplicates.Add($InnerItem)
				}
			}

		}
	}

	$Duplicates.ToArray()

	$PSDefaultParameterValues.Clear()
	foreach ($ParamKey in $ExistingDefaultParams.Keys)
	{
		$PSDefaultParameterValues.Add($ParamKey, $ExistingDefaultParams[$ParamKey])
	}
}

I Need Your Help!

I did test this, but the more eyes looking at it, the better. If you find any problems, share them here or use the GitHub’s issues feature to file a bug report.

Which PowerShell Script would you like?

Is there a particular PowerShell script of a problem you think would be solved using PowerShell you’d like to know about? Let me know in the comments below or head on over to the Altaro Dojo Forums and open a new thread. I’m active in the Dojo Forums community and will gladly answer your PowerShell questions there – who knows I might already have that PowerShell script you need!

Altaro Hyper-V Backup
Share this post

Not a DOJO Member yet?

Join thousands of other IT pros and receive a weekly roundup email with the latest content & updates!

6 thoughts on "Free PowerShell Script for Hyper-V: Detect MAC Address Conflicts"

  • Jeff Chase says:

    Awesome! Thank you for taking the time to publish this!

  • Thomas Brown says:

    Thank you, Eric! We’ll put this to use.

  • Michael Calkins says:

    I get this error message numerous times when I run the script.

    The property ‘LastKnownSwitchName’ cannot be found on this object. Verify that the property exists.
    At line:410 char:9
    $VMSwitchName = $EthPortSettings.LastKnownSwitchName
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    CategoryInfo : NotSpecified: (:) [], PropertyNotFoundException
    FullyQualifiedErrorId : PropertyNotFoundStrict

Leave a comment or ask a question

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

Your email address will not be published.

Notify me of follow-up replies via email

Yes, I would like to receive new blog posts by email

What is the color of grass?

Please note: If you’re not already a member on the Dojo Forums you will create a new account and receive an activation email.