diff --git a/CHANGELOG.md b/CHANGELOG.md index 7184a62..8f21963 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ For older change log history see the [historic changelog](HISTORIC_CHANGELOG.md) - Fix multiple DNS IP adresses does not work #190 - NetworkSetting parameter is now optional and no default actions are taken if not specified - Switch to use VM image `windows-latest` to build phase. + - DeviceNaming parameter added #206 + - MacAddressSpoofing parameter added #206 ## [3.18.0] - 2022-06-04 diff --git a/source/DSCResources/DSC_VMHyperV/DSC_VMHyperV.psm1 b/source/DSCResources/DSC_VMHyperV/DSC_VMHyperV.psm1 index 112942f..a233de5 100644 --- a/source/DSCResources/DSC_VMHyperV/DSC_VMHyperV.psm1 +++ b/source/DSCResources/DSC_VMHyperV/DSC_VMHyperV.psm1 @@ -362,7 +362,7 @@ function Set-TargetResource if ($nic.SwitchName -ne $switch) { Write-Verbose -Message ($script:localizedData.VMPropertyShouldBe -f 'NIC', $switch, $nic.SwitchName) - $nic | Connect-VMNetworkAdapter -SwitchName $switch + Connect-VMNetworkAdapter -VMNetworkAdapter $nic -SwitchName $switch Write-Verbose -Message ($script:localizedData.VMPropertySet -f 'NIC', $switch) } } diff --git a/source/DSCResources/DSC_VMNetworkAdapter/DSC_VMNetworkAdapter.psm1 b/source/DSCResources/DSC_VMNetworkAdapter/DSC_VMNetworkAdapter.psm1 index be24a8f..37c1f63 100644 --- a/source/DSCResources/DSC_VMNetworkAdapter/DSC_VMNetworkAdapter.psm1 +++ b/source/DSCResources/DSC_VMNetworkAdapter/DSC_VMNetworkAdapter.psm1 @@ -134,6 +134,12 @@ function Get-TargetResource .PARAMETER VlanId Specifies the Vlan Id for the network adapter. +.PARAMETER DeviceNaming + Use this to enable or disable Device Naming. Default: Off + +.PARAMETER MacAddressSpoofing + Use this to enable or disable MAC address spoofing. Default: Off + .PARAMETER Ensure Specifies if the network adapter should be Present or Absent. #> @@ -170,6 +176,16 @@ function Set-TargetResource [System.String] $VlanId, + [Parameter()] + [ValidateSet('On', 'Off')] + [System.String] + $DeviceNaming = 'Off', + + [Parameter()] + [ValidateSet('On', 'Off')] + [System.String] + $MacAddressSpoofing = 'Off', + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -205,12 +221,12 @@ function Set-TargetResource if ($netAdapterExists.DynamicMacAddressEnabled) { Write-Verbose -Message $script:localizedData.EnableStaticMacAddress - $updateMacAddress = $true + $updateAdapter = $true } - elseif ($MacAddress -ne $netAdapterExists.StaicMacAddress) + elseif ($MacAddress -ne $netAdapterExists.MacAddress) { Write-Verbose -Message $script:localizedData.EnableStaticMacAddress - $updateMacAddress = $true + $updateAdapter = $true } } else @@ -218,21 +234,29 @@ function Set-TargetResource if (-not $netAdapterExists.DynamicMacAddressEnabled) { Write-Verbose -Message $script:localizedData.EnableDynamicMacAddress - $updateMacAddress = $true + $updateAdapter = $true } } + if ($netAdapterExists.DeviceNaming -ne $DeviceNaming) + { + $updateAdapter = $true + } + if ($netAdapterExists.SwitchName -ne $SwitchName) { Write-Verbose -Message $script:localizedData.PerformSwitchConnect Connect-VMNetworkAdapter -VMNetworkAdapter $netAdapterExists -SwitchName $SwitchName -ErrorAction Stop -Verbose } - if (($updateMacAddress)) + if (($updateAdapter)) { Write-Verbose -Message $script:localizedData.PerformVMNetModify - $setArguments = @{ } + $setArguments = @{ + DeviceNaming = $DeviceNaming + MacAddressSpoofing = $MacAddressSpoofing + } $setArguments.Add('VMNetworkAdapter', $netAdapterExists) if ($MacAddress) { @@ -259,9 +283,11 @@ function Set-TargetResource $arguments.Add('StaticMacAddress', $MacAddress) } $arguments.Add('SwitchName', $SwitchName) + $arguments.Add('DeviceNaming', $DeviceNaming) } Write-Verbose -Message $script:localizedData.AddVMNetAdapter $netAdapterExists = Add-VMNetworkAdapter @arguments -Passthru -ErrorAction Stop + Set-VMNetworkAdapter -VMNetworkAdapter $netAdapterExists -MacAddressSpoofing $MacAddressSpoofing } if ($VmName -ne 'ManagementOS') @@ -367,6 +393,12 @@ function Set-TargetResource .PARAMETER VlanId Specifies the Vlan Id for the network adapter. +.PARAMETER DeviceNaming + Use this to enable or disable Device Naming. Default: Off + +.PARAMETER MacAddressSpoofing + Use this to enable or disable MAC address spoofing. Default: Off + .PARAMETER Ensure Specifies if the network adapter should be Present or Absent. #> @@ -404,6 +436,16 @@ function Test-TargetResource [System.String] $VlanId, + [Parameter()] + [ValidateSet('On', 'Off')] + [System.String] + $DeviceNaming = 'Off', + + [Parameter()] + [ValidateSet('On', 'Off')] + [System.String] + $MacAddressSpoofing = 'Off', + [Parameter()] [ValidateSet('Present', 'Absent')] [System.String] @@ -554,10 +596,30 @@ function Test-TargetResource } else { - Write-Verbose -Message $script:localizedData.VMNetAdapterExistsNoActionNeeded - return $true + Write-Verbose -Message $script:localizedData.SwitchIsCorrect + } + + if ($netAdapterExists.MacAddressSpoofing -ne $MacAddressSpoofing) + { + Write-Verbose -Message $script:localizedData.SpoofingDifferent + return $false + } + else + { + Write-Verbose -Message $script:localizedData.SpoofingConfiguredNoActionNeeded } + if ($netAdapterExists.DeviceNaming -ne $DeviceNaming) + { + Write-Verbose -Message $script:localizedData.DeviceNamingDifferent + return $false + } + else + { + Write-Verbose -Message $script:localizedData.DeviceNamingConfiguredNoActionNeeded + } + + return $true } else { diff --git a/source/DSCResources/DSC_VMNetworkAdapter/DSC_VMNetworkAdapter.schema.mof b/source/DSCResources/DSC_VMNetworkAdapter/DSC_VMNetworkAdapter.schema.mof index 65b1930..9cc512b 100644 --- a/source/DSCResources/DSC_VMNetworkAdapter/DSC_VMNetworkAdapter.schema.mof +++ b/source/DSCResources/DSC_VMNetworkAdapter/DSC_VMNetworkAdapter.schema.mof @@ -19,5 +19,7 @@ class DSC_VMNetworkAdapter : OMI_BaseResource [Write, Description("Network Settings of the network adapter. If this parameter is not supplied, DHCP will be used."), EmbeddedInstance("VMNetworkAdapterNetworkSettings")] String NetworkSetting; [Write, Description("Use this to specify a Vlan id on the Network Adapter.")] String VlanId; [Write, Description("Ensures that the VM Network Adapter is Present or Absent. The default value is `Present`."), ValueMap{"Present","Absent"}, Values{"Present","Absent"}] String Ensure; + [Write, Description("Use this to enable or disable Device Naming. Default: Off"), ValueMap{"On","Off"}, Values{"On","Off"}] String DeviceNaming; + [Write, Description("Use this to enable or disable MAC address spoofing. Default: Off"), ValueMap{"On","Off"}, Values{"On","Off"}] String MacAddressSpoofing; [Read, Description("Returns `$true` if the network adapter uses a dynamic MAC address.")] Boolean DynamicMacAddress; }; diff --git a/source/DSCResources/DSC_VMNetworkAdapter/en-US/DSC_VMNetworkAdapter.strings.psd1 b/source/DSCResources/DSC_VMNetworkAdapter/en-US/DSC_VMNetworkAdapter.strings.psd1 index d142c76..a6ad723 100644 --- a/source/DSCResources/DSC_VMNetworkAdapter/en-US/DSC_VMNetworkAdapter.strings.psd1 +++ b/source/DSCResources/DSC_VMNetworkAdapter/en-US/DSC_VMNetworkAdapter.strings.psd1 @@ -26,5 +26,10 @@ ConvertFrom-StringData @' VMNetAdapterExistsShouldRemove=VM Network Adapter Exists. It will be removed. VMNetAdapterDoesNotExistNoActionNeeded=VM Network adapter does not exist. No action needed. SwitchIsDifferent=Net Adapter is not connected to the requested switch. + SwitchIsCorrect=Net Adapter is connected to the requested switch. PerformSwitchConnect=Connecting VM Net adapter to the right switch. + SpoofingDifferent=MAC address spoofing configuration does not match. + SpoofingConfiguredNoActionNeeded=MAC address spoofing configured. + DeviceNamingDifferent=Device naming configuration does not match. + DeviceNamingConfiguredNoActionNeeded=Device naming configured. '@ diff --git a/tests/Unit/DSC_VMHyperV.Tests.ps1 b/tests/Unit/DSC_VMHyperV.Tests.ps1 index 13097b0..e1b4e1c 100644 --- a/tests/Unit/DSC_VMHyperV.Tests.ps1 +++ b/tests/Unit/DSC_VMHyperV.Tests.ps1 @@ -46,13 +46,13 @@ try $StubVMConfig = New-Item -Path 'TestDrive:\TestVM.xml' -ItemType File # Mock the class VMNetworkAdapter to support piping to cmdlet Connect-VMNetworkAdapter - $stubNIC1 = [Microsoft.HyperV.PowerShell.VMNetworkAdapter]::CreateTypeInstance() + $stubNIC1 = [Microsoft.HyperV.PowerShell.VMNetworkAdapterBase]::CreateTypeInstance() $stubNIC1.SwitchName = 'Test Switch 1' $stubNIC1.MacAddress = 'AA-BB-CC-DD-EE-FF' $stubNIC1.IpAddresses = @('192.168.0.1', '10.0.0.1') # Mock the class VMNetworkAdapter to support piping to cmdlet Connect-VMNetworkAdapter - $stubNIC2 = [Microsoft.HyperV.PowerShell.VMNetworkAdapter]::CreateTypeInstance() + $stubNIC2 = [Microsoft.HyperV.PowerShell.VMNetworkAdapterBase]::CreateTypeInstance() $stubNIC2.SwitchName = 'Test Switch 2' $stubNIC2.MacAddress = 'AA-BB-CC-DD-EE-FE' $stubNIC2.IpAddresses = @('192.168.1.1') @@ -602,7 +602,7 @@ try Mock -CommandName Stop-VM -MockWith { return $true } # requires output to be able to pipe something into Remove-VM Mock -CommandName Remove-VM -MockWith { return $true } Mock -CommandName Set-VMNetworkAdapter -MockWith { return $true } - Mock -CommandName Get-VMNetworkAdapter -MockWith { return $stubVM.NetworkAdapters.IpAddresses } + Mock -CommandName Get-VMNetworkAdapter -MockWith { return $stubVM.NetworkAdapters } Mock -CommandName Set-VMState -MockWith { return $true } Mock -CommandName Set-VMMemory diff --git a/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 b/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 index e9fa23a..77b704e 100644 --- a/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 +++ b/tests/Unit/DSC_VMNetworkAdapter.Tests.ps1 @@ -61,6 +61,19 @@ try $MockAdapter.VMName = $MockHostAdapter.VMName $MockAdapter.IsManagementOs = $true $MockAdapter.MacAddress = '14FEB5C6CE98' + $MockAdapter.DeviceNaming = 'Off' + $MockAdapter.MacAddressSpoofing = 'Off' + $MockAdapter.DynamicMacAddressEnabled = $false + + $dynamicMockAdapter = [Microsoft.HyperV.PowerShell.VMNetworkAdapterBase]::CreateTypeInstance() + $dynamicMockAdapter.Name = $MockHostAdapter.Name + $dynamicMockAdapter.SwitchName = $MockHostAdapter.SwitchName + $dynamicMockAdapter.VMName = 'VMName' + $dynamicMockAdapter.IsManagementOs = $true + $dynamicMockAdapter.MacAddress = '14FEB5C6CE98' + $dynamicMockAdapter.DeviceNaming = 'Off' + $dynamicMockAdapter.MacAddressSpoofing = 'Off' + $dynamicMockAdapter.DynamicMacAddressEnabled = $true $MockAdapterVlanUntagged = [PSObject]@{ OperationMode = 'Untagged' @@ -155,12 +168,14 @@ try Describe 'DSC_VMNetworkAdapter\Set-TargetResource' { $newAdapter = [PSObject]@{ - Id = 'UniqueString' - Name = $TestAdapter.Name - SwitchName = $TestAdapter.SwitchName - VMName = 'VMName' - NetworkSetting = $networkSettingsStatic - Ensure = 'Present' + Id = 'UniqueString' + Name = $TestAdapter.Name + SwitchName = $TestAdapter.SwitchName + VMName = 'VMName' + NetworkSetting = $networkSettingsStatic + Ensure = 'Present' + DeviceNaming = 'On' + MacAddressSpoofing = 'On' } Context 'Adapter does not exist but should' { @@ -172,6 +187,7 @@ try Mock -CommandName Remove-VMNetworkAdapter Mock -CommandName Set-VMNetworkAdapterVlan Mock -CommandName Set-NetworkInformation + Mock -CommandName Set-VMNetworkAdapter It 'should not throw error' { { @@ -185,6 +201,7 @@ try Assert-MockCalled -commandName Add-VMNetworkAdapter -Exactly 1 Assert-MockCalled -commandName Remove-VMNetworkAdapter -Exactly 0 Assert-MockCalled -CommandName Set-NetworkInformation -Exactly 1 + Assert-MockCalled -CommandName Set-VMNetworkAdapter -Exactly 1 } } @@ -208,15 +225,93 @@ try Assert-MockCalled -CommandName Set-VMNetworkAdapterVlan -Exactly 0 } } + + Context 'Adapter exists but hw address is different' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + Mock -CommandName Set-VMNetworkAdapter + Mock -CommandName Get-VMNetworkAdapterVlan + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.Remove('NetworkSetting') + $updateAdapter.VMName = "VMName" + $updateAdapter.MacAddress = '14FEB5C6CE99' + + { Set-TargetResource @updateAdapter } | Should -Not -throw + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Set-VMNetworkAdapter -Exactly 1 + } + } + Context 'Adapter exists but hw address is different and dynamic hw address is enabled' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $dynamicMockAdapter } + Mock -CommandName Set-VMNetworkAdapter + Mock -CommandName Get-VMNetworkAdapterVlan + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.Remove('NetworkSetting') + $updateAdapter.VMName = "VMName" + $updateAdapter.MacAddress = '14FEB5C6CE99' + + { Set-TargetResource @updateAdapter } | Should -Not -throw + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Set-VMNetworkAdapter -Exactly 1 + } + } + + Context 'Adapter exists but dynamic hw address setting is different' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + Mock -CommandName Set-VMNetworkAdapter + Mock -CommandName Get-VMNetworkAdapterVlan + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.Remove('NetworkSetting') + $updateAdapter.VMName = "VMName" + + { Set-TargetResource @updateAdapter } | Should -Not -throw + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Set-VMNetworkAdapter -Exactly 1 + } + } + + Context 'Adapter exists but connected to wrong switch' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + Mock -CommandName Set-VMNetworkAdapter + Mock -CommandName Connect-VMNetworkAdapter + Mock -CommandName Get-VMNetworkAdapterVlan + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.Remove('NetworkSetting') + $updateAdapter.VMName = "VMName" + $updateAdapter.SwitchName = "IAmAWrongSwitch" + + { Set-TargetResource @updateAdapter } | Should -Not -throw + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Connect-VMNetworkAdapter -Exactly 1 + Assert-MockCalled -commandName Set-VMNetworkAdapter -Exactly 1 + } + } } Describe 'DSC_VMNetworkAdapter\Test-TargetResource' { $newAdapter = [PSObject]@{ - Id = 'UniqueString' - Name = $TestAdapter.Name - SwitchName = $TestAdapter.SwitchName - VMName = 'ManagementOS' - Ensure = 'Present' + Id = 'UniqueString' + Name = $TestAdapter.Name + SwitchName = $TestAdapter.SwitchName + VMName = 'ManagementOS' + Ensure = 'Present' + DeviceNaming = 'On' + MacAddressSpoofing = 'On' } Context 'Adapter does not exist but should' { @@ -266,6 +361,8 @@ try $updateAdapter.VMName = "VMName" $updateAdapter.MacAddress = '14FEB5C6CE98' $updateAdapter.VlanId = '1' + $updateAdapter.DeviceNaming = 'Off' + $updateAdapter.MacAddressSpoofing = 'Off' Test-TargetResource @updateAdapter | Should -Be $true } It 'should call expected Mocks' { @@ -341,6 +438,120 @@ try Assert-MockCalled -commandName Get-NetworkInformation -Exactly 0 } } + + Context 'Adapter exists but hw address is different' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $MockAdapter } + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.VMName = "VMName" + $updateAdapter.MacAddress = '14FEB5C6CE99' + + Test-TargetResource @updateAdapter | Should -Be $false + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + } + } + Context 'Adapter exists but hw address is different and dynamic hw address is enabled' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $dynamicMockAdapter } + Mock -CommandName Get-VMNetworkAdapterVlan + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.VMName = "VMName" + $updateAdapter.MacAddress = '14FEB5C6CE99' + + Test-TargetResource @updateAdapter | Should -Be $false + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + } + } + + Context 'Adapter exists but dynamic hw address setting is different' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $dynamicMockAdapter } + Mock -CommandName Get-VMNetworkAdapterVlan + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.VMName = "VMName" + $updateAdapter.MacAddress = '14FEB5C6CE98' + + Test-TargetResource @updateAdapter | Should -Be $false + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + } + } + + Context 'Adapter exists and device naming setting OK' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $dynamicMockAdapter } + Mock -CommandName Get-VMNetworkAdapterVlan + + It 'should return true' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.VMName = "VMName" + $updateAdapter.DeviceNaming = "Off" + $updateAdapter.MacAddressSpoofing = "Off" + + Test-TargetResource @updateAdapter | Should -Be $true + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + } + } + + Context 'Adapter exists and device naming setting different' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $dynamicMockAdapter } + Mock -CommandName Get-VMNetworkAdapterVlan + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.VMName = "VMName" + $updateAdapter.DeviceNaming = "On" + $updateAdapter.MacAddressSpoofing = "Off" + + Test-TargetResource @updateAdapter | Should -Be $false + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + } + } + + Context 'Adapter exists and spoofing setting OK' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $dynamicMockAdapter } + Mock -CommandName Get-VMNetworkAdapterVlan + + It 'should return true' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.VMName = "VMName" + $updateAdapter.MacAddressSpoofing = "Off" + $updateAdapter.DeviceNaming = "Off" + + Test-TargetResource @updateAdapter | Should -Be $true + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + } + } + + Context 'Adapter exists and spoofing setting different' { + Mock -CommandName Get-VMNetworkAdapter -MockWith { $dynamicMockAdapter } + Mock -CommandName Get-VMNetworkAdapterVlan + + It 'should return false' { + $updateAdapter = $newAdapter.Clone() + $updateAdapter.VMName = "VMName" + $updateAdapter.MacAddressSpoofing = "On" + $updateAdapter.DeviceNaming = "Off" + + Test-TargetResource @updateAdapter | Should -Be $false + } + It 'should call expected Mocks' { + Assert-MockCalled -commandName Get-VMNetworkAdapter -Exactly 1 + } + } } } diff --git a/tests/Unit/Stubs/Hyper-V.stubs.psm1 b/tests/Unit/Stubs/Hyper-V.stubs.psm1 index 5f070ed..293fe97 100644 --- a/tests/Unit/Stubs/Hyper-V.stubs.psm1 +++ b/tests/Unit/Stubs/Hyper-V.stubs.psm1 @@ -340,7 +340,7 @@ namespace Microsoft.HyperV.PowerShell public System.DateTime CreationTime { get; set; } public System.Guid Id { get; set; } public System.String Name { get; set; } - public System.Collections.Generic.List NetworkAdapters { get; set; } + public System.Collections.Generic.List NetworkAdapters { get; set; } public Microsoft.Management.Infrastructure.CimSession CimSession { get; set; } public System.String ComputerName { get; set; } public System.Boolean IsDeleted { get; set; } @@ -1254,6 +1254,9 @@ namespace Microsoft.HyperV.PowerShell { // Manually added properties public System.String MacAddress { get; set; } + public Microsoft.HyperV.PowerShell.OnOffState DeviceNaming { get; set; } + public System.Boolean DynamicMacAddressEnabled { get; set; } + public System.String[] IPAddresses { get; set; } // Property public System.String SwitchName { get; set; } @@ -4861,13 +4864,13 @@ function Connect-VMNetworkAdapter { #> [CmdletBinding(DefaultParameterSetName='Name_SwitchName', SupportsShouldProcess=$true, ConfirmImpact='Medium')] - [OutputType([Microsoft.HyperV.PowerShell.VMNetworkAdapter])] + [OutputType([Microsoft.HyperV.PowerShell.VMNetworkAdapterBase])] param ( [Parameter(ParameterSetName='Object_SwitchName', Mandatory=$true, Position=0, ValueFromPipeline=$true)] [Parameter(ParameterSetName='Object_SwitchObject', Mandatory=$true, Position=0, ValueFromPipeline=$true)] [Parameter(ParameterSetName='Object_UseAutomaticConnection', Mandatory=$true, Position=0, ValueFromPipeline=$true)] [ValidateNotNullOrEmpty()] - [Microsoft.HyperV.PowerShell.VMNetworkAdapter[]] + [Microsoft.HyperV.PowerShell.VMNetworkAdapterBase[]] ${VMNetworkAdapter}, [Parameter(ParameterSetName='Name_SwitchObject', Position=1)] @@ -20498,4 +20501,3 @@ Wait-VM [-VM] [-AsJob] [-Passthru] [-For ] [-Del throw '{0}: StubNotImplemented' -f $MyInvocation.MyCommand } } -