I'm relatively new to PowerShell, so this may be something simple. I am attempting to display the translated name and original SIDs for the Groups associated with the current login. The Translated names are easy enough:
[System.Security.Principal.WindowsIdentity]::GetCurrent().Groups.Translate([System.Security.Principal.NTAccount]).Value
This display as such and includes an orphaned SID that could not be translated:
Everyone
BUILTIN\Administrators
BUILTIN\Users
NT AUTHORITY\INTERACTIVE
CONSOLE LOGON
NT AUTHORITY\Authenticated Users
NT AUTHORITY\This Organization
LOCAL
S-1-12-X-XXXXXXXX-XXXXXXXX-XXXXXXXX-XXXXXXX
NT AUTHORITY\Cloud Account Authentication
The orphaned SID has been redacted with Xs. This is part of a larger script and I am attempting to capture this section as HTML like the following:
$currentUser = [System.Security.Principal.WindowsIdentity]::GetCurrent() | Select-Object Name, @{n='Groups';e={$_.Groups | Foreach-Object {
try
{
$_.Translate([System.Security.Principal.NTAccount]).Value + ' (' + $_.Value +')'
}
catch [Exception]
{
Out-Null
}
}}} | ConvertTo-Html -As List -Fragment
In this example, I am suppressing the Exception, but I have not found a way to display the object that is causing the exception ("Translate" with "1" argument(s): "Some or all identity references could not be translated.").
Is there a way to list the object that caused the exception? I tried with the following:
$_.Exception.TargetObject
The TargetObject was empty. Is there perhaps an if/else construct that could be used if an exception is encountered?
The problem in this question is that the Foreach-Object
cmdlet uses the current item ($PSItem
or $_
) and the Catch
block also uses (overrules) the current item to reference the exception information.
A minimal reproducible example to show this, would be:
1..5 | Foreach-Object { try { 1 / ( 3 - $_ ) } catch { "Error processing: $_" } }
0.5
1
Error processing: Attempted to divide by zero.
-1
-0.5
Note that the same issue exists in an embedded Foreach-Object
loop.
Probably the easiest (and cleanest) way around this is to assign the current item to another variable which might be done further into the pipeline than the solution you present in your self-answer:
1..5 | Foreach-Object { $n = $_; try { 1 / ( 3 - $_ ) } catch { "Error processing: $n" } }
0.5
1
Error processing: 3
-1
-0.5
For your specific case, the Foreach-Object
loop might probably be something similar to this:
... | Foreach-Object {
$Sid = $_
try { "$($_.Translate([System.Security.Principal.NTAccount]).Value) ($($_.Value))" }
catch { $Sid.Value } # or better: catch [<Specific Exception>] { $Sid.Value }
}