msgraph-sdk-powershell
msgraph-sdk-powershell copied to clipboard
Get-MgDirectoryDeletedItem Does not return any data to the console
When running the command:
Get-MgDirectoryDeletedItem -DirectoryObjectId microsoft.graph.user
I would expect the output to show me the deleted users in Azure AD. Instead it shows:
Id DeletedDateTime
-- ---------------
When running the command while Fiddler is running, there are items being returned. I'm hiding the properties due to the sensitive nature of the info.
This is an issue for us as well. We can get the data using Invoke-GraphRequest
, but that shouldn't be necessary. Get-MgDirectoryDeletedItem
should return the data.
Also it isn't clear that the -DirectoryObjectId
parameter is supposed to work with a value of Microsoft.Graph.User
(which is an object type, not a directory object id). Maybe there should be two parameter sets on this cmdlet and other similar cmdlets: one for looking up a specific directory object (application, user or group) by id, and another for retrieval of all information by type, with the parameter accepting a limited set of values to match what is expected/supported.
I am also facing this issue and need to access deleted users. The functions available for getting users in the recycle bin seem to be severely lacking compared with Get-MSOLUser :(
I'm hoping for some traction on this. Again I ran into this issue (in latest v1.6.0) and thought I should report the bug and found that I already had.
Invoke-GraphRequest
does work, but is not very clean and requires some massaging with pagination and converting the array of hashtables to objects.
same for me... @DougChandler mentioned do we need this cmdlet to get the "soft deleted" users
It seems we could get at least some details via the AdditionalProperties['value']
property
$deleted = Get-MgDirectoryDeletedItem -DirectoryObjectId microsoft.graph.user -Property '*'
$deleted.AdditionalProperties['value'][0]
So sad to see that this is an old issue and still nothing. I'm updating my PowerShell scripts to use the Microsoft Graph module, and this is the second thing that I'm not able to use it...
Update:
Using @thuld idea:
It seems we could get at least some details via the
AdditionalProperties['value']
property$deleted = Get-MgDirectoryDeletedItem -DirectoryObjectId microsoft.graph.user -Property '*' $deleted.AdditionalProperties['value'][0]
$deleted = Get-MgDirectoryDeletedItem -DirectoryObjectId microsoft.graph.user -Property '*'
$deleted.AdditionalProperties['value'] | Select-Object @{L = "Name"; E = { $_.displayName} },@{L = "UserId"; E = { $_.id} } | Sort-Object "Name"
Here is a way to do something similar and get all values:
$DeletedUsers = Get-MgDirectoryDeletedItem -DirectoryObjectId microsoft.graph.user -Property '*'
$DeletedUsers = $DeletedUsers.AdditionalProperties['value']
foreach ($deletedUser in $DeletedUsers)
{
$deletedUser | Format-Table
}
$DeletedGroups = Get-MgDirectoryDeletedItem -DirectoryObjectId microsoft.graph.group -Property '*'
$DeletedGroups = $DeletedGroups.AdditionalProperties['value']
foreach ($deletedGroup in $DeletedGroups)
{
$deletedGroup | Format-Table
}
@Sekers I found your solution more reliable than others I have tested. Thank you so much
@Sekers, any ways to get more than 100 results ?
@CarlLowes Make sure to use the "-All" parameter (or -PageSize).
https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.identity.directorymanagement/get-mgdirectorydeleteditem
@CarlLowes Make sure to use the "-All" parameter (or -PageSize).
https://learn.microsoft.com/en-us/powershell/module/microsoft.graph.identity.directorymanagement/get-mgdirectorydeleteditem
When I use -All parameter I get the following error... Get-MgDirectoryDeletedItem : Parameter set cannot be resolved using the specified named parameters.
I cannot believe that we are nearly 3 years since it was reported, and it is a P1, that this bug still exists. The parameters for the CmdLet are mis-named, the -All parameter doesn't work, fetching all properties doesn't work, the CmdLet does not produce any data, you need to use a workaround to drill down to the data. We need this for our corporate system and took the decision last year to roll my own Graph connector which works perfectly well for deleted items, now coming back to it, this CmdLet still doesn't work :(
I'm in the same boat. Updating scripts to leverage graph and this still returns nothing.
3 years and still not fixed. We are trying to move away from the older modules but issues like this keep that from happening. If the MSOnline module is depreciated, then what? The only way to do this is to create an API in Azure and try to write large amounts of code just to get a list of deleted users? I don't understand how all these commands can get implemented with so many issues or just incomplete or so complicated. Get-msoluser -all -returndeletedusers. Simple. Please get this fixed soon.
The OData cast path that's needed to make the call is currently missing in the schema used to generate the modules. The work to add and enable the missing paths is being tracked at https://github.com/microsoftgraph/microsoft-graph-devx-api/issues/1228.
As a workaround, you can Invoke-MgGraphRequest
to get deleted directory items as mentioned above. In this case, the script will be something like:
$deletedUsers = @()
$uri = "/v1.0/directory/deletedItems/microsoft.graph.user"
do {
$result = Invoke-MgGraphRequest -Method GET -Uri $uri -OutputType PSObject
$deletedUsers += $result.value
$uri = $result.'@odata.nextLink'
} until ($null -eq $result.'@odata.nextLink')
Write-Host $deletedUsers.Count
I was literally going to put the same workaround, which is what I currently use. A bit of a pain to have to use a workaround as there is a dedicated method but it doesn't work :(
I used a combination of peombwa's solution and Get-MgDirectoryDeletedItem, because I needed to get the ImmutableId property of the deleted users (this will return all properties, just like Get-MsolUser -ReturnDeletedUsers -All):
$DeletedUsers = @() $uri = "/v1.0/directory/deletedItems/microsoft.graph.user" do { $result = Invoke-MgGraphRequest -Method GET -Uri $uri -OutputType PSObject $DeletedUsers += $result.value $uri = $result.'@odata.nextLink' } until ($null -eq $result.'@odata.nextLink')
$RecycleBinUsers = @() Foreach($deletedUser in $DeletedUsers) { $RecycleBinUsers += (Get-MgDirectoryDeletedItem -DirectoryObjectId $deletedUser.Id -Property *).AdditionalProperties }
Hope this saves you some hours :)
Thanks for all the replies. This is my first stab at getting a command in our main team module in order to search for a user.
<# .synopsis Returns a user from the O365 recycle bin
.description Returns a user from the O365 recycle bin
.Example Get-BCMGDeletedUser $Identity
.Notes Richard Ebeling - EIS Communications Team
#> [cmdletbinding()] Param ( [Parameter( mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "Enter the UserPrincipalName, SamAccountName, or ObjectID of The Deleted User" )] [string]$Identity )#Param
Begin { $global:ErrorActionPreference = "Stop" $deletedUsers = @() $uri = "/v1.0/directory/deletedItems/microsoft.graph.user" #$uri = "/beta/directory/deletedItems/microsoft.graph.user" }#Begin
Process {
Write-Verbose "Searching For Deleted Users. Please Wait."
do {
$result = Invoke-MgGraphRequest -Method GET -uri $uri -verbose:$false
$deletedUsers += $result.value
$uri = $result.'@odata.nextLink'
} until ($null -eq $result.'@odata.nextLink')
foreach ($deleteduser in $deletedusers) {
#Create an Object to reference the Users ID
$properties = @{}
foreach ($key in $deleteduser.keys) { $properties.add($key, $deleteduser[$key]) }
$UserProfile = New-Object -typename psobject -property $properties
#Retrieve the User Properties with the user ID
$userproperties = (Get-MgDirectoryDeletedItem -DirectoryObjectId $userprofile.id -Property * ).AdditionalProperties
#Create an Object from the UserProperties
$properties1 = @{}
foreach ($key in $userproperties.keys) { $properties1.add($key, $userproperties[$key]) }
$UserProfileProperties = New-Object -typename psobject -property $properties1
if ($UserProfileProperties.onPremisesUserPrincipalName -eq $identity -or
$UserProfileProperties.OnPremisesSamAccountName -eq $identity -or
$UserProperties1.ID -eq $identity ) {
#If found get the deletetion date and ID
$userproperties1 = (Get-MgDirectoryDeletedItem -DirectoryObjectId $userprofile.id -Property * )
$properties2 = @{
"Identity" = $identity
"UserPrincipalName" = $UserProfileProperties.Userprincipalname
"OnPremisesUserPrincipalName" = $UserProfileProperties.onPremisesUserPrincipalName
"DisplayName" = $UserProfileProperties.Displayname
"ID" = $UserProperties1.ID
"OnPremisesSamAccountName" = $UserProfileProperties.onPremisesSamAccountName
"DeletedDateTime" = $userproperties1.deletedDateTime
}#Properties
$obj = New-Object -TypeName psobject -Property $Properties2
$obj | Select-Object Identity, ID, DisplayName, Userprincipalname, OnPremisesUserPrincipalName, onPremisesSamAccountName, deletedDateTime
Break
}#if Found
}#foreach
}#Proccess
End { $global:ErrorActionPreference = "Continue" Write-Verbose "Operation Complete" }#End
Thanks to @peombwa and @AdrianStrasser. Here is the revised and simplified code. The $recycleBinUser Needs to be converted to a PSObject. I will eventually add a -All switch to this.
<# .synopsis Returns a user from the O365 recycle bin
.description Returns a user from the O365 recycle bin
.Example Get-BCMGDeletedUser $Identity
.Notes Richard Ebeling - REDACTED - EIS Communications Team
#>
[cmdletbinding()] Param ( [Parameter( mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, HelpMessage = "Enter the UserPrincipalName, SamAccountName, or ObjectID of The Deleted User" )] [string]$Identity )#Param
Begin { $global:ErrorActionPreference = "Stop" $deletedUsers = @() $uri = "/v1.0/directory/deletedItems/microsoft.graph.user" #$uri = "/beta/directory/deletedItems/microsoft.graph.user" }#Begin
Process {
Write-Verbose "Searching For Deleted Users. Please Wait."
do {
$result = Invoke-MgGraphRequest -Method GET -uri $uri -verbose:$false
$deletedUsers += $result.value
$uri = $result.'@odata.nextLink'
} until ($null -eq $result.'@odata.nextLink')
Write-Verbose "Filtering For User $identity. Please Wait."
Foreach ($deletedUser in $DeletedUsers) {
$RecycleBinUser = (Get-MgDirectoryDeletedItem -DirectoryObjectId $deletedUser.Id -Property *).AdditionalProperties
$UserProfileProperties = New-Object -typename psobject -property $RecycleBinUser
if ($UserProfileProperties.onPremisesUserPrincipalName -eq $identity -or
$UserProfileProperties.OnPremisesSamAccountName -eq $identity -or
$UserProfileProperties.ID -eq $identity ) {
#If found get the deletetion date and ID
$userproperties1 = (Get-MgDirectoryDeletedItem -DirectoryObjectId $deletedUser.id -Property * )
$properties2 = @{
"Identity" = $identity
"UserPrincipalName" = $UserProfileProperties.Userprincipalname
"OnPremisesUserPrincipalName" = $UserProfileProperties.onPremisesUserPrincipalName
"DisplayName" = $UserProfileProperties.Displayname
"ID" = $UserProperties1.ID
"OnPremisesSamAccountName" = $UserProfileProperties.onPremisesSamAccountName
"DeletedDateTime" = $userproperties1.deletedDateTime
}#Properties
$obj = New-Object -TypeName psobject -Property $Properties2
$obj | Select-Object Identity, ID, DisplayName, Userprincipalname, OnPremisesUserPrincipalName, onPremisesSamAccountName, deletedDateTime
Break
}#if Found
}#Foreach User
}#Proccess
End { $global:ErrorActionPreference = "Continue" Write-Verbose "Operation Complete" }#End
@RichWorld-Tech, thanks for putting this together.
@DougChandler, the issue is currently blocked by a downstream dependency. There is ongoing work to bring OData cast support to the SDK that's being tracked at https://github.com/microsoftgraph/microsoft-graph-devx-api/issues/1228. The first part was merged last week - https://github.com/microsoft/OpenAPI.NET.OData/issues/324.
We are aiming to have OData cast support in the SDK in v2, quality dependent.
@peombwa Thanks for the update. Will the OData cast also fix microsoft.graph.user and microsoft.graph.group as https://github.com/microsoftgraph/microsoft-graph-devx-api/issues/1228 only mentions Applications? Also I assume Get-MgDirectoryDeletedItem will need a new parameter for the deleted item type (user, group, etc.)? Are there any timescales for a fix?
Yes, the fix will cover all supported derived types of directotyObject as stated at https://learn.microsoft.com/en-us/graph/api/directory-deleteditems-list?view=graph-rest-1.0&tabs=http:
Retrieve a list of recently deleted directory objects. Currently, deleted items functionality is only supported for the application, servicePrincipal, group, administrative unit, and user resources.
Each derived type will have a dedicated command. For example, Get-MgDirectoryDeletedItemAsUser
will return deleted users.
Are there any timescales for a fix?
The timeline is subject to a downstream dependency, but we believe the change should be out in a week or two as part of v2 preview.
Great, looking forward to it, but why not have dedicated methods called Get-mgDeletedUser in line with Get-mgUser, or Get-mgDirectoryDeletedUser? I know these are off the directory deleted items resource in Graph but conceptually from the user they are with the non-deleted resource and will be used that way as indeed they are in the Azure portal. Any chance of some common sense here?
Great, looking forward to it, but why not have dedicated methods called Get-mgDeletedUser in line with Get-mgUser, or Get-mgDirectoryDeletedUser? I know these are off the directory deleted items resource in Graph but conceptually from the user they are with the non-deleted resource and will be used that way as indeed they are in the Azure portal. Any chance of some common sense here?
This is stated at Navigating the Microsoft Graph PowerShell SDK. The commands follow a path-based naming convention. The names are influenced by shape of the REST API. By design, all Microsoft Graph SDKs currently follow a path-based naming convention. The commands are all auto-generated based on a path-based naming convention.
Yes it is a shame that some commands are a bit illogical such as deleted users, hence putting them under users in Azure Portal so you can find them...
To balance between API consistency and discoverability, we can consider aliasing GET directory/deletedItems/{Entity-Type}
commands to something similar to your above suggestion of Get-mgDirectoryDeletedUser
.
I like that idea, but I would lose the word 'Directory' since it is irrelevant since everything is in the directory... it always confuses me that it has 'Directory' in Get-mgDirectoryDeletedItem anyway. I understand that it is under /Directory in Graph and that is probably the reason but it is confusing, would be better to be under the applicable resource, e.g. /Users/Deleted, as that is how they are used.
Closing as fixed by https://github.com/microsoftgraph/msgraph-sdk-powershell/releases/tag/2.0.0-rc1:
The commands are also aliased as mentioned at https://github.com/microsoftgraph/msgraph-sdk-powershell/issues/294#issuecomment-1515473937.
@DougChandler, I've shared your feedback with the API owner for review. The API owner will review the current API path to simplify its discoverability and use.
Thanks I will give this a try when I can. Thanks for passing on the feedback, it would be good to see some common sense introduced and get rid of the whole 'Directory' nonsense.
Installed the pre-release version and we are still having issue with this, as there are still many fields showing as blank. For example "Deleteddatetime" as mentioned by OP. Why are these fields still returning with a null value? The date/time that a user was deleted is a key piece of info for a deleted user. We need this fixed so that all the info is clearly shown when running the simple command of Get-MgDirectoryDeletedItemAsUser