1

I'm attempting to get Exchange mailbox permissions of specific mailbox in C# using Remote PowerShell. I need to get SecurityIdentifier of privileged user, as the property User is a nested property, im trying to load it by using -ExpandProperty PowerShell feature.

var powerShell = PowerShell.Create();
powerShell.Runspace = runspace;
var command = new Command("Get-MailboxPermission");
command.Parameters.Add("Identity", "user-smtp@test-domain.com");

powerShell.Commands.AddCommand(command);

var selectCommand = new Command("Select-Object");
selectCommand.Parameters.Add("Property", new[] {"AccessRights", "User"});
selectCommand.Parameters.Add("ExpandProperty", "User");
                
powerShell.Commands.AddCommand(selectCommand);

var result = powerShell.Invoke();

foreach (var psObject in result){
   var accessRights = psObject.Properties["AccessRights"].Value.ToString();  
   var user = psObject.Properties["User"].Value.ToString();
   var userSecurityIdentifier = psObject.Properties["SecurityIdentifier"].Value.ToString();
}

Unfortunately this code doesn't return SecurityIdentifier.

I guess that the nested property User is already deserialized as explained here:
https://stackoverflow.com/a/44825068/8125728

Executing command as a script was working fine until April 2021 Exchange Server Security Update which changed the Exchange Management Console endpoint language mode from FullLanguage mode to NoLanguage mode. NoLanguage mode unfortunately does not support AddScript().

var script = "Get-MailboxPermission -Identity 'user-smtp@test-domain.com' | Select-Object -Property AccessRights, User -ExpandProperty User";
powerShell.AddScript(script);
powerShell.Invoke();

I know that this can done by importing session and executing script in ScriptBlock but importing the PsSession leads to huge memory usage and also to memory leak as it caches the imported modules.

var script = "Get-MailboxPermission -Identity 'user-smtp@test-domain.com' | Select-Object -Property AccessRights, User -ExpandProperty User";
Command command = new Command("Invoke-Command");
command.Parameters.Add("Session", session);
command.Parameters.Add("ScriptBlock", ScriptBlock.Create(script));

Is there any workaround how to get SecurityIdentifier from nested User property without importing PsSession?

Baki
  • 11
  • 3
  • 1
    It's one or the other, you can't call on a property , then try to expand another. – Abraham Zinala Jun 02 '21 at 13:47
  • 1
    @AbrahamZinala Sure you do - using `-Property` in conjunction with `-ExpandProperty` to flatten the object hierarchy is absolutely fine and supported. The problem here is likely that OP needs `psObject.Properties["User"].Properties["SecurityIdentifier"]` instead of `psObject.Properties["SecurityIdentifier"]` – Mathias R. Jessen Jun 02 '21 at 14:11
  • Ohh, fancy. Good to know – Abraham Zinala Jun 02 '21 at 14:13
  • @Mathias R. Jessen `psObject.Properties["User"]` is already deserialized so its type is `String` – Baki Jun 02 '21 at 14:20
  • 3
    So `@{ n='SID' ; e={ $_.User.SecurityIdentifier }}` is not an option right? – Santiago Squarzon Jun 02 '21 at 14:25
  • 1
    This won't solve your problem, but as an aside: if you combine `-Property` with `-ExpandProperty`, the `-Property` properties are added as _NoteProperty_ members to whatever (enumerated) instances `-ExpandProperty` returns. Therefore, use of `User` _twice_ is pointless; what `-ExpandProperty User` outputs _are_ already the (enumerated) `.User` property values. – mklement0 Jun 02 '21 at 16:55
  • @SantiagoSquarzon I just tried that to be sure but unfortunately it didn't help. – Baki Jun 04 '21 at 11:11

0 Answers0