1

I'm running a query to pull data from AD. I have a 2 line script to get the data. The first line takes 4 or 5 minutes to complete. It returns around 200,000 users. The second line takes about 20 hours to complete.

$allEnabled = Get-adUser -f { (userAccountControl  -eq 512) -and (Enabled -eq $true) }   -properties employeeID, emailaddress, GivenName, SurName 
$allEnabled | ft employeeID, emailaddress, GivenName, SurName | out-file d:\temp\output.txt

I've tried writing the output one line at a time, and I've tried stuffing it in an array but I can't find a way to write the data any quicker. I've run it from a beefy server with ample resources so CPU and memory are not constrained.

3
  • Firstly, every time you use | (pipe), you are slowing yourself down but that's probably not the real reason for slowness. When PowerShell cmdlets lets you down, your best bet is to use .NET methods directly. Commented Nov 11, 2015 at 22:34
  • 1
    @AdilHindistan You are using the pipe whether you explicitly type it out or not. The pipe can streamline many actions. Commented Nov 11, 2015 at 22:45
  • 1
    @Matt Not true, but this is not a good place to argue the point either. Pipeline has its uses but should in general be avoided when you have RAM and need speed. Commented Nov 11, 2015 at 22:49

3 Answers 3

3

Not sure of the gains here but you can make some simple changes... Namely avoiding saving the results in a variable and not using the Format- cmdlets for output (that is not to console!). In the case of the latter I think it needs to enumerate the entire object so it know how to display it on console.

Since you are using object you would be better off taking advantage of that and using Export-CSV for output.

Get-adUser -f { (userAccountControl  -eq 512) -and (Enabled -eq $true) }   -properties employeeID, emailaddress, GivenName, SurName | 
    Select employeeID, emailaddress, GivenName, SurName | 
    Export-CSV -NoTypeInformation d:\temp\output.txt

This should effectively be writing one object at a time to file. Format-Table I think was the biggest issue here.

Sign up to request clarification or add additional context in comments.

1 Comment

Using this method the entire process completed in under 3 minutes. Much more efficient that what I was doing.
1

Firstly, every time you use | (pipe), you are slowing yourself down but that's probably not the real reason for slowness. When PowerShell cmdlets lets you down, your best bet is to use .NET methods directly. You could for example try StreamWriter:

$sw = [System.IO.StreamWriter] "d:\temp\output.txt"
$allEnabled = Get-adUser -f { (userAccountControl  -eq 512) -and (Enabled -eq $true) }   -properties employeeID, emailaddress, GivenName, SurName
$allEnabled | % { $sw.WriteLine("$($_.employeeID), $($_.emailaddress), $($_.GivenName), $($_.SurName)") }
$sw.close()

3 Comments

With 1000 users this one seems a bit faster than the 2 other answers. I'm tempted to add 50k fake accounts and re-run ^_^
Using this method the entire process completed in under 3 minutes. Much more efficient that what I was doing.
@dft277 Streamwriter will beat most native cmdlets (if not all) hands down.
0

Format-Table will not do any form of result formatting. It is only used for console outputs. You want to pipe out data directly to file in your case.

Also I suggest you to use LDAP filter instead. For my system it works slighty faster than -Filter parameter.

Get-ADUser -LDAPFilter "(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(userAccountControl=512))" -properties employeeID, emailaddress, GivenName, SurName | Export-Csv -Path c:\adusers.csv -NoTypeInformation

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.