Using Powershell’s new-webserviceproxy with Exchange Web Services
The other day I was working on a case where the customer was using VBScript and CDO 1.21 to make some changes in some mailboxes, and I couldn’t help but feel that we were working in the past. Don’t get me wrong, there’s a lot of tried and tested VBScript and CDO 1.21 code out there, but I found myself wondering what the “new” way to do this would be.
I started looking at using Powershell to automate a .Net HttpWebRequest to post to an EWS endpoint, and just build the SOAP requests myself (or leverage an XmlDocument), but while I was researching this I stumbled upon something slightly more interesting.
The version of Powershell that is included with the Windows 7 Beta includes a new cmdlet called new-webserviceproxy and it does exactly what it sounds like. You can point it at a wsdl file, and it auto-generates a proxy in a way that seems very similar to the Visual Studio auto-generated proxies.
The following is the result of a good deal of trial and error, but what you end up with is a output that displays some basic information about all of the emails in your inbox.
1: <# Untested sample code, use at your own risk! #>
3: ## Setup the Exchange Service Binding
4: $uri = "https://exchangeserver/ews/exchange.asmx"
5: $exchangeservicebinding = new-webserviceproxy -NameSpace "EWS" -URI $uri -UseDefaultCredential
6: $exchangeservicebinding.RequestServerVersionValue = new-object EWS.RequestServerVersion
7: $exchangeservicebinding.RequestServerVersionValue.Version = [EWS.ExchangeVersionType]::Exchange2007_SP1
8: $exchangeservicebinding.Url = $uri
10: ## Create and Populate the Parent Folder ID Collection
11: [EWS.DistinguishedFolderIdType]$parentfolderid = new-object EWS.DistinguishedFolderIdType
12: $parentfolderid.Id = [EWS.DistinguishedFolderIdNameType]::inbox
13: [EWS.BaseFolderIdType[]]$parentfolderids = $parentfolderid
15: ## Create an ItemShape and set it to return All Properties
16: [EWS.ItemResponseShapeType]$itemshape = new-object EWS.ItemResponseShapeType
17: $itemshape.BaseShape = [EWS.DefaultShapeNamesType]::AllProperties
19: ## Create the FindItemType object and populate with the Parent Folder Ids and Item Shape
20: [EWS.FindItemType]$finditemtype = new-object EWS.FindItemType
21: $finditemtype.ParentFolderIds = $parentfolderids
22: $finditemtype.ItemShape = $itemshape
24: ## Make the call to the webservice
25: [EWS.FindItemResponseType]$finditemresponses = $exchangeservicebinding.FindItem($finditemtype)
27: ## Loop through the returned messages and print some basic info
28: [EWS.MessageType]$messagetype
29: foreach($messagetype in $finditemresponses.ResponseMessages.Items[0].RootFolder.Item.Items)
31: Write-Host "From: " $messagetype.From.Item.Name
32: Write-Host "Subject: " $messagetype.Subject
33: Write-Host "Received: " $messagetype.DateTimeReceived.Date
34: Write-Host "-------------------------------------------------------"
35: Write-Host "ItemId: " $messagetype.ItemId.Id
36: Write-Host "======================================================="
The above code obviously has no error handling, but hopefully it shows a basic example of how this new cmdlet can be used.
If you want to dig in further, make use of the get-member cmdlet to examine objects of the types that are generated by the proxy, and you can also inspect the object using format-custom (alias fc) as follows (This can be done for any of the object types in the above code):
1: $exchangeservicebinding | get-member
2: $exchangeservicebinding | fc
Note: I did notice some strange errors if I run the above code multiple times within the same powershell session. I’ll update this post if I figure it out why, but if you receive errors about missing DLLs or if powershell claims that it “Can’t convert from type “EWS.FindItemType” to “EWS.FindItemType” then try starting a new PowerShell session.