Using PowerShell to call a WCF service

PowerShell lets you create web service proxies from WSDLs via the New-WebServiceProxy cmdlet. However, it only works for SOAP web services running on HTTP endpoints. If you have a WCF service using only non http protocols, such as NetTcp, you cannot use New-WebServiceProxy.

Now, I’ve created and consumed my fair share of web services. So when I began to use PowerShell, I quickly figured out this unfortunate fact. I always knew that I could make use of WCF API to generate the proxies, but I never bothered to figure out how. The annoyance was pretty academic to me. At some point I event told someone on stackoverflow that it can’t be done.

Then on Friday, I accidentally discovered that a Sharepoint MVP by the name of Christian Glessner solved this problem in 2008 while visiting the excellent site poshcode.org. Christian explains his solution in detail on his blog.

His solution was a very elegant PowerShell 1.0 solution. However, I felt it could be improved by adding some PowerShell 2.0 features such as parameter collections. I also was really intrigued and wanted to dig into his solution. He was supportive of my initial modifications so I put the git repo of my changes on the justaprogrammer github organization.

Using my version

My version of the script creates three functions:

  • Get-WsdlImporter
  • Get-WcfProxyType
  • Get-WcfProxy

The function that is most analogous to New-WebServiceProxy is Get-WcfProxy. I kept the name from Christian’s version of the code, despite the fact that New-WcfProxy would be more appropriate. In Christian’s version of the code, Get-WcfProxy only returned a System.Type of the generated proxy, not an instance of it. I renamed that to Get-WcfProxyType. Finally. Get-WsdlImporter takes a wsdl or mex endpoint and returns an instance of a System.ServiceModel.Description.WsdlImporter that represents that metadata.

By default Get-WsdlImporter tries to generate the WsdlImporter via metadata exchange, but it can parse a wsdl with the -HttpGet switch. Below are some examples illustrating its usage:

$wsdlImporter = Get-WsdlImporter 'http://localhost:14232/EchoService.svc/mex' # Mex endpoint
Get-WsdlImporter 'http://localhost:14232/EchoService.svc' -HttpGet # WDSL endpoint
Get-WsdlImporter 'http://localhost:14232/EchoService.svc?wsdl' -HttpGet # WSD: endpoint 

I don’t see much point for calling Get-WcfProxyType directly so I will not illustrate how to use it here. Get-WcfProxy is the function you want to call. Its main parameter is either a url or a WsdlImporter. You can either let Get-WcfProxy pick the first endpoint it finds in the WsdlImporter, or specify an endpoint and url you want to use as parameters as illustrated below:.

$wsdlImporter = Get-WsdlImporter "http://localhost:14232/EchoService.svc/mex"
$proxy = Get-WcfProxy $wsdlImporter # using a WsdlImporter object
$proxy = Get-WcfProxy "http://$($hostname):14232/EchoService.svc/mex" # using a url
$proxy = Get-WcfProxy $wsdlImporter "http://localhost:14232/EchoService.svc/WCF" (New-Object System.ServiceModel.WSHttpBinding) # using a WsdlImporter and specifying the endpoint and binding.
$proxy = Get-WcfProxy 'net.tcp://localhost:8732/EchoService/mex' 'net.tcp://localhost:8732/EchoService/' (New-Object System.ServiceModel.NetTcpBinding) # using a metadata url and specifying the endpoint and binding.
$proxy.Echo("Justin Dearing"); # calling a service function

As you might have guessed from my examples I used the justaprogrammer EchoService in my tests.

The code itself

I recommend you refer to the github repo for the latest version of the code. However, the version I used here is posted on poshcode.org and embedded below.

Future directions

My fork is released under the MIT license and I’d be happy to review patches and consider bug reports and feature requests.