Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get-LocalGroupMember - Failed to compare two elements in the array. #2996

Closed
ephos opened this issue Jan 11, 2017 · 155 comments
Closed

Get-LocalGroupMember - Failed to compare two elements in the array. #2996

ephos opened this issue Jan 11, 2017 · 155 comments
Assignees
Labels
Issue-Bug Issue has been identified as a bug in the product Resolution-External The issue is caused by external component(s). WG-Cmdlets general cmdlet issues
Milestone

Comments

@ephos
Copy link

ephos commented Jan 11, 2017

It appears that if you have domain groups added to a local group and then move the server to a workgroup before removing them Get-LocalGroupMember no longer works and instead throws an exception 'Failed to compare two elements in the array.'. I am seeing this on Server 2016 Core, I have not tried on any other editions. I found this while building a server in one domain that needed to move to a different one.

Steps to reproduce

  • Join a Windows Server 2016 Core server to a domain.
  • Added 3 domain groups to the local administrators group.
  • Moved the server back into a workgroup.
  • Ran Get-LocalGroupMember -Group Administrators

I've reproduced this on two servers.

Expected behavior

It should return the group members as it would prior to moving to a workgroup and just display the unresolved SIDs for the old domain. Then ideally allow you to reference those unresolved SIDS for Remove-LocalGroupMember.

Actual behavior

Throws an exception.
2017-01-11_17-32-25

Environment data

> $PSVersionTable
PSVersion                      5.1.14393.206
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14393.206
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
@mirichmo
Copy link
Member

@ephos This is an interesting issue. Can you please provide

$Error[0] | fl * -force

as well?

@mirichmo mirichmo added the WG-Cmdlets general cmdlet issues label Jan 11, 2017
@ephos
Copy link
Author

ephos commented Jan 12, 2017

@mirichmo here you go!

> $Error[0] | fl * -Force


writeErrorStream      : True
PSMessageDetails      : 
Exception             : System.InvalidOperationException: Failed to compare two elements in the array. ---> 
                        System.NullReferenceException: Object reference not set to an instance of an object.
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.<>c.<ProcessesMembership>b_
                        _20_0(LocalPrincipal p1, LocalPrincipal p2)
                           at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 
                        comparer, Int32 a, Int32 b)
                           at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 
                        left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
                           at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 
                        length, IComparer`1 comparer)
                           --- End of inner exception stack trace ---
                           at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 
                        length, IComparer`1 comparer)
                           at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
                           at System.Collections.Generic.List`1.Sort(Comparison`1 comparison)
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.ProcessesMembership(IEnumer
                        able`1 membership)
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.ProcessRecord()
TargetObject          : 
CategoryInfo          : NotSpecified: (:) [Get-LocalGroupMember], InvalidOperationException
FullyQualifiedErrorId : An unspecified error occurred.,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {0, 1}

@mirichmo mirichmo added the Issue-Bug Issue has been identified as a bug in the product label Jan 12, 2017
@mirichmo
Copy link
Member

Thanks for the info

@iSazonov
Copy link
Collaborator

It's work well on Windows 10 :

Name                           Value
----                           -----
CLRVersion
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
GitCommitId                    v6.0.0-alpha.14-28-geef6ed0584ba62e232f95668ad25d277d2137efc-dirty
SerializationVersion           1.1.0.1
PSRemotingProtocolVersion      2.3
PSEdition                      Core
WSManStackVersion              3.0
BuildVersion                   3.0.0.0
PSVersion                      6.0.0-alpha

@ssylvan
Copy link

ssylvan commented Jan 13, 2017

I am also hitting this issue, any workarounds?

@iSazonov
Copy link
Collaborator

@ssylvan Can you confirm that the problem is on Windows Server 2016 Core server only.

@ssylvan
Copy link

ssylvan commented Jan 13, 2017 via email

@iSazonov
Copy link
Collaborator

@ssylvan Thanks for the clarification.

@itisbrendan
Copy link

itisbrendan commented Jan 31, 2017

Hello, I'm seeing this error raised as well. Windows 10 Pro

PS C:\> [System.Environment]::OSVersion.Version

Major  Minor  Build  Revision
-----  -----  -----  --------
10     0      14393  0

@iSazonov
Copy link
Collaborator

iSazonov commented Feb 1, 2017

@itisbrendan Thanks for confirmation!

@OraDotNetDev
Copy link

OraDotNetDev commented Feb 2, 2017

Workaround here

Same experience in Windows 7 Enterprise and exactly the same Error details as @ephos

Major  Minor  Build  Revision
-----  -----  -----  --------
6      1      7601   65536


PS C:\> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.14409.1005
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14409.1005
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

@PwshPally
Copy link

PwshPally commented Mar 6, 2017

I'm getting the same on Win10 joined to Azure AD. This PC has never been part of a traditional Active Directory.

PS C:\Users\SteveMahoney> $PSVersionTable

Name                           Value                                                                                                                            
----                           -----                                                                                                                            
PSVersion                      5.1.14393.693                                                                                                                    
PSEdition                      Desktop                                                                                                                          
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                                                          
BuildVersion                   10.0.14393.693                                                                                                                   
CLRVersion                     4.0.30319.42000                                                                                                                  
WSManStackVersion              3.0                                                                                                                              
PSRemotingProtocolVersion      2.3                                                                                                                              
SerializationVersion           1.1.0.1 

PS C:\Users\SteveMahoney> Get-LocalGroupMember -Group "Administrators"
Get-LocalGroupMember : Failed to compare two elements in the array.
At line:1 char:1
+ Get-LocalGroupMember -Group "Administrators"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-LocalGroupMember], InvalidOperationException
    + FullyQualifiedErrorId : An unspecified error occurred.,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand
 

PS C:\Users\SteveMahoney> $Error[0] | fl * -force


writeErrorStream      : True
PSMessageDetails      : 
Exception             : System.InvalidOperationException: Failed to compare two elements in the array. ---> System.NullReferenceException: Object reference not 
                        set to an instance of an object.
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.<>c.<ProcessesMembership>b__20_0(LocalPrincipal p1, LocalPrincipal p2)
                           at System.Collections.Generic.ArraySortHelper`1.InsertionSort(T[] keys, Int32 lo, Int32 hi, IComparer`1 comparer)
                           at System.Collections.Generic.ArraySortHelper`1.IntrospectiveSort(T[] keys, Int32 left, Int32 length, IComparer`1 comparer)
                           at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
                           --- End of inner exception stack trace ---
                           at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
                           at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
                           at System.Collections.Generic.List`1.Sort(Comparison`1 comparison)
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.ProcessesMembership(IEnumerable`1 membership)
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.ProcessRecord()
TargetObject          : 
CategoryInfo          : NotSpecified: (:) [Get-LocalGroupMember], InvalidOperationException
FullyQualifiedErrorId : An unspecified error occurred.,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {0, 1}

@fullenw1
Copy link

fullenw1 commented May 4, 2017

Same issue on Windows 2008 R2 and 2012 R2.

@indented-automation
Copy link
Contributor

indented-automation commented Oct 17, 2017

I've had a bit of a poke around and a chat and some help from faustonascimento on IRC. This code will reproduce the problem:

Import-Module Microsoft.PowerShell.LocalAccounts
Add-Type -ReferencedAssemblies ([PowerShell].Assembly.Location), ([Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand].Assembly.Location) -TypeDefinition '
using System;
using System.Collections.Generic;
using System.Security.Principal;
using Microsoft.PowerShell.Commands;

public class Test
{
    public static IEnumerable<LocalPrincipal> Get()
    {
        List<LocalPrincipal> rv = new List<LocalPrincipal>();

        LocalPrincipal principal = new LocalPrincipal(Environment.UserName);
        principal.SID = (SecurityIdentifier)(new NTAccount(Environment.UserName)).Translate(typeof(SecurityIdentifier));
        rv.Add(principal);

        // https://github.com/PowerShell/PowerShell/blob/1462ac300bc5e4a20f0360b428de1cb1de4eaba4/src/Microsoft.PowerShell.LocalAccounts/LocalAccounts/Sam.cs#L2813
        rv.Add(null);

        rv.Sort((p1, p2) => string.Compare(p1.Name, p2.Name, StringComparison.CurrentCultureIgnoreCase));
        return rv;
    }
}
'
[Test]::Get()

The problem appears to be caused by the null return from the MakeLocalPrincipalObject method:

private LocalPrincipal MakeLocalPrincipalObject(AccountInfo info)

The null value is being pushed to MakeLocalPrincipalObject because an invalid SID will cause a name lookup failure from Win32.LookupAccountSid. This method explicitly returns null when the error code ERROR_NONE_MAPPED (1332) is set.

This value is not filtered out and ends up being added to the rv collection which subsequently fails on Sort.

It can be argued that this value should be filtered out, as the null value is not useful. For example, by inserting:

rv = rv.Where(x => x != null).ToList();

Returning the invalid entry is a deep(er) change to the GetGroupMembers method. This would potentially be useful as it may allow these commands to fix the problem (if it is such) rather than just ignoring the condition. Achievable by speculatively replacing the yield return with line with the following:

var sid = new SecurityIdentifier(idArray[i]);
AccountInfo info = LookupAccountInfo(sid);
if (info == null)
{
    info = new AccountInfo { Sid = sid };
}
yield return MakeLocalPrincipalObject(info);

The LookupAccountInfo method is shared by most of the other commands, changing its behaviour would be intrusive. GetGroupMembers only appears to be used by Get-LocalGroupMember.

Chris

@jeffbi
Copy link
Contributor

jeffbi commented Oct 17, 2017

I think in general this makes sense. The only other method that calls MakeLocalPrincipalObject checks for a null return from LookupAccountInfo and throws an exception.

I'm curious about why we would be getting an invalid SID in the first place. There are two overloads for the GetGroupMembers method---one takes a group name and the other takes a group SID. They do their queries for group membership in different ways (Net API vs. SAM API). Do we know whether the null comes from one of these or the other, or both?

@indented-automation
Copy link
Contributor

I only see one overload for GetGroupMembers in the source code? There are two overloads for GetLocalGroupMembers, both call GetGroupMembers with a SID.

It seems the only way to recreate this is described in the first post. A machine must be added to the domain, a member added, then the machine removed from the domain. Using a local user is not sufficient to recreate the problem. I'm not at liberty to test such things at the moment although it will need to be tested after the code has been changed.

@jeffbi
Copy link
Contributor

jeffbi commented Oct 18, 2017

Oops. Sorry, you're right. I was looking at an experimental version I'd forgotten about.

After re-reading the original description and looking at things again, the whole thing makes more sense to me and I think your solution is the correct one. There would need to be an additional minor change elsewhere to get the SID to be displayed in the output in place of the name, and there would be no way (I think) to correctly determine the ObjectClass.

Sorry for the noise.

Of course, all this kinda depends on the LocalAccounts cmdlets getting back into the build once they no longer use the SAM API.

@Hicsy
Copy link

Hicsy commented Nov 28, 2017

Any update?
ALL PC's at work can't use get-localgroupmembers due to being Azure-AD connected.

  1. Create an O365/AzureAD tenant, and add a user. Can be just intune, but most commonly EMS pack... and soon EVERY customer who buys Microsoft 365 business/enterprise suite (Windows 10 Enterprise, EMS, Office 365) will be affected.
  2. Start a NEW computer. Anything Windows 10. Otherwise just spool up a new VM with a fresh Windows 10 installation. During normal OOBE setup it will ask the user to sign into Microsoft.
  3. Sign into the work account created in step 1.
  4. Windows will add this user account to "Administrators" localgroup automatically due to there not being an active local administrator account set up.

Likely due to there being an AzureAD account - this powershell cmdlet always crashes

PS C:\WINDOWS\system32> net localgroup administrators
Alias name     administrators
Comment        Administrators have complete and unrestricted access to the computer/domain

Members

-------------------------------------------------------------------------------
Administrator
AzureAD\TestO365Account
The command completed successfully.
PS C:\WINDOWS\system32> Get-LocalGroupMember administrators
Get-LocalGroupMember : Failed to compare two elements in the array.
At line:1 char:1
+ Get-LocalGroupMember administrators
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-LocalGroupMember], InvalidOperationException
    + FullyQualifiedErrorId : An unspecified error occurred.,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand

Diagnostics:

PS C:\WINDOWS\system32> $Error[0] | fl * -force


writeErrorStream      : True
PSMessageDetails      :
Exception             : System.InvalidOperationException: Failed to compare two elements in the array. ---> System.NullReferenceException: Object reference not set to an instance of an
                        object.
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.<>c.<ProcessesMembership>b__20_0(LocalPrincipal p1, LocalPrincipal p2)
                           at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 comparer, Int32 a, Int32 b)
                           at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, Int32 right, IComparer`1 comparer, Int32 depthLimit)
                           at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
                           --- End of inner exception stack trace ---
                           at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, IComparer`1 comparer)
                           at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
                           at System.Collections.Generic.List`1.Sort(Comparison`1 comparison)
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.ProcessesMembership(IEnumerable`1 membership)
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.ProcessRecord()
TargetObject          :
CategoryInfo          : NotSpecified: (:) [Get-LocalGroupMember], InvalidOperationException
FullyQualifiedErrorId : An unspecified error occurred.,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {0, 1}


PS C:\WINDOWS\system32> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      5.1.17046.1000
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.17046.1000
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1

@iSazonov
Copy link
Collaborator

/cc @SteveL-MSFT Azure-AD scenario failed.

@indented-automation
Copy link
Contributor

I haven't been rushing to make a PR as this will only affect PowerShell 6 builds where it's currently not operational (and I'm rather busy at the moment).

It would be rather nice to stream this out as a standalone module, but even if it is, that won't make it immediately available to anyone.

@SteveL-MSFT SteveL-MSFT added the Backport-5.1-Consider Consider to backport to Windows PowerShell 5.1 due to impact label Nov 28, 2017
@SteveL-MSFT SteveL-MSFT added this to the 6.1.0-Consider milestone Nov 28, 2017
@SteveL-MSFT
Copy link
Member

@Hicsy after we have a fix in PSCore6, we can consider backporting it to Windows PowerShell 5.1.

@JohnBons
Copy link

JohnBons commented Dec 8, 2017

@SteveL-MSFT I also would like to see that fix in 5.1 since im running into the same issue.

Running windows 2012 R2


PS C:\> [System.Environment]::OSVersion.Version

Major  Minor  Build  Revision
-----  -----  -----  --------
6      3      9600   0

Name                           Value                                                                                   
----                           -----                                                                                   
PSVersion                      5.1.14409.1012                                                                          
PSEdition                      Desktop                                                                                 
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}                                                                 
BuildVersion                   10.0.14409.1012                                                                         
CLRVersion                     4.0.30319.42000                                                                         
WSManStackVersion              3.0                                                                                     
PSRemotingProtocolVersion      2.3                                                                                     
SerializationVersion           1.1.0.1                                                                                 




writeErrorStream      : True
PSMessageDetails      : 
Exception             : System.InvalidOperationException: Failed to compare two elements in the array. ---> 
                        System.NullReferenceException: Object reference not set to an instance of an object.
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.<>c.<ProcessesMembership>b__20_0
                        (LocalPrincipal p1, LocalPrincipal p2)
                           at System.Collections.Generic.ArraySortHelper`1.SwapIfGreater(T[] keys, IComparer`1 
                        comparer, Int32 a, Int32 b)
                           at System.Collections.Generic.ArraySortHelper`1.DepthLimitedQuickSort(T[] keys, Int32 left, 
                        Int32 right, IComparer`1 comparer, Int32 depthLimit)
                           at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, 
                        IComparer`1 comparer)
                           --- End of inner exception stack trace ---
                           at System.Collections.Generic.ArraySortHelper`1.Sort(T[] keys, Int32 index, Int32 length, 
                        IComparer`1 comparer)
                           at System.Array.Sort[T](T[] array, Int32 index, Int32 length, IComparer`1 comparer)
                           at System.Collections.Generic.List`1.Sort(Comparison`1 comparison)
                           at 
                        Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.ProcessesMembership(IEnumerable`1 
                        membership)
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.ProcessRecord()
TargetObject          : 
CategoryInfo          : NotSpecified: (:) [Get-LocalGroupMember], InvalidOperationException
FullyQualifiedErrorId : An unspecified error occurred.,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {0, 1}

@sfishy
Copy link

sfishy commented May 4, 2018

FFS.

@neomancipator
Copy link

Are there any updates on this?

@itisbrendan
Copy link

itisbrendan commented May 9, 2018 via email

@itisbrendan
Copy link

itisbrendan commented Jun 13, 2023 via email

@StevieLamb
Copy link

StevieLamb commented Jul 6, 2023

I've read the comments and want to say thanks to the community for workarounds.

I also want to express my frustration with MSFT at their absurd - if predictable - combination of unwillingness to fix a widespread issue, and complete silence on why.

I recommended Office365 and a "cloud-only" approach, and one huge reason was PowerShell.
With bugs like this, and the crude mess that is the Microsoft.Graph PowerShell modules, I will not make that recommendation again.

Too often we cannot deploy scripts which conform to PowerShell coding practices via Intune: it targets Windows PowerShell, the native feature does not support parameters, the Mg cmdlets do not support pipeline.

Rant over.
Based on code from ganlbarone above I've created this function, which I'm sharing here.
I've given up trying to format it correctly in a code block, though: gee, I wonder which entity hasn't fixed that...

`
function Get-LocalAdmins {

    <#
        .SYNOPSIS
        Compensate for a known, widespread - but inexplicably unfixed - issue in Get-LocalGroupMember.
        Issue here: https://github.com/PowerShell/PowerShell/issues/2996

        .DESCRIPTION
        The script uses ADSI to fetch all members of the local Administrators group.
        MSFT are aware of this issue, but have closed it without a fix, citing no reason.
        It will output the SID of AzureAD objects such as roles, groups and users,
        and any others which cnanot be resolved.
        the AAD principals' SIDS need to be mapped to identities using MS Graph.

        Designed to run from the Intune MDM and thus accepts no parameters.

        .EXAMPLE
        $results = Get-localAdmins
        $results

        The above will store the output of the function in the $results variable, and
        output the results to console

        .OUTPUTS
        System.Management.Automation.PSCustomObject
        Name        MemberType   Definition
        ----        ----------   ----------
        Equals      Method       bool Equals(System.Object obj)
        GetHashCode Method       int GetHashCode()
        GetType     Method       type GetType()
        ToString    Method       string ToString()
        Computer    NoteProperty string Computer=Workstation1
        Domain      NoteProperty System.String Domain=Contoso
        User        NoteProperty System.String User=Administrator
    #>

    [CmdletBinding()]

    $group = [ADSI]"WinNT://$env:COMPUTERNAME/Administrators"
        $admins = $group.Invoke('Members') | ForEach-Object {
            $path = ([adsi]$_).path
            [pscustomobject]@{
                Computer = $env:COMPUTERNAME
                Domain = $(Split-Path (Split-Path $path) -Leaf)
                User = $(Split-Path $path -Leaf)
            }
        }
    return $admins
}`

@ConfigMgrRSC
Copy link

@StevieLamb i like your solution, i just updated your code to consider region specific names if OS is not installed en ;)

`
function Get-LocalAdmins {
<#
.SYNOPSIS
Compensate for a known, widespread - but inexplicably unfixed - issue in Get-LocalGroupMember.
Issue here: #2996

    .DESCRIPTION
    The script uses ADSI to fetch all members of the local Administrators group.
    MSFT are aware of this issue, but have closed it without a fix, citing no reason.
    It will output the SID of AzureAD objects such as roles, groups and users,
    and any others which cnanot be resolved.
    the AAD principals' SIDS need to be mapped to identities using MS Graph.

    Designed to run from the Intune MDM and thus accepts no parameters.

    .EXAMPLE
    $results = Get-localAdmins
    $results

    The above will store the output of the function in the $results variable, and
    output the results to console

    .OUTPUTS
    System.Management.Automation.PSCustomObject
    Name        MemberType   Definition
    ----        ----------   ----------
    Equals      Method       bool Equals(System.Object obj)
    GetHashCode Method       int GetHashCode()
    GetType     Method       type GetType()
    ToString    Method       string ToString()
    Computer    NoteProperty string Computer=Workstation1
    Domain      NoteProperty System.String Domain=Contoso
    User        NoteProperty System.String User=Administrator
#>

[CmdletBinding()]

$GroupSID='S-1-5-32-544'
[string]$Groupname = (get-localgroup -SID $GroupSID)[0].Name

#$group = [ADSI]"WinNT://$env:COMPUTERNAME/Administrators"		
$group = [ADSI]"WinNT://$env:COMPUTERNAME/$Groupname"
    $admins = $group.Invoke('Members') | ForEach-Object {
        $path = ([adsi]$_).path
        [pscustomobject]@{
            Computer = $env:COMPUTERNAME
            Domain = $(Split-Path (Split-Path $path) -Leaf)
            User = $(Split-Path $path -Leaf)
        }
    }
return $admins

}
`

@StevieLamb
Copy link

@ConfigMgrRSC an excellent addition IMHO, much appreciated

@darrelmiller
Copy link

@StevieLamb Appreciate the candid feedback. I was the person that started the Microsoft Graph PowerShell effort a number of years ago. A number of unfortunate circumstances have prevented us from enabling pipelining in cmdlets without an intermediate steps, for far too long. However, we believe we have removed those blocking issues and pipelining is something that we are going to try and improve this semester.

If there are specific pipelining scenarios that you wish were supported that would be valuable feedback for us.

@StevieLamb
Copy link

@StevieLamb Appreciate the candid feedback. I was the person that started the Microsoft Graph PowerShell effort a number of years ago. A number of unfortunate circumstances have prevented us from enabling pipelining in cmdlets without an intermediate steps, for far too long. However, we believe we have removed those blocking issues and pipelining is something that we are going to try and improve this semester.

If there are specific pipelining scenarios that you wish were supported that would be valuable feedback for us.

Firstly, you do your company great credit by owning this issue, my sincere thanks.
Secondly, that is great news regarding pipelining.

For my part?
Get-MgUser and Get-MgDevice should accept pipeline input for their UserId and DeviceId parameters, to support the classic scenarios where the person running the script has created a Collection/array of such objects. The goal would be to adequately support a pipeline where we say

$collection | ForEach-Object {
    Get-MgUser
    # do subsequent work
    }

I think the objects returned by Get-MgUser and Get-MgDevice should be accepted as an input object by cmdlets which get specific information about such objects.

For example
Get-MgUser -UserId employee@contoso.com | GetMgUserManager

This would allow us to neatly expand on the original example:

$collection | ForEach-Object {
    Get-MgUser
    $UserUPN = $_.userPrincipalName
    # this line may need correction, didn't have time to verify syntax right now, sorry
    $UserManagerUPN = Get-MgUserManager | select-object -expandproperty userPrincipalName
    $userData = [pscustomobject]@{
                    Username = $UserUPN
                    Department = $_.department
                    Manager = $UserManagerUPN
                }
    $allUserData += $userData
}

I wonder if you would consider enacting a poll on a suitable platform (TBD by MSFT) - to allow you to shortlist some initial proposals based on community feedback?
If so, you might also wish to consider publicising it via forums such as the r/PowerShell subreddit.

I look forward to enjoying the fruits of your labour :)

@StevieLamb
Copy link

@StevieLamb i like your solution, i just updated your code to consider region specific names if OS is not installed en ;)

` function Get-LocalAdmins { <# .SYNOPSIS Compensate for a known, widespread - but inexplicably unfixed - issue in Get-LocalGroupMember. Issue here: #2996

    .DESCRIPTION
    The script uses ADSI to fetch all members of the local Administrators group.
    MSFT are aware of this issue, but have closed it without a fix, citing no reason.
    It will output the SID of AzureAD objects such as roles, groups and users,
    and any others which cnanot be resolved.
    the AAD principals' SIDS need to be mapped to identities using MS Graph.

    Designed to run from the Intune MDM and thus accepts no parameters.

    .EXAMPLE
    $results = Get-localAdmins
    $results

    The above will store the output of the function in the $results variable, and
    output the results to console

    .OUTPUTS
    System.Management.Automation.PSCustomObject
    Name        MemberType   Definition
    ----        ----------   ----------
    Equals      Method       bool Equals(System.Object obj)
    GetHashCode Method       int GetHashCode()
    GetType     Method       type GetType()
    ToString    Method       string ToString()
    Computer    NoteProperty string Computer=Workstation1
    Domain      NoteProperty System.String Domain=Contoso
    User        NoteProperty System.String User=Administrator
#>

[CmdletBinding()]

$GroupSID='S-1-5-32-544'
[string]$Groupname = (get-localgroup -SID $GroupSID)[0].Name

#$group = [ADSI]"WinNT://$env:COMPUTERNAME/Administrators"		
$group = [ADSI]"WinNT://$env:COMPUTERNAME/$Groupname"
    $admins = $group.Invoke('Members') | ForEach-Object {
        $path = ([adsi]$_).path
        [pscustomobject]@{
            Computer = $env:COMPUTERNAME
            Domain = $(Split-Path (Split-Path $path) -Leaf)
            User = $(Split-Path $path -Leaf)
        }
    }
return $admins

} `

@ConfigMgrRSC I've enhanced this a little bit, thanks to the work of Oliver Kieselbach shown at
https://oliverkieselbach.com/2020/05/13/powershell-helpers-to-convert-azure-ad-object-ids-and-sids/comment-page-1/?unapproved=35782&moderation-hash=a541c2ea9e0cad096d276109a002d5e5#comment-35782

Combining one of his functions with your revised function, we get this.
It will take the SIDs returned as members, and record their AAD OvjectIDs.
(Quick and dirty: I couldn't get a reliable comparison going for an if statement to skip over local users, and the Outputs statement is incomplete - missing the object id)

function Get-LocalAdmins {

    <#
        .SYNOPSIS
        Replacement for non-functional Get-LocalgroupMember, which has an unfixed issue with broad scope of impact.
        Issue here: https://github.com/PowerShell/PowerShell/issues/2996
        Credits:
        @ganlbarone on GitHub for the base code
        @ConfigMgrRSC on Github for the localisation supplement

        .DESCRIPTION
        The script uses ADSI to fetch all members of the local Administrators group.
        MSFT are aware of this issue, but have closed it without a fix.
        It will output the SID of AzureAD objects such as roles, groups and users,
        and any others which cannot be resolved.

        Designed to run from the Intune MDM and thus accepts no parameters.

        .EXAMPLE
        $results = Get-localAdmins
        $results

        The above will store the output of the function in the $results variable, and
        output the results to console

        .OUTPUTS
        System.Management.Automation.PSCustomObject
        Name        MemberType   Definition
        ----        ----------   ----------
        Equals      Method       bool Equals(System.Object obj)
        GetHashCode Method       int GetHashCode()
        GetType     Method       type GetType()
        ToString    Method       string ToString()
        Computer    NoteProperty string Computer=Workstation1
        Domain      NoteProperty System.String Domain=Contoso
        User        NoteProperty System.String User=Administrator
    #>

    [CmdletBinding()]

    $GroupSID='S-1-5-32-544'
    [string]$Groupname = (get-localgroup -SID $GroupSID)[0].Name
    
    $group = [ADSI]"WinNT://$env:COMPUTERNAME/$Groupname"
        $admins = $group.Invoke('Members') | ForEach-Object {
            $path = ([adsi]$_).path
            $memberSID = $(Split-Path $path -Leaf)
            $AadObjectID = Convert-AzureAdSidToObjectId -Sid $memberSID -ErrorAction SilentlyContinue
            [pscustomobject]@{
                Computer = $env:COMPUTERNAME
                Domain = $(Split-Path (Split-Path $path) -Leaf)
                User = $(Split-Path $path -Leaf)
                ObjectID = $AadObjectID
            }
        }
    return $admins
    
}

function Convert-AzureAdSidToObjectId {
    <#
    .SYNOPSIS
    Convert a Azure AD SID to Object ID
     
    .DESCRIPTION
    Converts an Azure AD SID to Object ID.
    Author: Oliver Kieselbach (oliverkieselbach.com)
    The script is provided "AS IS" with no warranties.
     
    .PARAMETER Sid
    The SID to convert
    #>
    
    [CmdletBinding()]
    param([String] $Sid)

    $text = $sid.Replace('S-1-12-1-', '')
    $array = [UInt32[]]$text.Split('-')

    $bytes = New-Object 'Byte[]' 16
    [Buffer]::BlockCopy($array, 0, $bytes, 0, 16)
    [Guid]$guid = $bytes

    return $guid
}

@CortComp
Copy link

CortComp commented Aug 4, 2023

Just running across this and ended up here. Not fantastic at PS, is there a way to pipe these results straight into something like remove-localgroupmember (even if it's an azure/domain/whatever user) so the group ends up empty?

@timwest95
Copy link

Just running across this and ended up here. Not fantastic at PS, is there a way to pipe these results straight into something like remove-localgroupmember (even if it's an azure/domain/whatever user) so the group ends up empty?

#use the old net localgroup command to get members of the local Administrators group, then parse the text output, excluding the built-in Administrator user and Domain Admins group
$LocalAdmins = net localgroup administrators| where {$_ -and $_ -notmatch "command completed successfully" -and $_ -notmatch '^Administrator$' -and $_ -notmatch 'Domain Admins'} | select -skip 4

#Convert the text to an array
$LocalAdmins = $LocalAdmins.Split([Environment]::NewLine) | ? { $_ -ne "" }

#Example of looping through the array
foreach ($user in $LocalAdmins) {
  Write-Host "Removing $user from local Administrators group"
  Remove-LocalGroupMember -Group "Administrators" -Member $user
}

@CortComp
Copy link

CortComp commented Aug 4, 2023

Just running across this and ended up here. Not fantastic at PS, is there a way to pipe these results straight into something like remove-localgroupmember (even if it's an azure/domain/whatever user) so the group ends up empty?

#use the old net localgroup command to get members of the local Administrators group, then parse the text output, excluding the built-in Administrator user and Domain Admins group
$LocalAdmins = net localgroup administrators| where {$_ -and $_ -notmatch "command completed successfully" -and $_ -notmatch '^Administrator$' -and $_ -notmatch 'Domain Admins'} | select -skip 4

I'll give this a run. I do want to remove the built in admin (or disable it but that's easy) and the domain admins group if it exists, a full nuke, so i'll try different variations. Can i ask what the -skip 4 does?

@StevieLamb
Copy link

StevieLamb commented Aug 4, 2023

Just running across this and ended up here. Not fantastic at PS, is there a way to pipe these results straight into something like remove-localgroupmember (even if it's an azure/domain/whatever user) so the group ends up empty?

I'd recommend against scripting that element, because better options exist, it'll only work that way as long as nothing else gets broken by incomplete regression testing, and (this one personal) I don't like scripts which mix PowerShell and batch programming.

Use Group Policy's Restricted Groups feature if you're in an AD DS environment (a.k.a. "on-premise AD"):
https://learn.microsoft.com/en-us/troubleshoot/windows-server/group-policy/description-of-group-policy-restricted-groups

If using Intune to manage devices in a pure Azure AD directory environment (no on-premise AD), instead use the option under Endpoint security >> Account protection which does the same thing as the Restricted Groups.
https://techcommunity.microsoft.com/t5/intune-customer-success/new-settings-available-to-configure-local-user-group-membership/ba-p/3093207

This article gives a description of group policy restricted groups.
TECHCOMMUNITY.MICROSOFT.COM
We are pleased to announce a new experience to configure local user group membership settings for Windows devices!

@CortComp
Copy link

CortComp commented Aug 4, 2023

I'd recommend against scripting that element, because better options exist, it'll only work that way as long as nothing else gets broken by incomplete regression testing, and (this one personal) I don't like scripts which mix PowerShell and batch programming.

Use Group Policy's Restricted Groups feature if you're in an AD DS environment (a.k.a. "on-premise AD"): https://learn.microsoft.com/en-us/troubleshoot/windows-server/group-policy/description-of-group-policy-restricted-groups

If using Intune to manage devices in a pure Azure AD directory environment (no on-premise AD), instead use the option under Endpoint security >> Account protection which does the same thing as the Restricted Groups. https://techcommunity.microsoft.com/t5/intune-customer-success/new-settings-available-to-configure-local-user-group-membership/ba-p/3093207

**Description of group policy restricted groups - Windows Server**This article gives a description of group policy restricted groups.

<img alt="" width="48"

Understood but i'm looking for a nuke and pave solution for multiple environments where there may or may not be a local domain, azure/intune in place. Users in the group may be local, domain, azure, or groups and any or all may or may not still exist (and be orphaned with just SIDs). So, looking to make something heavy handed we can deploy to be sure there are no local admins and then we can organize and bring them up to a baseline if required.

This article gives a description of group policy restricted groups.
TECHCOMMUNITY.MICROSOFT.COM
We are pleased to announce a new experience to configure local user group membership settings for Windows devices!

@matesolutions
Copy link

WTF Microsoft. Can you please fix this blatant issue? It has been so long already

@ConfigMgrRSC
Copy link

ConfigMgrRSC commented Aug 14, 2023

Just running across this and ended up here. Not fantastic at PS, is there a way to pipe these results straight into something like remove-localgroupmember (even if it's an azure/domain/whatever user) so the group ends up empty?

#use the old net localgroup command to get members of the local Administrators group, then parse the text output, excluding the built-in Administrator user and Domain Admins group
$LocalAdmins = net localgroup administrators| where {$_ -and $_ -notmatch "command completed successfully" -and $_ -notmatch '^Administrator$' -and $_ -notmatch 'Domain Admins'} | select -skip 4

I'll give this a run. I do want to remove the built in admin (or disable it but that's easy) and the domain admins group if it exists, a full nuke, so i'll try different variations. Can i ask what the -skip 4 does?

well this one does not recognize localisation of the administrators group - personally i wrote a function to clean out all except the local admin and testet this in onprem and AAD only environment ( not hybrid) to cleanup. basically i agree, dont like to mix up several techniques and try to be powershell only, but in this case this was the only solution for me..

function clean-LocalgroupTargetSID{
<#
.SYNOPSIS
cleanout local group except localAdministrator, default group SID is S-1-5-32-544
 
.DESCRIPTION
use ADSI for getting group members because of bug in get-localgroupmember "get-LocalGroupMember : Failed to compare two elements in the array" if there is any kind of SID in group
# https://github.com/PowerShell/PowerShell/issues/2996 

# https://www.petervanderwoude.nl/post/remediating-local-administrators-with-proactive-remediations/
# https://superuser.com/questions/1131901/get-localgroupmember-generates-error-for-administrators-group/1205981#1205981
 
.PARAMETER GroupSID
The local SID of Targetgroup to cleanup
#>

    param([String] $GroupSID='S-1-5-32-544')

    #https://blog.iisreset.me/identifying-well-known-security-principals-with-confidence/
    # find localized localadmin account via well knownSID 
    [string]$localizedadmincaption = (Get-WmiObject -Query "SELECT * FROM Win32_UserAccount WHERE LocalAccount = 'True'"|Where-Object -Property SID -Like "S-1-5-21-*-500").caption
    Log -LogFile $LogFile "Administrator caption is $localizedadmincaption"

    #get groupname for ADSI
    [string]$Groupname = (get-localgroup -SID $GroupSID)[0].Name
    Log -LogFile $LogFile "Administratorsgroup Name is $Groupname"

    #get members of group via ADSI
    $administrators = $null
    $administrators = @(
        ([ADSI]"WinNT://./$Groupname").psbase.Invoke('Members') |ForEach-Object {
            $_.GetType().InvokeMember('AdsPath','GetProperty',$null,$($_),$null) 
            }
        ) -match '^WinNT';

    # string conversions
    $administrators = $administrators -replace "WinNT://",""
    $administrators = $administrators -replace "/","\"
    
    Log -LogFile $LogFile "start adsi removal $($administrators.count)"
    # remove every member except local Administrator
    $administrators |ForEach-Object{
            
        if ($_ -ne $localizedadmincaption){
            
            try{
                    Remove-LocalGroupMember -SID $GroupSID -Member $_ -erroraction Stop
                    Log -LogFile $LogFile "Successfully removed $_ from $Groupname ($LocalgroupTargetSID)" 
            }catch{
                    Log -LogFile $LogFile -ErrorMessage "Remove-LocalGroupMember of $_ failed $($Error[0])"
                }

        }else{
            Log -LogFile $LogFile "skip because local admin $localizedadmincaption"
        }
    }

    # should be readable now because SIDs are already cleared 
    $administrators = $null
    $administrators = get-LocalGroupMember -SID $GroupSID -ErrorAction Stop

    
    if ($administrators.Count -gt 1){
        
        Log -LogFile $LogFile "start get-LocalGroupMember removal $($administrators.count)"    
        $administrators |ForEach-Object{
            
            if ($_.Name -ne $localizedadmincaption){
            
                try{
                        Remove-LocalGroupMember -SID $GroupSID -Member $_ -ErrorAction Stop
                        Log -LogFile $LogFile "Successfully removed $_ from $Groupname ($LocalgroupTargetSID)" 
                }catch{
                        Log -LogFile $LogFile -ErrorMessage "Remove-LocalGroupMember of $_ failed $($Error[0])"
                    }

            }else{
                Log -LogFile $LogFile "skip because local admin $env:COMPUTERNAME\Administrator"
            }
        }
    }else{
        Log -LogFile $LogFile "Local group count ($GroupSID) is $($administrators.Count)"
    }
}

@MonDeveloper
Copy link

Error is still present on a fresh Win11 joined to a Domain once and never revert to workgroup.

PS C:\Users\xxxxxxxxxxx> [System.Environment]::OSVersion.Version

Major  Minor  Build  Revision
-----  -----  -----  --------
10     0      22621  0

PS C:\Users\xxxxxxxxxxx> Get-LocalGroupMember -Group 'Administrators'
Get-LocalGroupMember: Failed to compare two elements in the array.
PS C:\Users\xxxxxxxxxxx> $Error[0] | fl * -force

PSMessageDetails      :
Exception             : System.InvalidOperationException: Failed to compare two elements in the array.
                         ---> System.NullReferenceException: Object reference not set to an instance of an object.
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.<>c.<ProcessesMembership>b__20_0(LocalPrincipal p1, LocalPrincipal p2)
                           at System.Collections.Generic.ArraySortHelper`1.InsertionSort(Span`1 keys, Comparison`1 comparer)
                           at System.Collections.Generic.ArraySortHelper`1.IntroSort(Span`1 keys, Int32 depthLimit, Comparison`1 comparer)
                           at System.Collections.Generic.ArraySortHelper`1.Sort(Span`1 keys, Comparison`1 comparer)
                           --- End of inner exception stack trace ---
                           at System.Collections.Generic.ArraySortHelper`1.Sort(Span`1 keys, Comparison`1 comparer)
                           at System.Collections.Generic.List`1.Sort(Comparison`1 comparison)
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.ProcessesMembership(IEnumerable`1 membership)
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.ProcessGroup(LocalGroup group)
                           at Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand.ProcessRecord()
TargetObject          :
CategoryInfo          : NotSpecified: (:) [Get-LocalGroupMember], InvalidOperationException
FullyQualifiedErrorId : An unspecified error occurred.,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at <ScriptBlock>, <No file>: line 1
PipelineIterationInfo : {0, 1}

@GoodThings2Life
Copy link

I can't believe it's been almost 7 full years since this was opened, a fix was identified and rejected, and Microsoft still can't be bothered to acknowledge it. Maybe we should start a campaign to submit this thread URL to Jeff Snover and see if he can get a set of eyes on it.

@razgrim
Copy link

razgrim commented Nov 7, 2023

My workaround to this problem was shifting career out of the Windows ecosystem.

@PwshPally
Copy link

PwshPally commented Nov 7, 2023 via email

@AndresPae
Copy link

This is still issue ! Scenario is little different ( domain membeserver has domain objects in local Admin group, but those domain objects are deleted, so they are not resolved and SID is dispalyed in GUI) . PS fails miserably with same error.

@Keybonesabi
Copy link

Keybonesabi commented Dec 14, 2023 via email

@3vi1
Copy link

3vi1 commented Dec 16, 2023

Ridonkulous that this has been a known problem for so long. I experienced it with Win 11 and a server that always been joined to our main domain (likely because it had admin members from a trusted domain that's no longer present). There's no good reason for the command to fail completely in scenarios like this.

@BrendanHere
Copy link

BrendanHere commented Dec 18, 2023 via email

@Kaioty
Copy link

Kaioty commented Jan 20, 2024

Attempted to use this in Win11Pro to verify that my script is working properly but it still returns the same error.

@alexipeck
Copy link

alexipeck commented Jan 24, 2024

If anyone is looking for a workaround where getting an array of usernames is the goal and are fine with the old "net localgroup administrators", keeping in mind that this won't provide you with the user object, here are a couple of implementations:

Get all users in the group:
$(net localgroup administrators) | Where-Object { -not ($_ -match '^-+$|^The command completed successfully.$|^Members$|^Alias name\s+administrators$|^Comment\s+Administrators have complete and unrestricted access to the computer/domain$|^$') -and $_.Trim() -ne '' }

Get all users minus a few matching a regex filter, adding pipe | separated usernames (e.g, "Administrator") or more complex filters (e.g, ".*Domain Admins"):
$(net localgroup administrators) | Where-Object { -not ($_ -match 'Administrator|.*Domain Admins|^-+$|^The command completed successfully.$|^Members$|^Alias name\s+administrators$|^Comment\s+Administrators have complete and unrestricted access to the computer/domain$|^$') -and $_.Trim() -ne '' }

@emilwojcik93
Copy link

emilwojcik93 commented Feb 10, 2024

Issue

I was able to make an workaround for this issue because it's still exists in:

OSVersion                     : 2009
OSEdition                     : Microsoft Windows 11 Enterprise
OSBuild                       : 22621.3007
CurrentInstalledUpdate        : January 9, 2024 - KB5034123 (OS Builds 22621.3007 and 22631.3007)

Example:

> Get-LocalGroupMember -Group "Administrators"
Get-LocalGroupMember : Failed to compare two elements in the array.
At line:1 char:1
+ Get-LocalGroupMember -Group "Administrators"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Get-LocalGroupMember], InvalidOperationException
    + FullyQualifiedErrorId : An unspecified error occurred.,Microsoft.PowerShell.Commands.GetLocalGroupMemberCommand

There is an .NET method WindowsIdentity.GetCurrent Method

Workaround Script:

param(
    [Parameter(Mandatory=$true, Position=0)]
    [Alias("g")]
    [string]$GroupName
)

function CheckGroupMembership {
    param([string]$groupName)

    $id = [Security.Principal.WindowsIdentity]::GetCurrent()
    $groups = $id.Groups | foreach-object {$_.Translate([Security.Principal.NTAccount])}

    $isMember = ($groups.Value | Where-Object { $_.Split('\')[-1] -eq $groupName } | Measure-Object).Count -gt 0

    if ($isMember) {
        Write-Host "User: `"$($id.Name)`" is a member of a group ending with `"$groupName`"."
    } else {
        Write-Host "User: `"$($id.Name)`" is not a member of any group ending with `"$groupName`"."
    }
}

CheckGroupMembership -groupName $GroupName

Examples:

Administrators:

> .\autosetup\deps\test-group.ps1 -groupName "Administrators"
User: "XXXXXX" is not a member of any group ending with "Administrators".

Users:

> .\autosetup\deps\test-group.ps1 -groupName "Users"
User: "XXXXXX" is a member of a group ending with "Users".

Further reading

@subcat
Copy link

subcat commented Apr 16, 2024

if anyone is still getting this, i found that if an unknown/deleted user exists in the queried group, the command fails. you need to remove the SID of the unknown / non existing user from the group. this resolved the issue for me.

@3vi1
Copy link

3vi1 commented Apr 16, 2024

Yes. I gave up on it and had to go with ADSI instead. I've got thousands of servers with plenty of deleted accounts from retired employees and former contractors that the owners put in local groups over the last 20 years (trying to clean that up separately; I needed something that works now).

@iSazonov
Copy link
Collaborator

iSazonov commented May 16, 2024

The bug was fixed in PowerShell 7.4+ compatible (unofficial) version of the Microsoft.PowerShell.LocalAccounts module
https://github.com/iSazonov/LocalAccounts-MS/tree/v7.0.0-Release.1

GitHub
Contribute to iSazonov/LocalAccounts-MS development by creating an account on GitHub.

This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Bug Issue has been identified as a bug in the product Resolution-External The issue is caused by external component(s). WG-Cmdlets general cmdlet issues
Projects
None yet
Development

Successfully merging a pull request may close this issue.