Powershell to grab ADGroups, members, then NTFS Permissions on shares RRS feed

  • General discussion

  • Hi,

    Relatively new to powershell and its concepts but learning as I go.

    Im currently evaluating a number of legacy file servers as we are looking forward to a building move as well as new hardware in "the new world".  Part of this is to evaluate both our AD Groups which there is a lot of dead weight in, as well as later on, windows file server shares which I can cross check access against this list to allow us to drop old shares and delete no longer needed groups etc. (This is an estate which hasnt really had any housekeeping for around 10 years, just had several waves of consolidation as companies have been merged...

    With this bit of powershell Im trying to generate a report of sorts.

    Listing 1 row for each AD Group, a count of members, the number of inactive(disabled accounts) members, and a list of users/groups in each group.  I can then port this into a spreadsheet and start filtering etc.


    GROUP, Member Count, Inactive Count, Members:

    Infrastructure Team, 7, 5, "Bjones, BDavies, Jsmith, Kbarlow, Sappleton, Pdint, Rwright, Amarkam"

    I guess the following Powershell is heading in the right direction but I know this can be done it ma much cleaner way.

    Any input or guidance would be great! :)


    # Get the list of SECURITY-GROUPS from AD (Domain not specified as local machine and logged in user are both domain members of the domain being queried.
    $SecurityGroups = get-adgroup -filter {groupcategory -eq "security" } | select samaccountname | sort samaccountname 
    $SecurityGroups | ft
    write-host TOTAL GROUPS : $SecurityGroups.count
    # Work through the list of groups to identify members and count of members (and inactive members)
    foreach ($SecurityGroup in $SecurityGroups) {
        $members = get-adgroupmember -identity $name
        $Membercount = $members.count
    #    $userdisabled = $members | where {$_.Enabled -eq $false}
        $DisabledCount = $userdisabled.count
        # Check that there are members before trying to process data on them
        if ($Membercount -gt 0) {
            [int]$Inactivemembers = 0
            # Work through each group processing members one at a time
            foreach ($member in $Members) {
                $userdisabled = ""
                #Im sure I can do the following command as a single command without the loop to count the disabled accounts in the group... but for now this will do...
                [array]$userdisabled = Get-ADUser -filter {samaccountname -eq $member.samaccountname -and Enabled -eq $false} 
                if ($userdisabled.enabled -eq $false) {
                    $Inactivemembers += 1

    Many thanks

    • Edited by Dustynet Thursday, December 22, 2016 7:44 AM insert code block
    • Changed type Bill_Stewart Friday, February 17, 2017 4:24 PM
    Friday, November 25, 2016 1:23 PM

All replies

  • Could you please format your code as code in the future here in the forum?

    Your request is too unspecific? Do you get some errors? Or do you get other than the expected results? Or do you have a particular question to a particular snippet of code then you should ask this.

    Grüße - Best regards

    PS:> (79,108,97,102|%{[char]$_})-join''

    • Edited by BOfH-666 Friday, November 25, 2016 3:40 PM
    Friday, November 25, 2016 3:39 PM
  • Your request doesn't make much sense or seem very useful but here:

    get-adgroup -filter { groupcategory -eq "security" } | 
    	Get-AdGroupMember |
    	where{ $_.objectClass -eq 'user' } |
    	Get-Aduser |
    	Group Enabled | 
    	Select @{n='Enabled';e={$_.Name}}, Count


    Friday, November 25, 2016 3:54 PM
  • Thanks for the response.

    Your condensed PS takes a long time to complete, due to the call after call for AD data.

    I was looking for something quicker in processing time and came up with the idea of querying ADUsers and ADGroups (both relatively quick queries in themselves), then proccessing in memory.

    This resulted in the following code which produces the output I was looking for.  Specifically, something useful for generating a report which I can save to Excel, then use for AD housekeeping.

    This is useful as it clearly identifies groups with no members, groups with volumes of disabled accounts, security groups with email addresses etc which can all be reviewed and managed accordingly.

    import-module activedirectory
    # -------------------------------------------------
    # Check if we can write output files to the desktop
    # -------------------------------------------------
    #$outputfile1 = "$env:userprofile\desktop\ADGroups.txt"
    $outputfile2 = "$env:userprofile\desktop\ADGroupMembers.txt"
    try {
        write-host Output File will be : $outputfile2
        out-file -filepath $outputfile2 -inputobject "ADGroups" -encoding ascii
    catch {
        write-host "Unable to write to the location: $outputfile2"
    # write out the heading for the output file
    out-file -filepath $outputfile2 -inputobject "NAME,TYPE, EMAIL,MEMBERS,INACTIVE,MEMBERS" -encoding ascii
    # Set a progress counter so that the WRITE-PROGRESS bar can update in reference to the $ADGroups loop
    # Get list of AD Groups
    $ADGroups = get-adgroup -filter * -properties *| where {$_.sid -notlike 'S-1-5-32*'} | sort name
    # Get list of AD users
    $ADUsers = get-aduser -filter * -Properties MemberOf | where {$_.sid -notlike '*-5??'} #| select name, samaccountname, enabled, sid, memberof | sort samaccountname
    write-host TOTAL GROUPS : $ADGroups.count
    write-host TOTAL USERS  : $ADUsers.count
    # Work through the list of groups to identify members and count of members (and inactive members which are prefixed with *)
    foreach ($ADGroup in $ADGroups) {
    # Nice progress bar
        Write-Progress -Activity "Compiling Data" -status "Progress:" -currentoperation $GroupName -percentcomplete (($ProgressCounter / $ADGroups.count) * 100)
        $GroupName = $ADGroup.name
        $groupCat = $ADGroup.groupcategory
        $groupmail = $ADGroup.mail
        $membercount = 0
        $inactivecount = 0
        $membernames = @()
    # Run through each ($ADUSER.SAMACCOUNTNAME).MEMBEROF to match against $ADGROUP.name for matches
        foreach ($user in $ADusers) {
            $member = $user | where {$_.memberof -like "*$groupname*"}
            if ($member.length -lt 1) { 
    # This user is not a match (resulting user count=0)
            } else {
    # We got a matching user who is a member of $ADGROUP.NAME
                if ($user.enabled -eq $true) {
                    $membernames += $user.samaccountname
    #                write-host "    " $groupname ":"$user.samaccountname
                } else {
    #   Tag the disabled accounts with a * symbol 
                    $membernames += "*" + $user.samaccountname
    #                write-host "    " $groupname ":*"$user.samaccountname
                } # end of if $user enabled
            } # end of if $member.length
        } # end of foreach $User
    #   This group is finished processing
    #   Sort the list of members into a string to make life simple when using the data...
        $memberstring = ""
        $membernames = $membernames | sort 
    #   Pipe the data into a pipe delimited string for output
        foreach ($member in $membernames) {
            $memberstring += "$member|"
        write-host "$GroupName,$groupCat,$groupmail,$Membercount,$inactivecount,$memberstring"
        out-file -filepath $outputfile2 -inputobject "$GroupName, $groupCat, $groupmail, $Membercount, $inactivecount, $memberstring" -append -encoding ascii
    write-host "Complete!"

    While this code may not exactly be great, it produces exactly what I want in the way of output.

    I import this file into Excel using text to columns, using comma as the delimiter, and save off for reference.  

    This has saved hours if not days over the last couple of weeks dipping in and out of housekeeping AD.

    One thing I think I could do better is use an array to store the resulting data, but as I say, Im new to Powershell so revising this can go on a to-do list.

    Just wanted to share the results.


    • Edited by Dustynet Thursday, December 22, 2016 8:11 AM
    Thursday, December 22, 2016 8:07 AM