Array of Hashtable to DSC

Hello all,

 

I am attempting to pass an array of hashtables (containing flat values string:string for key:value:) to a dsc resource created using the Hashtable resource property of the XDSCResourceDesigner. I have read through numerous posts on this site as well. The one issue we have is it is a third party programming passing this hash table to invoke-dscresource. I was able to use the third party debugger to get the exact call and reproduce the following in powershell:

PS C:\genetec\CloudOps\internal_system_tool> $test = @(@{test=123;test2=1234},@{test=321;test2=4321})

PS C:\genetec\CloudOps\internal_system_tool> $invokeParams = @{
Name = 'resource'
ModuleName = @{
modulename = 'module'
moduleversion = '1.0.0'
}
Method = 'test'
Property = @{
'ensure' = 'Present';
'privilegeshashtable' = $test
}
}
$result = Invoke-DscResource @invokeParams
Invoke-DscResource : Failed to serialize properties into CimInstance.
At line:13 char:11
+ $result = Invoke-DscResource @invokeParams
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Invoke-DscResource], SerializationException
+ FullyQualifiedErrorId : System.Runtime.Serialization.SerializationException,Microsoft.PowerShell.DesiredStateConfiguration.Commands.InvokeDscResourceMethodCommand

Based on the dsc designer notes this should be possible, yet I get an error each time until my array hashtable is of count 1. This snippit is pulled from the psm1 of xdscresourcedesigner on github:

 

        # An array of hashtables is not converted back to a hashtable, but is
        # passed to the provider as an array of CimInstances
        "Hashtable[]"    = [Microsoft.Management.Infrastructure.CimInstance[]];

Is there no way to pass a raw hashtable array to a dsc resource using invoke-command without actually looping through and calling the resource as many times as there are <= count in the array? I prefer to make one call and handle the array in my custom resource. Reason being i have hundreds of items to process and a loop in the resource is far less costly than invoke-dscresource a few hundred times.

I’m afraid I don’t have time to test right now, but have you tried casting your array of hashtable before sending it to Invoke-DscResource?

At the moment this:

$test = @(@{test=123;test2=1234},@{test=321;test2=4321})
 

Gives you a type of [object]. I’m not sure Invoke-DscResource is able to cast that for you, so you could try:

$test = [hashtable[]]@(@{test=123;test2=1234},@{test=321;test2=4321})
Just a quick thought...

I don’t exactly have this luxury since it is the puppet engine that is passing the resource. Michael Greene had suggested possibly doing this in the schema file during the summit a few weeks back but I don’t exactly know how to approach that.

chughes 14:03:57> $test | gm


TypeName: System.Collections.Hashtable

Name MemberType Definition
---- ---------- ----------
Add Method void Add(System.Object key, System.Object value), void IDictionary.Add(Syste...
Clear Method void Clear(), void IDictionary.Clear()
Clone Method System.Object Clone(), System.Object ICloneable.Clone()
Contains Method bool Contains(System.Object key), bool IDictionary.Contains(System.Object key)
ContainsKey Method bool ContainsKey(System.Object key)
ContainsValue Method bool ContainsValue(System.Object value)
CopyTo Method void CopyTo(array array, int arrayIndex), void ICollection.CopyTo(array arra...
Equals Method bool Equals(System.Object obj)
GetEnumerator Method System.Collections.IDictionaryEnumerator GetEnumerator(), System.Collections...
GetHashCode Method int GetHashCode()
GetObjectData Method void GetObjectData(System.Runtime.Serialization.SerializationInfo info, Syst...
GetType Method type GetType()
OnDeserialization Method void OnDeserialization(System.Object sender), void IDeserializationCallback....
Remove Method void Remove(System.Object key), void IDictionary.Remove(System.Object key)
ToString Method string ToString()
Item ParameterizedProperty System.Object Item(System.Object key) {get;set;}
Count Property int Count {get;}
IsFixedSize Property bool IsFixedSize {get;}
IsReadOnly Property bool IsReadOnly {get;}
IsSynchronized Property bool IsSynchronized {get;}
Keys Property System.Collections.ICollection Keys {get;}
SyncRoot Property System.Object SyncRoot {get;}
Values Property System.Collections.ICollection Values {get;}

Tested quickly it appears to return what I am expecting, a collection of hashtables.