RobO
RobO

Reputation: 450

Using non-standard parameter data types in Powershell advanced functions

I've noticed that most Powershell advanced functions declare parameters of standard datatypes (string, int, bool, xml, array, hashtable, etc.) which map to specific .Net types.

How would one declare an advanced function parameter using another .Net data type? For example, here is a contrived example:

function Do-Something
{
    [CmdletBinding()]
    Param(        
        [System.Xml.XPathNodeList] $nodeList
    )

    Begin {}
    Process 
    {    
        Foreach ($node in $nodeList)
        {
            Write-Host $node
        }        
    }
    End {}
}        

# Prepare to call the function:
$xml = [xml](get-content .\employee.xml)
$nodeList = $xml.SelectNodes("//age")

# Call the function passing an XPathNodeList:
do-something $nodeList

Invoking this function results in the following runtime error:

Unable to find type [System.Xml.XPathNodeList]: make sure that the assembly
containing this type is loaded.

Can this be accomplished with LoadWithPartialName()? How?

Assuming this is possible, here's an ancillary question: would using non-standard types this way go against 'best practice'?

Upvotes: 1

Views: 4091

Answers (2)

Keith Hill
Keith Hill

Reputation: 202092

It is OK to use custom .NET types as long as you use something like the cmdlet Add-Type to load the assembly that defines the custom type. However in this case, the assembly, System.Xml, is already loaded. Your problem arises because the type you specified is a private type i.e. only visible within the System.Xml assembly.

PS> $nodeList.GetType()

IsPublic IsSerial Name                     BaseType
-------- -------- ----                     --------
False    False    XPathNodeList            System.Xml.XmlNodeList

Use its public base class instead:

[CmdletBinding()]
Param(
    [Parameter()]        
    [System.Xml.XmlNodeList] 
    $nodeList
)

Upvotes: 2

Ian Pugsley
Ian Pugsley

Reputation: 1062

You shouldn't have any issues with using standard .NET objects as function parameters - the error you're getting is associated with unloaded assemblies, and that's where I'd look. Check your profile to make sure there's nothing unusual happening - see http://msdn.microsoft.com/en-us/library/bb613488%28v=vs.85%29.aspx for details.

If it really comes to it, you can use the following to load System.Xml (casting to Void to suppress the text output of loading):

[Void][System.Reflection.Assembly]::LoadWithPartialName("System.Xml")

Upvotes: 0

Related Questions