# encoding: ascii
# api: powershell
# title: Compare-AD
# description: A set of functions (and sample code using them) to create
# version: 0.1
# type: function
# author: Dmitry Sotnikov
# license: CC0
# function: New-Snapshot
# x-poshcode-id: 638
# x-archived: 2016-11-12T21:15:51
# x-published: 2008-10-14T21:10:00
#
# snapshots of user accounts in the current Active Directory domain
# save them in an xml file, and then compare live AD environment
# against that XML
# (C) Dmitry Sotnikov
# http://dmitrysotnikov.wordpress.com/2008/10/14/compare-ad-against-snapshotscompare-ad-against-snapshots
#
###############################################################################
# Compare-AD - a set of functions (and sample code using them) to create
# snapshots of user accounts in the current Active Directory domain
# save them in an xml file, and then compare live AD environment
# against that XML
#
# (C) Dmitry Sotnikov
# http://dmitrysotnikov.wordpress.com/2008/10/14/compare-ad-against-snapshotscompare-ad-against-snapshots
#
###############################################################################
# Requires QAD cmdlets
if ((Get-PSSnapin "Quest.ActiveRoles.ADManagement" `
-ErrorAction SilentlyContinue) -eq $null) {
Add-PSSnapin "Quest.ActiveRoles.ADManagement"
}
###############################################################################
# Functions
###############################################################################
# Retrives all AD users from the current domain and stores the selected
# set of properties (passed as an array of strings in the $properties parameter)
# as an xml file by the path passed as $path
# See sample use below
function New-Snapshot {
param($path, $properties)
Get-QADUser -SizeLimit 0 -DontUseDefaultIncludedProperties `
-IncludedProperties $properties |
Select $properties | Export-Clixml $path
}
# Load the snapshot and compare it against current AD domain
function Compare-ActiveDirectory {
param($path, $properties)
# $old is the snapshot, $new is the current environment data
$old = Import-Clixml $path
$new = Get-QADUser -SizeLimit 0 -DontUseDefaultIncludedProperties `
-IncludedProperties $properties |
Select $properties
# First lets report the ones which got created or deleted
$diff = Compare-Object $old $new -Property Name
$created = , ($diff | where { $_.SideIndicator -eq "=>" })
$deleted = , ($diff | where { $_.SideIndicator -eq "<=" })
if ( $created.Count -gt 0 ) {
"New accounts:"
$created | Format-Table Name
}
if ( $deleted.Count -gt 0 ) {
"Deleted accounts:"
$deleted | Format-Table Name
}
# Now let's load the accounts in a hash-table so it is easier to locate them
$hash = @{}
$new | ForEach-Object { $hash[$_.DistinguishedName] = $_ }
# Let's enumerate the accounts and their properties and report any changes
"Modified objects:"
foreach ( $snapshot in $old ) {
$current = $hash[$snapshot.DistinguishedName]
if ( $current -and
($current.ModificationDate -ne $snapshot.ModificationDate )) {
@"
Object $($snapshot.distinguishedname)
Modified at $($current.ModificationDate)
Property`tOld Value`tNew Value
========`t=========`t=========
"@
foreach ($property in $properties) {
if ( ($property -ne "ModificationDate") -and
($snapshot.$property -ne $current.$property )) {
"$property`t$($snapshot.$property)`t$($current.$property)"
}
}
}
}
}
###############################################################################
# Common parameters
###############################################################################
# These are the properties to be compared
# Make sure they include Name, DistinguishedName, and ModificationDate
# Remove the TS attributes if your system requirements for retrieving those
# are not met:
# http://dmitrysotnikov.wordpress.com/2008/07/23/system-requirements-for-powershell-terminal-services-management/
$Members_to_Compare = @( "Name", "DistinguishedName", "ModificationDate",
"AccountIsDisabled", "AccountIsLockedOut", "AccountName",
"CanonicalName", "City", "Company", "Department", "Description",
"DisplayName", "Email", "Fax",
"FirstName", "HomeDirectory", "HomeDrive", "HomePhone", "Initials",
"LastName", "LdapDisplayName", "LogonName", "LogonScript", "Manager",
"MobilePhone", "Notes", "Office", "Pager",
"ParentContainerDN", "PasswordNeverExpires",
"PhoneNumber", "PostalCode", "PostOfficeBox", "ProfilePath",
"SamAccountName", "StateOrProvince", "StreetAddress", "Title",
"TsAllowLogon", "TsBrokenConnectionAction", "TsConnectClientDrives",
"TsConnectPrinterDrives", "TsDefaultToMainPrinter", "TsHomeDirectory",
"TsHomeDrive", "TsInitialProgram", "TsMaxConnectionTime",
"TsMaxDisconnectionTime", "TsMaxIdleTime", "TsProfilePath",
"TsReconnectionAction", "TsRemoteControl", "TsWorkDirectory",
"UserPrincipalName", "WebPage" )
# Path to the snapshot file
$SnapshotPath = "c:\snapshot.xml"
###############################################################################
# Sample usage
###############################################################################
# Create a snapshot
New-Snapshot -Path $SnapshotPath -Properties $Members_to_Compare
# Make some changes
New-QADUser -Name "Lawrence Alford" -ParentContainer mydomain.local/test
Set-QADUser "Jennifer Clarke" -PhoneNumber "(249) 111-22-33"
Set-QADUser "Ernest Cantrell" -City "San Francisco"
Remove-QADObject "Andreas Bold" -Force
# Let's see if we find them
Compare-ActiveDirectory -Path $SnapshotPath -Properties $Members_to_Compare