# Adding support for selecting ALL properties using '*' wildcard in Mg Graph commands 'property' parameter

# Problem

You may have noticed that Microsoft Graph SDK commands like `Get-MgUser`, `Get-MgDevice`, etc **don't retrieve all properties by default**. 👇

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680853085226/c2e5a31e-588c-4f84-9c77-1039a7455ab2.png align="center")

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 👇

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680853142082/4bc9620e-61ff-4066-a555-0a349e4fb4e0.png align="center")

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 like `name`, `id`, etc which you'll need in 99% of situations anyway, plus required "extra" properties
    
* You 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 the `Get-MgUser -Debug` example below 👇
    

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680854159614/9ed31810-bfb7-42ff-8161-27213ba161cf.jpeg align="center")

---

# TL;DR

Use my proxy function `Get-MgUser2` from my module PowerShell [MSGraphStuff](https://www.powershellgallery.com/packages/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

```powershell
$mgUserProperty = Get-MgUser -Top 1 | Get-Member -MemberType NoteProperty, Property | select -ExpandProperty Name
```

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680854622945/4cd9e8ba-d0aa-4f6c-bc6c-c0e0338292b6.png align="center")

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..."

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680854797596/39684ef4-20aa-4416-8c72-006fb5f59302.png align="center")

I found out that it is [caused by the property](https://github.com/microsoftgraph/msgraph-sdk-powershell/issues/1926) `DeviceEnrollmentLimit`, which therefore needs to be excluded.

Ok, next round. Now we try to get all properties without `DeviceEnrollmentLimit`. But it errors again 😄

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680855077099/5300b57d-5c71-4f38-ad16-ae3ae8e6a939.png align="center")

Uncle Google gives me the [answer for this error](https://stackoverflow.com/questions/54767695/error-access-denied-on-mailboxsettings-for-users). 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 👍

![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680855351971/7c3f159f-37f8-476b-aa8f-7c514df80467.png align="center")

```powershell
# 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](https://www.powershellgallery.com/packages/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](https://mcpmag.com/articles/2013/11/05/blacksmith-part-7.aspx).

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.

1. Code for creating a proxy function (in this case `Get-MgUser2` from original `Get-MgUser)`.
    

```powershell
# 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

1. 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.
    
    ![original proxy function modifications](https://cdn.hashnode.com/res/hashnode/image/upload/v1680859727116/a2aaf0d6-0a3f-4ec0-b007-81cc75d41456.png align="center")
    

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...
> 
> ![](https://cdn.hashnode.com/res/hashnode/image/upload/v1680966977049/1e9d045d-02c6-4d43-beac-e3dbbc34a84f.png align="center")
