Chapter 5. Exploring Application Programming Interface

Application Programming Interface (API) is a set of protocols, routines, and tools used to build software applications. The main purpose of API is data exchange and integration, whereas Software Development Kit (SDK) is customization. The type of API varies based on the data exchange and transport mechanism. The transport mechanism may be web-based, source code, or binary function.

Following are the most common types of API:

  • Web Services API
    • This is an API that is highly useful in up and coming technologies. It is hypertext-based and the standards used are REST, SOAP, XML-RPC, and JSON-RPC.
    • It is commonly used in web applications and service-oriented architecture (SOA).
  • Source code API
    • This offers libraries of objects, classes, and so on
    • It is commonly used in development projects
    • The standards used vary based on the platform, such as .NET or J2EE

In this chapter, we will cover the following topics:

  • Exploring API using PowerShell
  • The Exchange Web Services (EWS) API for managing online exchange, along with a demo involving purging items in mailbox folders and deleting items
  • The Lync 2013 / Skype for Business client-side API—installing the Lync API, exploring the client settings, automating test calls, and holding an IM conversation with contacts
  • Client server object model for managing SharePoint Online—installing client-side SDK
  • Exploring client-side object model (CSOM)
  • Manipulating SharePoint lists using CSOM in PowerShell

Developers use APIs to accomplish many tasks; using PowerShell, we can only achieve our tasks to some extent. For example, let's consider a scenario where we need to interact with a Windows API; to achieve this, we can use the Windows API. Most IT professionals don't use API considering the fact that it's meant for development. However, we can leverage APIs in Windows PowerShell to perform administration as well as development tasks.

In the following example, we will try to use the Windows API in PowerShell as a jump start. Let's take a look at the PowerShell way of playing with the User32.dll file.

The C++ code used is as follows:

BOOL WINAPI ShowWindow(
  _In_ HWND hWnd,
  _In_ int nCmdShow
);

In Windows PowerShell, we will use the Add-type command for this exercise. This is not a big deal! It's a pretty old concept. However, to begin, we need to know how PowerShell loads the standard assembly. Later in this topic, we will examine the managed assemblies as well. Run the following command:

Help Add-Type -Detailed

Yes, as like all other cmdlets, we need to first read the help document before we proceed further. Using the preceding result, we can explore the parameters and related information. Now, we will build a PowerShell script that performs a few actions on Windows, which is as follows:

Function Set-Window {
  Param(
    [Parameter(Mandatory = $true)]
    $ID
  )
  $code = @"
  [DllImport("user32.dll")]
  public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
  "@
  $demo = Add-Type -MemberDefinition $code -Name "Demo" -Namespace Win32Functions -PassThru
  $demo::ShowWindowAsync((Get-Process -id $ID).MainWindowHandle , 2)
}
Set-Window -ID $pid

How does this work? We created a PowerShell function named Set-Window, which accepts a parameter called ID. Run the following command:

$code = @"
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
"@

Using the previous snippet of code inside the here-string, we will import the user32.dll file and consume the ShowWinodAsync function. This accepts the following two overloads:

  • hWnd: An example of this is process information
  • nCmdShow: This is a set of valid parameters listed in the following table:

    Value

    Meaning

    SW_FORCEMINIMIZE

    11

    This minimizes a window even if the thread that owns the window is not responding. This flag should only be used while minimizing windows from a different thread.

    SW_HIDE

    0

    This hides the window and activates another window.

    SW_MAXIMIZE

    3

    This maximizes the specified window.

    SW_MINIMIZE

    6

    This minimizes the specified window and activates the next top-level window in the Z order.

    SW_RESTORE

    9

    This activates and displays the window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag while restoring a minimized window.

    SW_SHOW

    5

    This activates the window and displays it in its current size and position.

    SW_SHOWDEFAULT

    10

    This sets the show state based on the SW_ value specified in the STARTUPINFO (https://msdn.microsoft.com/en-us/library/windows/desktop/ms686331(v=vs.85).aspx) structure passed to the CreateProcess (https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx) function by the program that started the application.

    SW_SHOWMAXIMIZED

    3

    This activates the window and displays it as a maximized window.

    SW_SHOWMINIMIZED

    2

    This activates the window and displays it as a minimized window.

    SW_SHOWMINNOACTIVE

    7

    This displays the window as a minimized window. This value is similar to SW_SHOWMINIMIZED, except that the window is not activated.

    SW_SHOWNA

    8

    This displays the window in its current size and position. This value is similar to SW_SHOW, except that the window is not activated.

    SW_SHOWNOACTIVATE

    4

    This displays a window in its most recent size and position. This value is similar to SW_SHOWNORMAL, except that the window is not activated.

    SW_SHOWNORMAL

    1

    This activates and displays a window. If the window is minimized or maximized, the system restores it to its original size and position. An application should specify this flag while displaying the window for the first time.

To instantiate the ShowWindowAsnc function, we will use the Add-Type cmdlet and assign it to the $demo variable, as shown in the following command line:

$demo = Add-Type -MemberDefinition $code -Name "Demo" -Namespace Win32Functions -PassThru
$demo::ShowWindowAsync((Get-Process -id $ID).MainWindowHandle , 2)
Set-Window -ID $pid

As we used $pid while executing the function, the code will affect the current PowerShell console and minimize it. We can perform the advanced functions as required and build a PowerShell code with reference to the User32.dll file.

In this chapter, we will cover PowerShell and API use for Microsoft technologies such as SharePoint, Exchange, and Lync; so, for another short example of .NET, let's take a look at the speech API.

Note

Refer to the following URL for the System.Speech API:

https://msdn.microsoft.com/en-us/library/gg145021%28v=vs.110%29.aspx

Run the following command:

Add-Type -AssemblyName System.Speech
$speak = New-Object System.Speech.Synthesis.SpeechSynthesizer
$speak.Rate = 1
$speak.Speak("Welcome to PowerShell 5.0")

The preceding code will speak out the text in the last line:

"Welcome to PowerShell 5.0"

This command will perform the following functions:

  • It will load the System.Speech assembly
  • It will create a $speak object
  • It will control the speaking rate at 1
  • It will speak out the text

Exploring API using PowerShell

We considered a basic example of using the Windows API. There are different ways to use APIs in PowerShell based on the requirements. Windows PowerShell has the feature of interacting with .NET DLL files as well. Let's consider that you have a code that simply performs addition operations that we can load in PowerShell and then explores the methods. But why are we discussing DLL now? Here is a comparison of API and DLL:

API

DLL

Abstract

Concrete

In this, the interface is implemented by the software program

This is a method of providing APIs

An API is an interface to the library of code

DLL is nothing but a library of code

In short, DLL is a file format and a way to use API.

Let's take a look at a demo where we will use a custom DLL file in Windows PowerShell. For this, we will choose a class library in Visual C# and build a code that will simply add two given integers.

The C# code is as follows:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassLibrary2
{
    public class Class1
    {
        public static int sum(int a,int b)
        {
            return a + b;
        }
    }
}

Note that you can rename namespace and class, which helps others understand them. Here, we have selected the default options for demonstration purposes.

We can directly use this with the here-string, and with the help of the Add-Type cmdlet, we can call the sum function and add two integer values. Run the following command:

$code = @"
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ClassLibrary2
{
    public class Class1
    {
        public static int sum(int a,int b)
        {
            return a + b;
        }
    }
}
"@
Add-Type -TypeDefinition $code
[ClassLibrary2.Class1]::sum(34,45)

The output is illustrated in the following image:

Exploring API using PowerShell

Points marked in the figure can be explained as follows:

  • 1: Everything between @" and "@ is the here-string
  • 2: Here, we use the Add-Type cmdlet
  • 3: Using the TypeDefinition parameter, we specify the source code
  • 4: In the $code variable, we have our source code in the here-string format
  • 5: Here, we make use of the namespace, the class, and the sum method
  • 6: Here, it returns the output value

Now, in Visual Studio, compile the code and find the DLL file; in our case, we have the DLL file in the Temp folder, so we can use the following snippet of code in PowerShell:

Import-Module C:TempClassLibrary2ClassLibrary2inDebugClassLibrary2.dll
[ClassLibrary2.Class1]::sum(45,56)

Take a look at the following image:

Exploring API using PowerShell

Note that we have a Class keyword in WMF 5.0; we could use that. However, in PowerShell, we have a few constraints—refer to the WMF 5.0 release notes.

In the next topic, we will explore the EWS API for managing Exchange Online.

The EWS API for managing Exchange Online

The Exchange Web Services (EWS) Managed API provides a managed interface for developing .NET client applications that use EWS. Using the EWS Managed API, we can access most of the information stored in Office 365, Exchange Online, or the Exchange Server mailbox.

The EWS Managed API is now available as an open source project on GitHub. You can share your contributions and bug report bugs in GitHub.

Note

For the contributions, refer to the following link:

https://github.com/OfficeDev/ews-managed-api/blob/master/CONTRIBUTING.md

To report issues, refer to the following link:

https://github.com/OfficeDev/ews-managed-api/issues

For the MSDN documentation, refer to the following link:

https://msdn.microsoft.com/en-us/library/office/dd633710%28v=exchg.80%29.aspx

To download the EWS Managed API 2.2, refer to the following link:

http://www.microsoft.com/en-us/download/details.aspx?id=42951

The installation of the EWS Managed API is as simple as a click—click and it's done! For an easy reference and quick demo, we moved the DLL file to the C:TempEWS folder.

One of the easiest methods to explore the items in the mailbox folder is using the MSOnline module.

To connect to Exchange Online, we will use the following snippet of code:

Import-Module MSOnline
$O365Cred = Get-Credential
$O365Session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/?proxymethod=rps -Credential $O365Cred -Authentication Basic -AllowRedirection
Import-PSSession $O365Session
Connect-MsolService –Credential $O365Cred

Here is the PowerShell code:

Get-MailboxFolderStatistics -Identity "TargetMailBoxID" | Select FolderType , Name , ItemsinFolder

Refer to the following image:

The EWS API for managing Exchange Online

We installed the EWS API 2.2 and moved the DLL file to the desired location. On the EWS managed API, we can do this using the following code:

#Target MailboxID's
$MailboxNames =  "TargetMailID"
#Any Exchange Admin ID with appropriate permissions
$AdminID = "AdminID"
#Fetch password as secure string
$AdminPwd = Read-Host "Enter Password" -AsSecureString
#Load the Exchange Web Service DLL
$dllpath = "C:TempMicrosoft.Exchange.WebServices.dll"
[Reflection.Assembly]::LoadFile($dllpath)
#Create a Exchange Web Service
$Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1)
#Credentials to impersonate the mail box
$Service.Credentials = New-Object System.Net.NetworkCredential($AdminID , $AdminPwd)
foreach($MailboxName in $MailboxNames)
{
#Impersonate using Exchange WebService Class
$Service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)
$Service.AutodiscoverUrl($MailboxName,{$true})
#Assing EWS URL
$service.Url = 'https://outlook.office365.com/EWS/Exchange.asmx'
Write-Host "Processing Mailbox: $MailboxName" -ForegroundColor Green
#Fetch Root Folder ID
$RootFolderID = New-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Root, $MailboxName)
$RootFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service,$RootFolderID)
#Create a Folder View
$FolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1000)
$FolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
#Retrive the Information
$response = $RootFolder.FindFolders($FolderView)
$response | Select DisplayName , TotalCount , FolderClass
}

This returns the same output as shown in the following image, but provides in-depth information:

The EWS API for managing Exchange Online

You can spin up PowerShell and customize the scripting according to your needs.

At times, we may consider building a unique interface to collect and audit organization information such as AD, Mailbox, SharePoint, Lync, and so on. Let's accommodate PowerShell in C# to call the Exchange Online cmdlets; the reason for this is the unique and clean interface, which helps us query multiple sources. In the following example, we will obtain information from Exchange Online.

Here is a demo code that will print your Exchange Online user's display name and SMTP address:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Remoting;
using System.Management.Automation.Runspaces;
using System.Security;
using System.Collections.ObjectModel;
using System.Text;
namespace Office365
{
    class Program
    {
        static void Main(string[] args)
        {
            string username = "ExchangeAdminID";
            string password = "Password";
            System.Security.SecureString securepassword = new System.Security.SecureString();
            foreach (char c in password)
            {
                securepassword.AppendChar(c);
            }
            PSCredential credential = new PSCredential(username, securepassword);
            WSManConnectionInfo connectioninfo = new WSManConnectionInfo(new Uri("https://ps.outlook.com/powershell"), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credential);
            connectioninfo.AuthenticationMechanism = AuthenticationMechanism.Basic;
            //connectioninfo.AuthenticationMechanism = AuthenticationMechanism.Basic;
            connectioninfo.MaximumConnectionRedirectionCount = 2;
            //connectioninfo.MaximumConnectionRedirectionCount = 2;
            using (Runspace runspace = RunspaceFactory.CreateRunspace(connectioninfo))
            {
                runspace.Open();
                using (PowerShell powershell = PowerShell.Create())
                {
                    powershell.Runspace = runspace;
                    //Create the command and add a parameter
                    powershell.AddCommand("Get-Mailbox");
                    powershell.AddParameter("RecipientTypeDetails", "UserMailbox");
                    //powershell.
                    //Invoke the command and store the results in a PSObject collection
                    Collection<PSObject> results = powershell.Invoke();
                    foreach (PSObject result in results)
                    {
                        string createText = string.Format("Name: {0} Alias: {1} Mail: {2}", result.Properties["DisplayName"].Value.ToString(), result.Properties["Alias"].Value.ToString(), result.Properties["PrimarySMTPAddress"].Value.ToString());
                        System.IO.File.WriteAllText("C:\User.txt", createText);
                    }
                }
            }
        }
    }
}

The output is illustrated in the following image:

The EWS API for managing Exchange Online

Purging items in the mailbox folder

Most organizations are moving to cloud-based storage, and as we know, all Microsoft products have a PowerShell interface. This eventually helps both developers and administrators to perform tasks without using a GUI. Not only automating tasks, using PowerShell we troubleshoot issues, identify the root cause, and so on.

Let's consider an operational requirement to purge Lync contact entries. Ignore the technical background and requirements or designs such as unified contact stores and so on; all we need to know is how to consume the EWS API and explore objects. Perform the following steps:

  1. Get the target mailbox for which the items need to be purged.
  2. You will need the appropriate permission to perform this task. Connect with your exchange admin account and plan the authentication and security process based on your organization's rules.
  3. Pass the admin ID credentials.
  4. Load the Exchange Web Service DLL file. Run the following command:
    #Target MailboxID's
    $MailboxNames =  "TargetMailBoxID1" , "TargetMailBoxID1"
    #Any Exchange Admin ID with appropriate permissions
    $AdminID = "AdminID"
    #Fetch password as secure string
    $AdminPwd = Read-Host "Enter Password" -AsSecureString
    #Load the Exchange Web Service DLL
    $dllpath = "C:TempMicrosoft.Exchange.WebServices.dll"
    [Reflection.Assembly]::LoadFile($dllpath)
    

Now, perform the following steps:

  1. Create an Exchange Web service.
  2. Using the admin credentials, impersonate the target mailbox. Run the following command:
    #Create a Exchange Web Service
    $Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService([Microsoft.Exchange.WebServices.Data.ExchangeVersion]::Exchange2013_SP1)
    #Credentials to impersonate the mail box
    $Service.Credentials = New-Object System.Net.NetworkCredential($AdminID , $AdminPwd)
    

After this, perform the following steps:

  1. Impersonate each target mailbox using EWS.
  2. Assign the EWS URL.
  3. Retrieve the root folder ID.
  4. Traverse and get the folder view. Here, we will use 1000 items taking the possibility of throttling into consideration.
  5. Retrieve the folders from the view.
  6. Query the folder name with its class.
  7. Purge the items using soft delete; do not use hard delete as it makes it impossible to restore the items from the dumpster.
  8. Call the Load method. Run the following command:
    foreach($MailboxName in $MailboxNames)
    {
    #Impersonate using Exchange WebService Class
    $Service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $MailboxName)
    $Service.AutodiscoverUrl($MailboxName,{$true})
    #Assing EWS URL
    $service.Url = 'https://outlook.office365.com/EWS/Exchange.asmx'
    Write-Host "Processing Mailbox: $MailboxName" -ForegroundColor Green
    #Fetch Root Folder ID
    $RootFolderID = New-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::Root, $MailboxName)
    $RootFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service,$RootFolderID)
    #Create a Folder View
    $FolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1000)
    $FolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
    #Retrieve Folders from view
    $response = $RootFolder.FindFolders($FolderView)
    #Query Folder which has display name like Lync Contacts
    $Folder =  $response | ? {$_.FolderClass -eq 'IPF.Contact.MOC.QuickContacts'}
    $Folder | Select DisplayName , TotalCount
    #Purge the items
    $Folder.Empty([Microsoft.Exchange.WebServices.Data.DeleteMode]::SoftDelete, $false)
    $Folder.Load()
    }
    

Deleting items from the mailbox folder

Deleting items from the mailbox folder is almost similar to purging. We can delete items using the following lines of code:

$Folder.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::SoftDelete)
$Folder.Load()

We cannot remove the Lync contacts entries in Outlook by simply right–clicking and deleting. We need to purge the items and then delete the entries in the contact folders. However, we can't communicate to the users to perform the delete operations themselves after performing purge, so simply executing the preceding code will complete the task. Using the previously mentioned methods we can perform administration tasks remotely without the user's intervention.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset