Difference between revisions of "PowerShell API Wrapper Tutorial"

[unchecked revision][checked revision]
Line 11: Line 11:
  
 
* [[Media:MailStore_SPE_Scripting_Tutorial.zip|MailStore PowerShell API Wrapper and tutorial example scripts]]
 
* [[Media:MailStore_SPE_Scripting_Tutorial.zip|MailStore PowerShell API Wrapper and tutorial example scripts]]
* [http://www.microsoft.com/en-us/download/details.aspx?id=34595 Windows Management Framework 3.0] (contains PowerShell 3.0)
+
* [https://docs.microsoft.com/en-us/powershell/wmf Windows Management Framework] for your Operating System which includes the PowerShell
* [http://www.microsoft.com/en-us/download/details.aspx?id=40855 Windows Management Framework 4.0] (alternatively, contains PowerShell 4.0)
 
  
 
Please take note of the system requirements and further notices for the respective version of the Windows Management Framework.
 
Please take note of the system requirements and further notices for the respective version of the Windows Management Framework.

Revision as of 10:57, 15 January 2018


Important notice: The PowerShell API wrapper for the MailStore Server Administration API provided on this website is to be regarded as an example implementation of an API client. This wrapper should help system administrators and developers to quickly understand how MailStore Server Administration API calls work and how to use them in their own scripts.
Please understand that beyond this documentation no further support for the Powershell API wrapper is provided. Unless stated otherwise, the PowerShell API wrapper as well as all related example scripts are released under the terms and conditions of the MIT License.


This tutorial aims to explain the usage of the MailStore Service Provider Edition Management API through simple Windows PowerShell example scripts. Basic knowledge of MailStore Server, Windows and PowerShell is a necessary precondition. In order to prevent loss of data, service interruption or other problems, it is highly recommended to use a non-productive test environment for this tutorial as well as for script development in general.

Installation of Necessary Components

The examples demonstrated here use the MailStore PowerShell API Wrapper and are compatible with Windows PowerShell 3.0 and higher. Depending on your version of Windows it might be necessary to download and install a compatible version of PowerShell first. You can find the components necessary for this tutorial here:

Please take note of the system requirements and further notices for the respective version of the Windows Management Framework.

Important Notice: Installation of a Windows Management Framework on systems that require a specific version of Windows PowerShell, such as Microsoft Exchange Servers, is not supported and may lead to massive system failures and data loss.

After downloading and installing Windows PowerShell (if necessary) please unzip the MailStore PowerShell API Wrapper and the example scripts (to C:\MailStore SPE Scripting Tutorial\PowerShell\ by default).

Neither the MailStore PowerShell API Wrapper nor the example scripts are digitally signed, therefore execution of such scripts has to be enabled in an administrative PowerShell session using

  Set-ExecutionPolicy -ExecutionPolicy Unrestricted

Importing the MailStore PowerShell API Wrapper

The MailStore PowerShell API Wrapper is implemented as a PowerShell Script Module (MS.PS.Lib.psm1) and can thus be imported in a PowerShell session via its manifest (MS.PS.Lib.psd1) by using Import-Module.

Please open a PowerShell session and import the API wrapper module using this command:

  Import-Module "C:\MailStore SPE Scripting Tutorial\PowerShell\API-Wrapper\MS.PS.Lib.psd1"

Getting Information about the MailStore PowerShell API Wrapper

The MailStore PowerShell API Wrapper provides several functions to access the MailStore SPE Management API, following PowerShell conventions. Enter the following command to get information about these features:

  Get-Module MS.PS.Lib | fl

More detailed information is available via the module's properties. For example,

  (Get-Module MS.PS.Lib).ExportedFunctions

returns the functions provided by the module. Via

  Get-Help *MSApi*

the MailStore PowerShell API Wrapper returns inline help for all its functions.

Calling API Wrapper Functions

The following example script (Example1.ps1 in the tutorial package) explains the basic usage of MailStore PowerShell API Wrapper functions.

  Import-Module '..\API-Wrapper\MS.PS.Lib.psd1'
  $MSApiClient = New-MSApiClient -Username "admin" -Password "admin" -ManagementServer "localhost" -Port 8474 -IgnoreInvalidSSLCerts
  $return = Invoke-MSApiCall $MSApiClient "GetEnvironmentInfo"
  $return | fl

The function New-MSApiClient creates a new API client object, which is used by the Invoke-MSApiCall function for API calls. The values for -Username and -Password have to be supplied, while -ManagementServer defaults to "localhost" and -Port defaults to "8474". The switch -IgnoreInvalidSSLCerts has to be set if untrusted certificates are used; otherwise an error occurs.

Apart from the API client object, Invoke-MSApiCall needs an API command and its parameters if applicable. The command GetEnvironmentInfo in the script does not have any parameters and returns a JSON object as follows:

 error           : 
 token           : 
 statusVersion   : 2
 statusCode      : succeeded
 percentProgress : 
 statusText      : 
 result          : @{version=9.1.0.10258; copyright=Copyright (c) 2005-2014 MailStore Software GmbH; licenseeName=MailStore; licenseeID=23634; serverName=tutorial.mailstore.test; userName=admin; systemProperties=}
 logOutput       :  

The result property of that object has the actual return value if the request succeeded as indicated by the statusCode:

 version          : 9.1.0.10258
 copyright        : Copyright (c) 2005-2014 MailStore Software GmbH
 licenseeName     : MailStore Software GmbH
 licenseeID       : 23634
 serverName       : tutorial.mailstore.test
 userName         : admin
 systemProperties : @{processors=System.Object[]; totalPhysicalMemory=2146947072; operatingSystem=Microsoft Windows Server 2012 Standard}
 

Calling API Wrapper Functions with Parameters

For most MailStore SPE Management API commands you need to provide parameters. Of course, the MailStore PowerShell API Wrapper's Invoke-MSApiCall function can submit these parameters, as demonstrated by the following script (Example2.ps1 in the tutorial package):

  Import-Module '..\API-Wrapper\MS.PS.Lib.psd1'
  $MSApiclient = New-MSApiClient -Username "admin" -Password "admin" -ManagementServer "localhost" -Port 8474 -IgnoreInvalidSSLCerts
  $instances = (Invoke-MSApiCall $MSApiclient "GetInstances" @{instanceFilter = "*"}).result
  foreach ($instance in $instances) {
      $users = (Invoke-MSApiCall $MSapiclient "GetUsers" @{instanceID = $instance.instanceID}).result
      foreach ($user in $users) {
          (Invoke-MSApiCall $MSapiclient "GetUserInfo" @{instanceID = $instance.instanceID; userName = $user.userName}).result | fl
      }
  }

The scripts lists details about the users created in the MailStore SPE instances. Because the MailStore PowerShell API Wrapper converts API responses into objects, their properties can be used directly in the script's workflow. The function Invoke-MSApiCall expects parameters as a hashtable, e.g. @{parametername1 = value1; parametername2 = value2;...}. Parameter names are case sensitive.

First, a list of all MailStore SPE instances is requested with the API command GetInstances. This command returns an array of instances as follows:

 instanceID     : test01
 alias          : tutorial
 displayName    : Tutorial Test Instance
 instanceHost   : tutorial.mailstore.test
 startMode      : automatic
 processID      : 3140
 status         : running
 startStopError : 

The script now iterates over this array using the instanceID property of each entry as a parameter for the API command GetUsers. The list of users of each instance is then also iterated over and each user's properties are requested via GetUserInfo.

For the entry listed above the result could be as follows:

 userName            : johndoe
 fullName            : John Doe
 distinguishedName   : 
 authentication      : integrated
 emailAddresses      : {}
 pop3UserNames       : {}
 privileges          : {login, changePassword}
 privilegesOnFolders : {@{folder=johndoe; privileges=System.Object[]}}

As can be seen in the privilegesOnFolders property, returned objects may be nested and may also contain further objects.

Handling Asynchronous API Calls

The server may decide to execute Management API commands asynchronously if their execution takes more time. The MailStore PowerShell API Wrapper identifies calls of such asynchronously executed API commands and executes them as PowerShell Jobs in the background.

Waiting for Asynchronous API Calls to Complete

A script's execution can be interrupted until a PowerShell Job created by the API wrapper terminates as demonstrated by the following script (Example3.ps1 in the tutorial package):

  Import-Module '..\API-Wrapper\MS.PS.Lib.psd1'
  $MSApiclient = New-MSApiClient -Username "admin" -Password "admin" -ManagementServer "localhost" -Port 8474 -IgnoreInvalidSSLCerts
  $instances = (Invoke-MSApiCall $MSApiclient "GetInstances" @{instanceFilter = "*"}).result
  $return = Invoke-MSApiCall $MSApiclient "VerifyStore" @{instanceID = $instances[0].instanceID; id = "1"}
  $return | fl

The API commands GetInstances and VerifyStore called in the script are regularly run asynchronously by the server. By using Invoke-MSApiCall the API wrapper waits for an API command that is executed asynchronously and simply returns its final result:

 error           : 
 token           : sa4c1dd3dcf56da32e44b29215b4d60b2b
 statusVersion   : 152
 statusCode      : succeeded
 percentProgress : 100
 statusText      : 
 result          : 
 logOutput       : 

Subscribing to Events Triggered by Asynchronous API Calls

Instead of interrupting a script's execution, the PowerShell Jobs created by the API wrapper can be reacted to while they are running in the background. These jobs trigger a PowerShell EngineEvent with each status request that the script can subscribe to in order to execute further code on each occurrence. To demonstrate this, the previous script needs to be adapted only a bit (Example4.ps1 in the tutorial package):

  Import-Module '..\API-Wrapper\MS.PS.Lib.psd1'
  $MSApiclient = New-MSApiClient -Username "admin" -Password "admin" -ManagementServer "localhost" -Port 8474 -IgnoreInvalidSSLCerts
  $instances = (Invoke-MSApiCall $MSApiclient "GetInstances" @{instanceFilter = "*"}).result
  $return = Start-MSApiCall $MSApiclient "VerifyStore" @{instanceID = $instances[0].instanceID; id = "1"}
  if ($return.statusCode -eq "running") {
      $mssevent = Register-EngineEvent -SourceIdentifier $return.Token -Action {write-host $event.MessageData}
  } else {
      $return | fl
  }

By using Start-MSApiCall the API wrapper runs an API command that is executed asynchronously by the server in the background and returns its first result. The script subscribes to the event that is triggered by the background job via Register-EngineEvent, using the return object's Token property as SourceIdentifier. By that property the event relates to the triggering PowerShell Job and thus to the server process. The Action script block is itself created as a PowerShell Job that is executed with each triggering of the event. Through the MessageData property of the $event automatic variable the script block can access the JSON object provided by the background job. That object contains the status of the server process:

 @{error=; token=sae8b8eaa3f645d11ee0207797cebbc0b1; statusVersion=8;
   statusCode=running; percentProgress=1; statusText=; result=;
   logOutput=  300 messages verified...
  }

Via these mechanisms the script can execute further tasks while monitoring the server process in the background. Execution and handling of multiple asynchronous API commands is also possible this way.

Cancelling Asynchronous API Wrapper PowerShell Jobs

To cancel the execution of an asynchronous API command, use Stop-MSApiCall with either the token or the JSON object. For the example above the call would be:

  Stop-MSApiCall $MSApiclient -AsyncReturnObject $return