Check when user was added to AD group

Today I will show you script to check when user was added to AD group.

Script is using functionality of repadmin tool to check when users were modified inside the group.
Showobjmeta displays the replication metadata for a specified object stored in Active Directory, so it can be used not only for group membership checking.
You can find other functionalities of this tool on TechNet site.
Output from repadmin tool is parsed by regex to read all information in easy way and put them in Powershell object(in our case it’s Array).

Example of usage:

Get-ADGroupMemberDate -Group "Domain Admins"

Script:

Function Get-ADGroupMemberDate {
    
    [cmdletbinding()]
    Param (
        [parameter(ValueFromPipeline=$True,ValueFromPipelineByPropertyName=$True,Mandatory=$True)]
        [string]$Group
        
    )
    Begin {
        
        [regex]$pattern = '^(?<State>\w+)\s+member(?:\s(?<DateTime>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2})\s+(?:.*\\)?(?<DC>\w+|(?:(?:\w{8}-(?:\w{4}-){3}\w{12})))\s+(?:\d+)\s+(?:\d+)\s+(?<Modified>\d+))?'
        $DomainController = ($env:LOGONSERVER -replace "\\\\")
        If(!$DomainController)
        {
            Throw "Computer from which script is run is not joined to domain and domain controller can not be identified."
            Break
        }
    }
    Process
    {
        Write-Verbose "Checking distinguished name of the group $Group"
        Try
        {
            $distinguishedName = (Get-ADGroup -Identity $Group).DistinguishedName
        } 
        Catch 
        {
            Write-Warning "$group can not be found!"
            Break                
        }
        $RepadminMetaData = (repadmin /showobjmeta $DomainController $distinguishedName | Select-String "^\w+\s+member" -Context 2)
        $Array = @()
        ForEach ($rep in $RepadminMetaData) 
        {
           If ($rep.line -match $pattern) 
           {
               
               $object = New-Object PSObject -Property  @{
                    Username = [regex]::Matches($rep.context.postcontext,"CN=(?<Username>.*?),.*") | ForEach {$_.Groups['Username'].Value}
                    LastModified = If ($matches.DateTime) {[datetime]$matches.DateTime} Else {$Null}
                    DomainController = $matches.dc
                    Group = $group
                    State = $matches.state
                    ModifiedCounter = $matches.modified
                }
                
                $Array += $object
                
            }
        }
    
    }
    End
    {
        $Array = $Array | Format-Table -AutoSize
        $Array
    }
}

In result you will receive array with information with folowing informations:
Username – full name of the user which is/was a member of specific group
LastModified – information when user was added or removed from group
DomainController – information on which DC user was added/removed
Group – name of the group
State – information about user membership – PRESENT or ABSENT
ModifiedCounter – information about how often user account was modified in group

Now you know how to check when user was added to AD Group.

I hope it will be usefull for some of you 🙂
Enjoy!

16 thoughts on “Check when user was added to AD group

  1. Get-ADGroupMemberDate : The term ‘Get-ADGroupMemberDate’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the
    path is correct and try again.
    At line:1 char:1
    + Get-ADGroupMemberDate
    + ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (Get-ADGroupMemberDate:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    1. Hi Chad,

      Before you call function you must load it to your PowerShell code editor (ISE, Visual Studio Code, etc).
      Copy code from Script part, paste to your editor and run.
      Right after that you can use command Get-ADGroupMemberDate -Group “GroupName”.
      Hope now it’s clear 😉

      Regards,
      Artur

  2. Great script, I tested it on a Server 2016 environment and got positive results. The only thing missing is which UserAccount added the user as member to the ADGroup.

  3. I believe there is a bug. If the AD user name has a comma which AD escapes for the DN with a slash, then the slash is erroneously returned. e.g. User name “Bob Smith, MD” returns a user name of “Bob Smith /”

    1. Username = [regex]::Matches($rep.context.postcontext,”CN=(?.*\\?),.*”) | ForEach {$_.Groups[‘Username’].Value}

      add \\ see above.

    1. You can find this in security eventlog:

      $DCs = (Get-ADDomainController -filter *).name
      $Results = @()
      $Results = Invoke-Command -ComputerName $DCs -ErrorAction SilentlyContinue -ScriptBlock {

      #Events criteria
      $Filter = @{
      LogName = ‘Security’
      ID = 4732, 4728, 4729
      }
       
      # Get events
      $Events = Get-WinEvent -FilterHashtable $Filter | select id, timecreated, properties,message
      If( $Events ){
      Foreach ( $Event in $Events ){
       
      $Object = @{} | Select ‘Event ID’, ‘Time created’, ‘Message’, ‘Subject user’, ‘Target user’, ‘Group name’
      $Object.’Event ID’ = [string]$Event.id
      $Object.’Time created’ = $Event.timecreated
      $Object.’Message’ = ($Event.Message -split (‘[\r\n]’))[0]
      $Object.’Subject user’ = $Event.Properties[-4].value
      $Object.’Target user’ = $Event.Properties[0].value
      $Object.’Group name’ = $Event.Properties[2].value
      $Object
      }
      }
       
      } | Select @{n=’ServerName’;e={$_.pscomputername}},’Event ID’, ‘Time created’, ‘Message’, ‘Subject user’, ‘Target user’, ‘Group name’
       
      $Results | ogv -title ‘Events’

  4. Get-ADGroupMemberDate -Group “Domain Admins” |out-gridview
    Get-ADGroupMemberDate -Group “Domain Admins” |export-csv -path .\desktop\adgroup.csv -notypeinformation
    output format is not support. please help me how can i do

  5. There’s a small (but significant) bug: if repadmin returns the DC’s name rather than GUID, if the DC’s name has a hyphen in it, the RegEx will only capture PRESENT or ABSENT and will not match any of the rest of the details. A simple fix is to change the part of the DC capture that has ‘\w+’ to instead read ‘\w[-\w]+’. This will accurately capture letters, numbers, underscores, and hyphens in DC names.

  6. Hi All,
    I am new to powershell and i was looking for a same script but with some advancement like-

    1.The script should be able to iterate through specific group like(Group1,Group2,Group3).
    2.I want the script to fetch data of users added/removed from specific group(Group1,Group2,Group3) in last 24 hours.
    3. And in the last it should contain the below mentioned columns exported to csv with it’s values.

    ‘ID’ = $obj.SamAccountName
    ‘Name’ = $obj.name
    ‘Group Name’ = $groupName
    ‘Created on’ = $obj.whenCreated
    ‘Email Address’ = $obj.EmailAddress
    ‘UPN’ = $obj.UserPrincipalName
    ‘DN’ = $obj.DistinguishedName
    ‘State’ = $matches.state
    ‘ModifiedCounter’ = $matches.modified

    Thanks in advance!!!!

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.