# CountValues.ps1 # PowerShell V2 script to count the total number of values in all non-linked # multi-valued attributes of an object in Active Directory. # # Copyright (c) 2015 Richard L. Mueller # Credit: Parts of this script are based on ideas in the script # Find-BloatedObjects.ps1 by Tony Murray (dated Sept. 18, 2014). # http://www.open-a-socket.com/index.php/2014/09/19/multivalued-attribute-limits-in-active-directory/ # # ---------------------------------------------------------------------- # You have a royalty-free right to use, modify, reproduce, and # distribute this script file in any way you find useful, provided that # you agree that the copyright owner above has no warranty, obligations, # or liability for such use. # Note: This script considers attributes that are not replicated to all domain # controllers, like the dSCorePropagationData, repsFrom, repsTo, and subRefs attributes. # Such attributes can have different numbers of values on each DC. It is not known if # such attributes affect the limit on the total number of values for all non-linked # multi-valued attributes of any object in Active Directory. # Version 1.0 - August 13, 2015 # Check for parameter identifying the object. # If the parameter has embedded "$" or "`" characters, either have the script prompt for # the value, or enclose the parameter in single quote characters on the command line. If ($Args.Count -eq 1) { $ADObjectName = $Args[0] } Else { $ADObjectName = Read-Host "Enter object sAMAccountName or distinguishedName" } Import-Module ActiveDirectory # Only consider multi-valued attributes. $Collection = "Microsoft.ActiveDirectory.Management.ADPropertyValueCollection*" # Check the schema for non-linked attributes. $SchemaNC = (Get-ADRootDSE).SchemaNamingContext # Retrieve the values of all default and extended properties exposed # by Get-ADObject, plus all AD attributes that have values. The Get-ADObject # cmdlet is used because it supports all classes of objects and exposes fewer # default and extended properties than other cmdlets. Also, the ones it does # expose are not multi-valued. This prevents attributes being included twice, # once by PowerShell property name, and a second time by lDAPDisplayName. $ADObject = $Null If ($ADObjectName -Like "*,*") { # $ADObjectName is the distinguished name of an object. $ADObject = Get-ADObject -Identity $ADObjectName -Properties * } Else { # $ADObjectName is the sAMAccountName of an object. $ADObject = Get-ADObject -LDAPFilter "(sAMAccountName=$ADObjectName)" -Properties * } If ($ADObject -eq $Null) { "Object $ADObjectName not found" Break } # Retrieve lDAPDisplayNames of multi-valued attributes that have values or # correspond to default or extended properties exposed by Get-ADObject. $Props = $ADObject | Get-Member -MemberType Property ` | Where {$_.Definition -Like $Collection} | Select -ExpandProperty Name $NTName = $ADObject.sAMAccountName If ($NTName -eq $Null) { $ADObject.distinguishedName } Else { $ADObject.distinguishedName + " (" + $ADObject.sAMAccountName + ")" } "Non-linked multi-valued attributes with values:" "-----" $Total = 0 ForEach ($Prop In $Props) { # Check if the attribute is linked. $Linked = (Get-ADObject -SearchBase $SchemaNC ` -LDAPFilter "(&(objectClass=attributeSchema)(lDAPDisplayName=$Prop))" ` -Properties linkID).linkID # Only consider non-linked attributes (no linkID) that have # at least one value. If (($Linked -eq $Null) -And (($ADObject.$Prop).Count -gt 0)) { # Display the attribute lDAPDisplayName and the number of values. $Prop + " (" + ($ADObject.$Prop).Count + ")" # Sum the number of values of all non-linked multi-valued attributes # for this object. $Total = $Total + ($ADObject.$Prop).Count } } "Total number of values: $Total"