Adding support for selecting ALL properties using '*' wildcard in Mg Graph commands 'property' parameter
Table of contents
Problem
You may have noticed that Microsoft Graph SDK commands like Get-MgUser
, Get-MgDevice
, etc don't retrieve all properties by default. ๐
All object properties are returned, but most of them are empty.
What you need to do, is explicitly specify all properties you want to retrieve ๐
This approach has at least two problems:
Only properties you explicitly specify are returned (check
BusinessPhones
property โ) a.k.a. you always need to specify "obvious" properties likename
,id
, etc which you'll need in 99% of situations anyway, plus required "extra" propertiesYou can use the wildcard '*' in the command
property
parameter, however, '*' doesn't return all properties as we are used to from AzureAD cmdlets. Instead '*' returns only a small subset of all properties as can be seen in theGet-MgUser -Debug
example below ๐
TL;DR
Use my proxy function Get-MgUser2
from my module PowerShell MSGraphStuff.
It supports the usage of '*' in the property
parameter and unlike the official Get-MgUser
command, returns all properties.
Solution
OK, so how can we easily return all properties without explicitly specify one by one?
Oneliner
What can come to your mind is to retrieve all available property names using Get-Member
command right? So code like this should do the job
$mgUserProperty = Get-MgUser -Top 1 | Get-Member -MemberType NoteProperty, Property | select -ExpandProperty Name
Unfortunately, when we try to retrieve all available properties, Get-MgUser
will fail with the error: "No OData route exists that match template ~/entityset/key with http verb GET for request /StatelessOnboardingService/users..."
I found out that it is caused by the property DeviceEnrollmentLimit
, which therefore needs to be excluded.
Ok, next round. Now we try to get all properties without DeviceEnrollmentLimit
. But it errors again ๐
Uncle Google gives me the answer for this error. It is caused by the property MailboxSettings
which can be gathered only if you call Get-MgUser
upon the account that was used for authentication to Graph API.
Ok, next round, and finally we have all properties returned without any error ๐
# get all available property names
$mgUserProperty = Get-MgUser -Top 1 | Get-Member -MemberType Property | select -ExpandProperty Name
# return all properties (without the problematic ones)
Get-MgUser -UserId johnd@contoso.com -Property ($mgUserProperty | ? {$_ -notin 'DeviceEnrollmentLimit', 'MailboxSettings'})
Proxy function
As we saw in the previous section there are properties that cause troubles therefore simple oneliner cannot be used. So I've decided to create a proxy function Get-MgUser2
that alters how the original Get-MgUser
handles '*' wildcard in the property
parameter and at the same time solve issues with properties DeviceEnrollmentLimit, MailboxSettings
.
Get-MgUser2
function is part of my PowerShell module MSGraphStuff, feel free to install it using Install-Module
.
How proxy function Get-MgUser2 was created?
There are a lot of tutorials about creating PowerShell proxy functions. I've personally used this one.
In general, you retrieve the original function metadata (not the function code itself), wrap it into the new function and customize it as you like.
- Code for creating a proxy function (in this case
Get-MgUser2
from originalGet-MgUser)
.
# name of the function you want to create proxy function for
$originalCmdletName = "Get-MgUser"
# name of the new proxy function
$proxyFunctionName = "$originalCmdletName`2"
# where ps1 file with proxy function will be saved
$proxyFunctionLocation = "C:\proxyFunctions"
# get original command metadata
$metadata = New-Object System.Management.Automation.CommandMetaData (Get-Command $originalCmdletName)
# use metadata to create proxy function and save the result to the file
$proxyFunctionBody = @"
function $proxyFunctionName {
$([System.Management.Automation.ProxyCommand]::Create($metadata))
}
"@
# create proxy function definition and save it in C:\proxyFunctions\Get-MgUser2.ps1 file
[Void][System.IO.Directory]::CreateDirectory($proxyFunctionLocation)
$proxyFunctionBody | Out-File "$proxyFunctionLocation\$proxyFunctionName.ps1"
Code can be used to create a proxy function for any command, just replace value in
$originalCmdletName
variable
Now that we have the proxy function definition, we need to customize it to suit our needs. A.k.a. if '*' wildcard will be used in the
property
parameter: retrieve all available properties (without the problematic ones) and use them instead of '*'. The screenshot below shows what I've added to make it happen.
And that's it. The same approach can be used to create any proxy function ๐.
TIP: pipe output of Graph commands to
Format-Custom
to expand all those nested objects. This is great for comparisons etc...
Subscribe to my newsletter
Read articles from Ondrej Sebela directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Ondrej Sebela
Ondrej Sebela
I work as System Administrator for more than 10 years now and I love to make my life easier by automating work & personal stuff via PowerShell (even silly things like food recipes list generation).