Using WCF proxies in Powershell

powershellI came across this handy link a few months ago and it proved mighty useful for testing/calling WCF services from Powershell – a task not to be taken lightly as it turns out:

http://www.justaprogrammer.net/2012/02/11/using-powershell-to-call-a-wcf-service/

However, for some reason, the site has not been up that much lately so I’ll just post the source code found there over here, credits go to Just a Programmer – this is just for my (and eventually your) reference.

    
     
    # load WCF assemblies
    Add-Type -AssemblyName "System.ServiceModel"
    Add-Type -AssemblyName "System.Runtime.Serialization"
     
    
    function global:Get-WsdlImporter([CmdletBinding()][Parameter(Mandatory=$true, ValueFromPipeline=$true)][string]$WsdlUrl, [switch]$HttpGet)
    {
            if($HttpGet)
            {
                    $local:mode = [System.ServiceModel.Description.MetadataExchangeClientMode]::HttpGet
            }
            else
            {
                    $local:mode = [System.ServiceModel.Description.MetadataExchangeClientMode]::MetadataExchange
            }
           
            $mexClient = New-Object System.ServiceModel.Description.MetadataExchangeClient([Uri]$WsdlUrl, $mode);
            $mexClient.MaximumResolvedReferences = [System.Int32]::MaxValue
            $metadataSet = $mexClient.GetMetadata()
            $wsdlImporter = New-Object System.ServiceModel.Description.WsdlImporter($metadataSet)
           
            return $wsdlImporter   
    }
     
    
    function global:Get-WcfProxyType(
            [CmdletBinding()]
            [Parameter(ParameterSetName='WsdlImporter', Position=0, Mandatory=$true, ValueFromPipeline=$true)][ServiceModel.Description.WsdlImporter] $WsdlImporter,
            [Parameter(ParameterSetName='WsdlUrl', Position=0, Mandatory=$true, ValueFromPipeline=$true)][string] $WsdlUrl,
            [string] $proxyPath
    ) {
            switch ($PsCmdlet.ParameterSetName)
            {
                    "WsdlUrl" {
                            $WsdlImporter = Get-WsdlImporter $WsdlUrl
                            trap [Exception]
                            {
                                    $WsdlImporter = Get-WsdlImporter $WsdlUrl -HttpGet
                                    continue
                            }
                            break
                    }
                    "WsdlImporter" { break }
            }
           
            $generator = new-object System.ServiceModel.Description.ServiceContractGenerator
           
            foreach($contractDescription in $wsdlImporter.ImportAllContracts())
            {
                    [void]$generator.GenerateServiceContractType($contractDescription)
            }
           
            $parameters = New-Object System.CodeDom.Compiler.CompilerParameters
            if($proxyPath -eq $null)
            {
                    $parameters.GenerateInMemory = $true
            }
            else
            {
                    $parameters.OutputAssembly = $proxyPath
            }
           
            $providerOptions = New-Object "Collections.Generic.Dictionary[String,String]"
            [void]$providerOptions.Add("CompilerVersion","v3.5")
           
            $compiler = New-Object Microsoft.CSharp.CSharpCodeProvider($providerOptions)
            $result = $compiler.CompileAssemblyFromDom($parameters, $generator.TargetCompileUnit);
           
            if($result.Errors.Count -gt 0)
            {
                    throw "Proxy generation failed"      
            }
           
            return $result.CompiledAssembly.GetTypes() | Where-Object {$_.BaseType.IsGenericType -and $_.BaseType.GetGenericTypeDefinition().FullName -eq "System.ServiceModel.ClientBase``1" }
    }
     
    
    function global:Get-WcfProxy(
            [CmdletBinding()]
            [Parameter(ParameterSetName='WsdlImporter', Position=0, Mandatory=$true, ValueFromPipeline=$true)][ServiceModel.Description.WsdlImporter] $WsdlImporter,
            [Parameter(ParameterSetName='WsdlUrl', Position=0, Mandatory=$true, ValueFromPipeline=$true)][string] $WsdlUrl,
            [Parameter(Position=1, Mandatory=$false)][string] $EndpointAddress = $null,
            [Parameter(Position=2, Mandatory=$false)][System.ServiceModel.Channels.Binding] $Binding = $null
    ) {
            if ($Binding -ne $null -and [string]::IsNullOrEmpty($EndpointAddress)) {
                    throw New-Object ArgumentNullException '$EndPointAddress', 'You cannot set $Binding without setting $EndpointAddress.'
            }
           
            switch ($PsCmdlet.ParameterSetName)
            {
                    "WsdlUrl" {
                            $WsdlImporter = Get-WsdlImporter $WsdlUrl
                            trap [Exception]
                            {
                                    $WsdlImporter = Get-WsdlImporter $WsdlUrl -HttpGet
                                    continue
                            }
                            break
                    }
            }
           
            $proxyType = Get-WcfProxyType $wsdlImporter;
           
            if ([string]::IsNullOrEmpty($EndpointAddress)) {
                    $endpoints = $WsdlImporter.ImportAllEndpoints();
                    $Binding = $endpoints[0].Binding;
                    $EndpointAddress = $endpoints[0].Address;
            }
           
            return New-Object $proxyType($Binding, $EndpointAddress);
    }
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s