June 8th, 2021

Microsoft Graph Mailbag – A deeper look into the Microsoft Graph PowerShell SDK

In today’s Microsoft Graph Mailbag post, we’ll continue our dive into the Microsoft Graph PowerShell SDK. 

Please be sure to follow this blog series using https://aka.ms/MSGraphMailbag or with RSS using https://developer.microsoft.com/graph/blogs/feed/?tag=MSGraphMailbag.

Introduction 

In my last post, we started to look at the Microsoft Graph PowerShell SDK and using it to interact with Microsoft Graph using some simple examples. In this post we’ll familiarize ourselves with navigating the SDK and using core Microsoft Graph functionality.

Navigation 

The Microsoft Graph API surface is very large with thousands of endpoints.  Hence, the PowerShell SDK contains thousands of cmdlets (or commandlets) split between dozens of modules. Because of this, it can be difficult to identify the correct cmdlet needed to perform a specific query. 

We can use the PowerShell Get-Command cmdlet to search against the PowerShell SDK to get a list of available commands. Additionally, we can search for specific words to help narrow our search. For example, we may want to look up all calendar events for a specific user. We can search for all commands that include the word “calendar” from the PowerShell SDK: 

Get-Command -Module Microsoft.Graph* *calendar*

Get-Command -Module Microsoft.Graph* *calendar*

This limits the number of commands we need to review from thousands to a more manageable number, making it easier to find the applicable cmdlet. 

For those not familiar, PowerShell cmdlets use a format of ‘verb-[optionalPrefix]noun’. The Microsoft Graph PowerShell API has followed this naming convention as well, mapping the http request methods to the verb portion of the PowerShell command. A GET method maps to a ‘Get’ PowerShell command. POST and PUT methods map to a ‘New’ or ‘Add’ PowerShell command. The PATCH method maps to an ‘Update’ or ‘Set’ command. And the DELETE method maps to a ‘Remove’ command. 

We can use Get-Command to further filter results by verb and / or noun.  Wildcards can be used with an asterisk (*). 

Get-Command -Module Microsoft.Graph -Verb “Get”
Get-Command -Module Microsoft.Graph -Noun “Drive*”

Once we’ve found the correct command, we can use the PowerShell Get-Help cmdlet to see what parameters are available to perform the desired request. 

Get-Help Get-MgUserCalendarEvent -Detailed

Get-Help Get-MgUserCalendarEvent -Detailed

With the help of the Microsoft Graph API documentation and a tool like Graph Explorer or Postman, we can use this information to determine the correct command and syntax to use within our script. 

Now that we are familiar with navigating the SDK, let’s look at using the SDK for some of the core features available with Microsoft Graph.

Query Parameters 

A powerful feature of the Microsoft Graph API is the ability to use OData system query parameters to control the data that is returned. In a RESTful request, these are built as part of the URI that is submitted. The  PowerShell SDK makes these query options available through command parameters like -Filter or -Search. For example, if we want to return a message based on an email message ID, we can run the following command which makes use of the -Filter parameter (similar to the $filter query parameter): 

Get-MgUserMessage -UserId meganb@contoso.onmicrosoft.com -Filter "InternetMessageId eq '<860c02d9-abd8-4943-9116-e64745cc6840@az.southcentralus.production.microsoft.com>'"

Example of Get-MgUserMessage -UserId

Now, instead of returning all messages in a mailbox, we return only messages that match the filter (in this case one specific message). Scoping our request to a specific need and making it more efficient at the same time.

Paging 

For anyone who has submitted a Microsoft Graph API request, you are likely familiar with paging. Some queries return a great deal of information so the data is returned using multiple pages.Or, perhaps you’ve used the $top query parameter to specify the number of results returned causing manual paging of the results. Either way, to ensure we get all the data from our query, we need to make sure we process all the returned pages. 

Typically, we would look for an @odata.nextlink property in the response and follow the contained URL to view the next page of results. And if we are building a RESTful query, we would need to build that logic into our script. 

With the  PowerShell SDK, however, paging is much simpler to deal with. Just like with the RESTful request, we can specify the $top query by using the -Top parameter. We can use -Top with the -Skip parameter to build logic for manually paging results. Additionally, there is a -PageSize parameter that controls the number of results returned per page. 

The real power, in my opinion, is the -All parameter. This allows queries made with the  PowerShell SDK to automatically process paging and return all the results of the query with no need to build logic around the @odata.nextlink property creating a simpler scripting experience.

Throttling 

Like most cloud-based services, there are safeguards put in place to protect the services and Microsoft Graph is no exception. Throttling protects the service by limiting the number of requests that can be performed within a specific timeframe / concurrently / etc. 

Microsoft Graph documentation shows service specific limits and as well as best practices to handle throttling. When throttling occurs, Microsoft Graph sends HTTP status code 429 (Too many requests) in the response. Many service APIs also provide a Retry-After response header that provides a wait time to be used for delaying our requests. Luckily, the Microsoft Graph PowerShell SDK implements retry logic for us. It will automatically handle 429 status code responses as well as the Retry-After response header, saving us the need to manually process those responses and adjust requests.

Manual Requests 

Despite the coverage of the Microsoft Graph PowerShell SDK, there may be instances where we need to send a specific Microsoft Graph request that is not covered by the SDK.  In this case, we still have the ability to perform a RESTful web request using the SDK. The Invoke-MgGraphRequest cmdlet (similar to Invoke-RestMethod command), provides us the ability to specify a URI, Method, Headers, and Body to submit a request. Since it is an SDK cmdlet, we can utilize the authentication, access token management, and more. 

An example of where this functionality might be useful is performing a batch request. Currently, there is no batch command within the SDK, but with Invoke-MgGraphRequest, we can utilize that functionality if we desire. By building an HTTP request and submitting it via Invoke-MgGraphRequest, we are able to perform a batch request: 

Invoke-MgGraphRequest -Method POST -Uri “https://graph.microsoft.com/v1.0/$batch” -Body $body | ConvertTo-Json)

In this case we are submitting a POST request for a batch process and passing in the JSON formatted batch commands to the body of the request. This gives us the Microsoft Graph API batching functionality through the PowerShell SDK.

Conclusion 

In this post, we took a step further into the Microsoft Graph PowerShell SDK including finding the correct cmdlet, using query parameters, paging results, handling throttling, and issuing manual requests. With this we can begin to utilize the Microsoft Graph PowerShell SDK in our scripts and applications. Until next time! 

Today’s post was written by Matt Krause, Customer Engineer (CE) at Microsoft. You can follow Matt on Twitter @mattckrause. Join us for our next post on June 22, 2021.