Sometimes you do adds to a group for reasons. Maybe you are doing a staged migration of things and you are using a group to do that. Maybe someone wants a report of new users added in the last week. This can help do that for you. To complete this, you just need to run a command or two and generate your starting file to compare to. Then you setup a scheduled task to run on a weekly basis and there you have it! If you have had no changes, then it will not email you. If you do have changes, it will email with attachment and count of number of objects added. This also does this based on the named dates of the files so if you need to run it earlier, you will need to do a copy of the file and change the name to reflect a week earlier, or change the logic to not use the date names.

To get your starting file, you will need to create your folder to store the reports and run the command below in PowerShell with a machine that has the AD module loaded as part of the RSAT tools. You will also need the ScheduledTasks module loaded to create the scheduled tasks via PowerShell.

$outputLocation         = "C:\scripts\logs\GroupChanges"
$domain                 = "DomainOfGroup"
$groupName              = "GroupToMonitor"
$date                   = Get-Date
$dateReport             = ($date).ToString("MMddyyyy")
$outputFileName         = "$dateReport-group-members.csv"


$getCurrentGroupMembership = (Get-ADGroup -Server $domain $groupName | Get-ADGroupMember -Recursive | Select-Object -Unique | Sort | Select-Object SamAccountName)

$getCurrentGroupMembership | Export-CSV -Path $outputLocation\$outputFileName -Append -NoTypeInformation

Second verse, somewhat similar to the first.

# Script to do a weekly compare of Active Directory group memberships. Requires AD module to be loaded and an account / service account with read permissions to the objects.

$outputLocation         = "C:\scripts\logs\GroupChanges"
$domain                 = "DomainOfGroup"
$groupName              = "GroupToMonitor"
$date                   = Get-Date
$dateLastWeek           = ($date).AddDays(-7).ToString("MMddyyyy")
$dateReport             = ($date).ToString("MMddyyyy")
$outputFileName         = "$dateReport-group-members.csv"
$importFileNameLastWeek = "$dateLastWeek-group-members.csv"
$deltaFileName          = "$dateReport-delta.csv"
$report                 = @()

$getCurrentGroupMembership = (Get-ADGroup -Server $domain $groupName | Get-ADGroupMember -Recursive | Select-Object -Unique | Sort | Select-Object SamAccountName)

$getCurrentGroupMembership | Export-CSV -Path $outputLocation\$outputFileName -Append -NoTypeInformation

$inputFileNameLastWeek     = Import-Csv -Path "$outputLocation\$importFileNameLastWeek"

$objectCompare     = @{

  ReferenceObject  = ($getCurrentGroupMembership)
  DifferenceObject = ($inputFileNameLastWeek)

}

$deltaNames = (Compare-Object @objectCompare).InputObject

if($deltaNames -ne $null){

  $deltaNames | Export-Csv -Path $outputLocation\$deltaFileName -Append -NoTypeInformation
  $numberNewUsers = "New Users: " + ($deltaNames).Count

  $report += $deltaNames
  $report += $numberNewUsers
}

if($deltaNames -eq $null){

  Exit

}


$style = "<style>BODY{font-family: Arial; font-size: 10pt;}"
$style = $style + "TABLE{border: 1px solid black; border-collapse: collapse;}"
$style = $style + "TH{border: 1px solid black; background: #dddddd; padding: 5px; }"
$style = $style + "TD{border: 1px solid black; padding: 5px; }"
$style = $style + "</style>"
$body  = $report | ConvertTo-Html -Head $style

$dateEmail        = Get-Date -Format "MM-dd-yyyy"
$emailFrom        = "EmailFrom@company.com"
$emailTo          = "Someone@company.com"
$subject          = "Weekly Group Check | $dateEmail" 
$email            = New-object System.Net.Mail.MailMessage 
$email.to.Add($emailTo)
$email.From       = New-Object system.net.Mail.MailAddress $emailFrom
$email.Subject    = $subject
$email.IsBodyHtml = $true
$email.body       = $body
$attachment       = "$outputLocation\$deltaFileName"
$email.Attachments.Add($attachment)

$smtpserver       = "mail.company.com" 
$smtp             = new-object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($email)


And after you save that file, you will need to create the scheduled task. Make sure this is a machine that will be on and available during the time you want to run the script. I’m using “weeklychanges.ps1” as the example saved file name, running at 10am on Saturdays. Below will need to be ran from an elevated prompt / ISE in order to create the task without getting an “Access denied” error.

$taskName    = 'WeeklyGroupCheck'
$time        = "10am"
$user        = "domain\user"
$credentials = Get-Credential -Credential $user
$password    = $credentials.GetNetworkCredential().Password
$scriptPath  = "c:\scripts\weeklycheck.ps1"
$trigger     = New-ScheduledTaskTrigger -Weekly -At $time -DaysOfWeek Saturday
$action      = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-ExecutionPolicy Bypass -noprofile -file $scriptPath" 

Register-ScheduledTask -TaskName $taskName -Trigger $trigger -User $user -Password $password -Action $action -RunLevel Highest -Force