Home > Software design >  Powershell - Test if user is part of any Groups
Powershell - Test if user is part of any Groups

Time:02-16

I'm having trouble getting a small PS script to work the way I want it to.

Powershell version: 5.1

Ultimate goal: I want to parse all existing local User accounts and generate a list of those that are not part of any local Groups. (This is not an AD environment, nor part of a domain. This is all just local OS accounts and Groups.) Also, I am only interested in the Groups that I have manually created - I don't care about the default System Groups. (More on how I try to achieve this, later.) And then, after I get this part working, this output (list of User names) will then be used (in the future - not shown in this code) as input to another block that will add these not-in-a-Group users to a Group.

I found an example bit of code - which worked, and resulted in the correct set of user names. But it was slow - it took >5 minutes. So I wanted something faster.

The approach that I'm working with now generally seems like it will work, and is pretty quick. I'm just having trouble getting it to restrict things down correctly. It seems I'm having trouble referencing properties of objects returned by the cmdlets. (See code a bit further down. There are various counters and write-host steps in here, too, that are purely for helping me see what's going on and debugging - they aren't required for the actual task.)

My general outline of how I am going about this:

  1. Compile a list of all Users in all Groups

    • But, I only want Groups that have no Description - these are the ones that I have created on the machine. The OS default Groups all have a Description. This will help me narrow down my list of Users.
  2. Loop over the list of all Users on the system

    • Compare each user to the List from Step 1
    • If User is on the List, then that User is IN a Group, so skip it
    • If User is not on the List, then save/report that Name back [Side note - the user 'WDAGUtilityAccount' turned out to also not be in any Groups, but I don't want to change that one; so have a specific test to exclude it from the list.]

[original version of code]

# ---  Part 1
$UsersList = foreach ( $aGroup in get-localgroup ) {
    $groupcount  

    # Only want Groups that don't have a Description
    if ( $null -eq $aGroup.Description ) {
        Get-LocalGroupMember $aGroup.name
    }

    write-host "$groupCount -- $aGroup.Name _ $aGroup.Description"
}

#  Just for debugging - to see the content of Part 1
write-host "List = $UsersList"


# ---- Part 2
Get-LocalUser | ForEach-Object {
    $count  
    $name = $_.Name
    if ( $name -eq "WDAGUtilityAccount" ) {
        # nothing - skip this one
    } elseif ( $UsersList.Name -inotcontains "$env:COMPUTERNAME\$_" ) {
        $count2  
        write-host "$Count ($Count2) :  $name --  not a part of any groups"
    }
} 

It appears that my attempts to extract the Properties of the Group in Part 1 are failing - I am getting literal text 'Name' and 'Description', instead of the aGroup.Name aGroup.Description property values. So my output looks like "MyGroup1.Name" instead of "MyGroup1" (assuming the actual name of the group is 'MyGroup1').

I believe that I am approaching the 'Group' object correctly - when I do 'get-localgroup | get-member" it says that it is a 'LocalGroup' object, with various properties (Name and Description being two of those).

There may be many other approaches to this - I'm interested in hearing general ideas; but I would also like to know the specific issues with my current code - it's a learning exercise. :)

Thanks, J


[ Version 2 of code - after some suggestions... ]

     $UsersList = foreach ( $aGroup in get-localgroup ) {
        $groupcount  
        #Write-Host $aGroup.Description

        # Only want Groups that don't have a Description (i.e. are the Groups that we created, not the default System/OS groups)
        if ( $null -eq $($aGroup.Description) ) {
            $UserList  = Get-LocalGroupMember $($aGroup.name)
            write-host "$groupCount -- $($aGroup.Name) _ $($aGroup.Description)"
        }
    }

    write-host "List = $UsersList"

    Get-LocalUser | ForEach-Object {
        $count  
        $name = $_.Name
        if ( $name -eq "WDAGUtilityAccount" ) {
            # nothing - skip this one
        } elseif ( $($UsersList.name) -inotcontains "$env:COMPUTERNAME\$_" ) {
            $count2  
            write-host "$Count ($Count2) :  $name --  not a part of any groups"
        }
    } 

CodePudding user response:

I believe this could be reduced to:

  1. Store all members of a any group where the group's Description is null.
  2. Get all local users and filter where their user's Name is not equal to WDAGUtilityAccount and they are not part of the stored member's SID array.
$members = Get-LocalGroup | Where-Object { -not $_.Description } | Get-LocalGroupMember
Get-LocalUser | Where-Object {
    $_.Name -ne 'WDAGUtilityAccount' -and $_.SID -notin $members.SID
} | Format-Table -AutoSize
  • Related