I’ve been squeezing my brain trying to figure out how to get *-TargetResource to accept a [hashtable] parameter. Can it be done?
#psm1: param([hashtable]$AdvancedProperties) #schema: [Write] String AdvancedProperties;
breaks with
Write-NodeMOFFile : Invalid MOF definition for node 'localhost': Exception calling "ValidateInstanceText" with "1" argument(s): "Syntax error: At line:40, char:48 Buffer: $MSFT_KeyValuePair1ref,^ $M " At C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:1457 char:17 + ... Write-NodeMOFFile $name $mofNode $Script:NodeInstanceAlia ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [Write-Error], InvalidOperationException + FullyQualifiedErrorId : InvalidMOFDefinition,Write-NodeMOFFile
So that’s no good, obviously.
#psm1: param([hashtable]$AdvancedProperties) #schema [write] Hashtable AdvancedProperties;
is not recognized as a valid schema value at all, and the resource isn’t registered with DSC.
#psm1: param([hashtable]$AdvancedProperties) #schema [write, EmbeddedInstance("MSFT_KeyValuePair")] String AdvancedProperties;
breaks with the following error:
Write-NodeMOFFile : Invalid MOF definition for node 'localhost': Exception calling "ValidateInstanceText" with "1" argument(s): "Syntax error: At line:40, char:48 Buffer: $MSFT_KeyValuePair1ref,^ $M " At C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:1457 char:17 + ... Write-NodeMOFFile $name $mofNode $Script:NodeInstanceAlia ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [Write-Error], InvalidOperationException + FullyQualifiedErrorId : InvalidMOFDefinition,Write-NodeMOFFile
And finally, I found a PowerShell Team person (http://blogs.msdn.com/b/powershell/archive/2013/11/19/resource-designer-tool-a-walkthrough-writing-a-dsc-resource.aspx) suggesting that it should be set up as such:
#psm1 param([Microsoft.Management.Infrastructure.CimInstance]$AdvancedProperties) #schema [write, EmbeddedInstance("MSFT_KeyValuePair")] String AdvancedProperties;
but that also fails with the same error as previously
Write-NodeMOFFile : Invalid MOF definition for node 'localhost': Exception calling "ValidateInstanceText" with "1" argument(s): "Syntax error: At line:25, char:48 Buffer: $MSFT_KeyValuePair1ref,^ $M " At C:\windows\system32\windowspowershell\v1.0\Modules\PSDesiredStateConfiguration\PSDesiredStateConfiguration.psm1:1457 char:17 + ... Write-NodeMOFFile $name $mofNode $Script:NodeInstanceAlia ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [Write-Error], InvalidOperationException + FullyQualifiedErrorId : InvalidMOFDefinition,Write-NodeMOFFile
It breaks using both WMF4 and WMF5 Preview.
This is the configuration file I’m using:
configuration DSCModuleTest { param( [Parameter(Mandatory = $true)] [string]$ComputerName ) Import-DscResource -ModuleName devNetAdapterModule Node $ComputerName { sNetAdapterAdvancedProperty Property { InterfaceAlias = 'Ethernet' AdvancedProperties = @{ 'Jumbo Packet' = '1514' 'Receive Side Scaling' = '1' } } } } DSCModuleTest -ComputerName 'localhost'
and the associated DSCResource as it looks currently:
###################################################################################### # The Get-TargetResource cmdlet. # This function will get the working interface and its bindings ###################################################################################### function Get-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$InterfaceAlias ) $properties = GetNetAdapterAdvancedProperty -InterfaceAlias $InterfaceAlias -Formatted Write-Output $properties } ###################################################################################### # The Set-TargetResource cmdlet. # This function will set the bindings of the selected interface ###################################################################################### function Set-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$InterfaceAlias, [Parameter(Mandatory)] [hashtable]$AdvancedProperties #[Microsoft.Management.Infrastructure.CimInstance]$AdvancedProperties ) $properties = GetNetAdapterAdvancedProperty -InterfaceAlias $InterfaceAlias foreach($key in $AdvancedProperties.Keys) { Write-Verbose ('Processing property {0}' -f $key) $property = $properties | Where-Object DisplayName -eq $key if($property -eq $null) { throw "Property $key not found. Use the Get-NetAdapterAdvancedProperty cmdlet to see available properties for your interface, and configure DSC AdvancedProperties hashtable to use 'DisplayName' property as key, and 'RegistryValue' as value." } Write-Verbose ('Found and now setting property {0}' -f $property.DisplayName) $property | Set-NetAdapterAdvancedProperty -RegistryValue $AdvancedProperties.$key } } ###################################################################################### # The Test-TargetResource cmdlet. # This will test if the interface bindings are as expected ###################################################################################### function Test-TargetResource { [CmdletBinding()] param ( [Parameter(Mandatory)] [ValidateNotNullOrEmpty()] [string]$InterfaceAlias, [Parameter(Mandatory)] [hashtable]$AdvancedProperties #[Microsoft.Management.Infrastructure.CimInstance]$AdvancedProperties ) $properties = GetNetAdapterAdvancedProperty -InterfaceAlias $InterfaceAlias -Formatted foreach($key in $AdvancedProperties.Keys) { Write-Verbose ('Processing property {0}' -f $key) $property = $properties | Where-Object DisplayName -eq $key if($property -eq $null) { throw "Property $key not found. Use the Get-NetAdapterAdvancedProperty cmdlet to see available properties for your interface, and configure DSC AdvancedProperties hashtable to use 'DisplayName' property as key, and 'RegistryValue' as value." } Write-Verbose ('Found and now testing property {0}' -f $property.DisplayName) if($property.RegistryValue -ne $AdvancedProperties.$key) { Write-Verbose ('Property "{0}" with expected value "{1}" does not match set value "{2}"' -f $key, $AdvancedProperties.$key, $property.RegistryValue) return $false } } return $true } ####################################################################################### # Helper function that validates the IP Address properties. If the switch parameter # "Apply" is set, then it will set the properties after a test ####################################################################################### function GetNetAdapterByAlias { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$InterfaceAlias ) Write-Verbose "Attempting to find NetAdapter using Alias $InterfaceAlias" $adapter = Get-NetAdapter -InterfaceAlias $InterfaceAlias if($adapter -ne $null -and @($adapter).Count -eq 1) { Write-Verbose ('Found {0}' -f $adapter.Name) return $adapter } else { if(@($adapter).Count -gt 1) { throw ("Too many adapters found for Alias $InterfaceAlias ({0})" -f ($adapter.Name -join ', ')) } elseif($adapter -eq $null) { throw "No adapter found for Alias $InterfaceAlias" } else { throw ('Unexpected error? Adapter count: {0}. InterfaceAlias: {1}.' -f @($adapter).Count, $InterfaceAlias) } } } function GetNetAdapterAdvancedProperty { [CmdletBinding()] param( [Parameter(Mandatory)] [string]$InterfaceAlias, [switch]$Formatted ) $adapter = GetNetAdapterByAlias -InterfaceAlias $InterfaceAlias Write-Verbose "Getting advanced properties" $properties = $adapter | Get-NetAdapterAdvancedProperty if($properties -eq $null) { throw ("Unable to acquire bindings for NetAdapter {0}" -f $adapter.Name) } if($Formatted) { Write-Verbose "Formatting properties" $returnValue = foreach($property in $properties) { Write-Output @{ $property.DisplayName = $property.DisplayValue } } Write-Output $returnValue } else { Write-Output $properties } } # FUNCTIONS TO BE EXPORTED Export-ModuleMember -function Get-TargetResource, Set-TargetResource, Test-TargetResource