Link to home
Start Free TrialLog in
Avatar of K B
K BFlag for United States of America

asked on

How to make PowerShell script more efficient?

Any thoughts on how I could make this script more robust and efficient?

# This script produces an output of each ADUser's status of "Allow Inheritable Permissions to Propagate to this Object" (Or in 2012+ "Enable Inheritance")
# The output also includes the value, if any, for each ADUser's attribute "AdminCount".
# Open File in Excel, remove all rows of ADUsers that should not have their attributes modified. Re-Save.
Get-ADUser -Properties admincount,distinguishedname,canonicalname,nTSecurityDescriptor,proxyAddresses -Filter * |
  Sort canonicalname |
  ? {$_.proxyaddresses -notmatch '($null|SystemMailbox|FederatedEmail|HealthMailbox|migration|SearchMailbox|DiscoverySearch|Administrator|MSExchApproval|MsExchDiscovery)'} |
  % {
    $dn  = $_.distinguishedname
    $sd  = $_.nTSecurityDescriptor.AreAccessRulesProtected
    $can = $_.canonicalname -split '/'
    $OU  = $can[0..($can.Count – 2)] -join '/'
    $admincount = $_.admincount
    New-Object -TypeName PSCustomObject -Property @{
      InheritenceNeedsToBeEnabled=$sd
      dn=$dn
      OU = $OU
      AdminCount = $admincount
    }
  } | Export-Csv -Path c:\scripts\IsInheritanceEnabled.csv -NoTypeInformation -Encoding ASCII 

Open in new window

Avatar of Qlemo
Qlemo
Flag of Germany image

I do not see any issue. There is always space for improvement, or for doing it different, but no need to.
Avatar of K B

ASKER

I want to make sure it runs efficiently when there are over 100,000 AD Users. Is there anything you can think of?  Qlemo your opinion matters! :-)
Ouch. With that much objects you certainly should remove the sort. It requires to collect all user objects before being able to start processing. Without, any found object will be passed thru the pipeline immediately, processed and replaced by the new object. Or saying it different: with sort you need to keep up to 100000 AD user objects plus a few in memory, versus a few (~ 3) without.

And if you would need the sort, which you do not here, it should be placed after any filter like the where-object, so the sort is applied to less objects.
I agree with Qlemo. Sorting objects before filtering them - waste of time.
I'd place sort object at the last line of your script just before "| Export-CSV"

Another moment is about filtering of proxyaddress. Im not able to test it here, but what i see from the code is:
1. By Get-ADUser you would get all your 100000 records
2. If you remove sort from 5th line - that would save your time.
3. After you wait for getting all your 100000 records, you are starting filtering them one by one for ProxyAddress.
The question is: Why not to use Filter for proxyaddress inside Get-ADUser?
With this method - you would get already filtered out values as a result.

But in order to understand the timings and compare them - use measure-command for both methods and compare timings :)
ASKER CERTIFIED SOLUTION
Avatar of oBdA
oBdA

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I don't think Select-Object versus New-Object makes a significant difference, but the LDAP filter does for sure. It is always best to filter at the very first cmdlet ;-).
Avatar of K B

ASKER

Brilliant!