OU Management with PowerShell

I’ve got a few questions on Active Directory Organizational Unit management with PowerShell so I thought I would post a few examples on OU-related operations (using Active Directory cmdlets – note that for some of those like browsing OUs using AD provider is a viable alternative).

The first thing obstacle that you meet when deciding to start working with OUs is that at the moment (in version 1.0.1) specific cmdlets for OUs have not made it into the snapin yet. Which of course won’t stop us – as there are the wonderful *-QADObject cmdlets that help us survive while waiting for all type-specific cmdlets to become available.

So here we go:

Get the list of OUs:

PS C:> Get-QADObject -Type OrganizationalUnit  

Name               Type               DN  
----               ----               --  
Domain Controllers organizationalUnit OU=Domain Controllers,DC=ps64,DC=local  
Microsoft Excha... organizationalUnit OU=Microsoft Exchange Security Groups,DC=ps64,DC=local

Create New OU in domain root:

PS C:\> New-QADObject -Type organizationalUnit -Name TestOU -ParentContainer ps64.local/

Name               Type               DN  
----               ----               --  
TestOU             organizationalUnit OU=TestOU,DC=ps64,DC=local

Create 5 test users in the new OU:

PS C:> 1..5 | ForEach { New-QADUser -ParentContainer ps64.local/TestOU -Name ("TestUser" + $_)}

Name               Type               DN  
----               ----               --  
TestUser1          user               CN=TestUser1,OU=TestOU,DC=ps64,DC=local  
TestUser2          user               CN=TestUser2,OU=TestOU,DC=ps64,DC=local  
TestUser3          user               CN=TestUser3,OU=TestOU,DC=ps64,DC=local  
TestUser4          user               CN=TestUser4,OU=TestOU,DC=ps64,DC=local  
TestUser5          user               CN=TestUser5,OU=TestOU,DC=ps64,DC=local

Get a list of users in an OU (and all nested OUs):

PS C:\> Get-QADUser -SearchRoot ps64.local/TestOU

Name               Type               DN  
----               ----               --  
TestUser1          user               CN=TestUser1,OU=TestOU,DC=ps64,DC=local  
TestUser2          user               CN=TestUser2,OU=TestOU,DC=ps64,DC=local  
TestUser3          user               CN=TestUser3,OU=TestOU,DC=ps64,DC=local  
TestUser4          user               CN=TestUser4,OU=TestOU,DC=ps64,DC=local  
TestUser5          user               CN=TestUser5,OU=TestOU,DC=ps64,DC=local

Get only users placed directly in the OU (and not in sub-OUs):

PS C:\> Get-QADUser -SearchRoot ps64.local/TestOU -SearchScope OneLevel

Name               Type               DN  
----               ----               --  
TestUser1          user               CN=TestUser1,OU=TestOU,DC=ps64,DC=local  
TestUser2          user               CN=TestUser2,OU=TestOU,DC=ps64,DC=local  
TestUser3          user               CN=TestUser3,OU=TestOU,DC=ps64,DC=local  
TestUser4          user               CN=TestUser4,OU=TestOU,DC=ps64,DC=local  
TestUser5          user               CN=TestUser5,OU=TestOU,DC=ps64,DC=local

Modify all users from an OU:

PS C:\> Get-QADUser -SearchRoot ps64.local/TestOU | Set-QADUser -City TestCity

PS C:> Get-QADUser -SearchRoot ps64.local/TestOU | Format-Table Name, City

Name                                                City  
----                                                ----  
TestUser1                                           TestCity  
TestUser2                                           TestCity  
TestUser3                                           TestCity  
TestUser4                                           TestCity  
TestUser5                                           TestCity

Get statistics on the number of objects in each OU:

PS C:\> Get-QADObject -Type organizationalUnit | foreach { Write-Host $_.Name: (Get-QADObject -SearchRoot $_.DN).Count}

Domain Controllers : 5
Microsoft Exchange Security Groups : 6
TestOU : 6

Get the list of AD objects by OU:

PS C:\> Get-QADObject -Type organizationalUnit | foreach { Write-Host ([char]10) $_.Name ([char]10); Get-QADObject -SearchRoot $_.DN }

Domain Controllers  

Name               Type               DN  
----               ----               --  
Domain Controllers organizationalUnit OU=Domain Controllers,DC=ps64,DC=local  
SPB9880            computer           CN=SPB9880,OU=Domain Controllers,DC=ps64,DC=local  
RID Set            rIDSet             CN=RID Set,CN=SPB9880,OU=Domain Controllers,DC=ps64,DC=local  
NTFRS Subscript... nTFRSSubscriptions CN=NTFRS Subscriptions,CN=SPB9880,OU=Domain Controllers,DC=ps64,DC=local  
Domain System V... nTFRSSubscriber    CN=Domain System Volume (SYSVOL share),CN=NTFRS Subscriptions,CN=SPB9880,OU=Do...  

Microsoft Exchange Security Groups  

Microsoft Excha... organizationalUnit OU=Microsoft Exchange Security Groups,DC=ps64,DC=local  
Exchange Servers   group              CN=Exchange Servers,OU=Microsoft Exchange Security Groups,DC=ps64,DC=local  
Exchange Organi... group              CN=Exchange Organization Administrators,OU=Microsoft Exchange Security Groups,...  
Exchange Recipi... group              CN=Exchange Recipient Administrators,OU=Microsoft Exchange Security Groups,DC=...  
Exchange View-O... group              CN=Exchange View-Only Administrators,OU=Microsoft Exchange Security Groups,DC=...  
ExchangeLegacyI... group              CN=ExchangeLegacyInterop,OU=Microsoft Exchange Security Groups,DC=ps64,DC=local  

TestOU  

TestOU             organizationalUnit OU=TestOU,DC=ps64,DC=local  
TestUser1          user               CN=TestUser1,OU=TestOU,DC=ps64,DC=local  
TestUser2          user               CN=TestUser2,OU=TestOU,DC=ps64,DC=local  
TestUser3          user               CN=TestUser3,OU=TestOU,DC=ps64,DC=local  
TestUser4          user               CN=TestUser4,OU=TestOU,DC=ps64,DC=local  
TestUser5          user               CN=TestUser5,OU=TestOU,DC=ps64,DC=local

Notes:

  • For CSV-based OU/user provisioning just add import-csv as I described in earlier posts.
  • All the user operations are applicable to other types as well -just use *-QADGroup, *-QADComputer, etc. instead of *-QADUser.
  • The last statistics examples can be also made specific for users, groups, etc. by just changing the Get-QADObject cmdlet to a more specific one.

Tags: , , , ,

Advertisement

25 Responses to “OU Management with PowerShell”


  1. 1 Ambers June 13, 2007 at 5:14 am

    How would you go about grouping the output? For example I would like to be able to do the following:

    Root: Total Objects
    OU: Total Objects
    SubOU: Total Objects
    SubOU: Total Objects
    OU: Totat Objects

    ..etc.

    Thanks.

  2. 2 dmitrysotnikov June 13, 2007 at 2:57 pm

    Here’s the oneliner which worked for me (using AD cmdlets 1.0.3):

    PS:\> Get-QADObject | Group-Object ParentContainer -NoElement

    If you want the name to be first (and not cut by PowerShell) use format -table in the end:

    PS:\> Get-QADObject | Group-Object ParentContainer -NoElement | Format-Table Name, Count -AutoSize

    I hope that helps!

  3. 3 Anders May 9, 2008 at 11:54 am

    Hi.
    I’m writing a PS script to automate the creation of Mailboxes in Exchange 2007 on server 2008.
    I have installed the Quest cmdlets to be able to modify the AD.
    What i need is a script to check if an OU exists, and if not, create an OU based on data from a csv-file.
    I have tried, but havnt quite got it right.
    This is what I have so far:

    ## Import data from csv and store it in variable ‘data’

    $data = import-csv $args[0]

    $ou = get-qadobject -type organizationalunit

    if ( -not $ou = $data.Domain)
    {Some code to create a new OU based on the Domain from the CSV}
    else
    {Go on with the rest of the script}

    Am I on the right track?

    Regards
    Anders

  4. 4 dmitrysotnikov May 12, 2008 at 3:25 pm

    Anders,

    I believe Shay has already answered your question in this thread: http://powergui.org/thread.jspa?messageID=19543

    Dmitry

  5. 5 Marius April 24, 2009 at 9:11 am

    How would you go about finding empty OUs with no child object in a one liner using the available commandlet get-qadobject?

  6. 6 Dmitry Sotnikov April 24, 2009 at 9:58 am

    Try this:

    $emptyOUs = Get-QADObject -Type organizationalUnit | where {(Get-QADObject -SearchRoot $_.DN -SizeLimit 2).Count -eq 1}

    Note that this will display a ton of warnings (for all OUs with more than 1 child, because I explicitly tell it to only extract 2 – the OU itself and 1 more – which gives me a much better performance).

    However, once the execution is done – $emptyOUs has them all.

    Dmitry

  7. 7 James April 29, 2010 at 6:27 pm

    Hello, great site.

    How do I change a users OU? By viewing the properties of a user I see that the OU info is contained in ParentContainer and ParentContainerDN, but I don’t see a command to modify it.

    James

  8. 9 ksar January 7, 2011 at 10:07 am

    Hi, cool topic, very helpfull !

    Do you how can you exclude an OU when you list all users in an OU and subs ? (Get-QADUser -SearchRoot ps64.local/TestOU) ?

    John

    • 10 Dmitry Sotnikov May 6, 2011 at 8:33 pm

      John,

      I can think of a couple of ways you could do this:

      A. List multiple OUs in your query:

      Get-QADUser -SearchRoot ps64.local/TestOU/SubA, ps64.local/TestOU/SubC, ps64.local/TestOU/SubD

      B. Use -LDAPFilter to do the exclusion – post a question on our PowerShell and AD forum http://powergui.org/forum.jspa?forumID=173 if you need help with LDAP syntax.

      Dmitry

  9. 11 Dellinja May 6, 2011 at 11:27 am

    Q: is it possible to do the following with powershell –

    1. List all OU’s and filter a OU by it’s description (let’s say “Desc = Foreign”) and parse it into a variable?
    2. Use this variable to create a user and off user groups?

    Thanks in advance guys.

    • 12 Dmitry Sotnikov May 6, 2011 at 8:38 pm

      Dellinja,

      Yes, this is absolutely possible. 🙂

      This would list the OUs by description (use wildcards if you do not need exact match):

      Get-QADObject -Type organizationalUnit -Description ‘Foreign’

      Yes, you can assign the results to variable:

      $OUs = Get-QADObject -Type organizationalUnit -Description ‘Foreign’

      And yes, you can then use the value to supply the parent container paraneter to New-QADUser or New-QADGroup.

      You can find syntax and examples at: http://wiki.powergui.org/index.php/QAD_cmdlets_reference

      Post your questions to our PowerShell and AD forum http://powergui.org/forum.jspa?forumID=173 if you need further assistance.

      Dmitry

  10. 13 Michael June 24, 2011 at 9:39 am

    Hi There,
    I would like to output the OU of a user into a CSV as a single column. So, the column OU must display the users OU, that they’re in. How do I go about adding it into this Script:

    $Today = Get-Date
    $Past = $Today.AddDays(30)
    Get-QADUser -SearchRoot ‘OU=blah,DC=test,DC=com’ -IncludeAllProperties | Where-Object { $_.lastlogontimestamp -lt $Past -and $_.distinguishedname -notlike “*ou=blah,DC=ou,DC=acme,DC=com” } | sort SN | select CN, lastlogon, DN | Export-Csv C:\OldUsers.csv -notype

  11. 14 Pablo von Arx July 18, 2011 at 11:16 am

    Q: I want to add 4 Groups to an OU. But the OU where the groups have to been generated does still not exist. How can i do a dynamic generat group under a new OU that will be generated before?. Or can i look for recent created OU’s and then add the groups?

    • 15 Dmitry Sotnikov July 18, 2011 at 6:42 pm

      Pablo,

      Not sure what you want to do. Do you need to create an OU or does someone else create that for you? Can you be more specific in who does what and then? Just put entire sequence step by step.

      Also, AD and PowerShell forum here: http://powergui.org/forum.jspa?forumID=173 – might be a better place for the discussion than the blog comments. Please post all the details there and we will try to help.

      Dmitry

  12. 16 Curt Chapman October 20, 2011 at 12:14 am

    Great info. Here’s one…

    I want to pipe the results of your script that gets the members of an OU (computers specifically) to perform other functions (like reporting on disk space on the system drives for example). When I run the below to output to a TXT file…

    Get-QADComputer -ComputerRole DomainController | Format-Table -Property name -HideTableHeaders | out-file “d:\scripts\diskspace\DomainControllers.txt”

    the TXT file is unreadable by powershell because there are lots of eroneous spaces in the file and is therefore unusable by subsequent scripts.

    is there a way to output the names of the computers only to a clean TXT file that can be called by another script? … or is there a way to pipe the names retrieved in to another script? Your help is greatly appreciated

    • 17 Dmitry Sotnikov October 20, 2011 at 11:30 am

      Curt,

      Format-Table variable is intended to be used for screen output only – if you want to export to file use Select-Object instead. E.g.:

      Get-QADComputer -ComputerRole DomainController | Select-Object -ExpandProperty name | out-file “d:\scripts\diskspace\DomainControllers.txt”

      Dmitry

    • 18 hicannet November 24, 2011 at 2:10 pm

      Hi Curt,

      do it like this to create a ‘clean’ list (without white-spaces and such):

      $output = “D:\scripts\diskspace\DomainControllers.txt”
      $var = Get-QADComputer -ComputerRole DomainController | Select-Object Name | Sort Name | ft -HideTableHeaders
      $var | Out-File $output
      (Get-Content $output) | Where {$_ -ne “”} | Out-File $output

      Hope that helps, it gave me a headache as well 😉

  13. 19 Hicham September 20, 2012 at 2:32 pm

    Hi guys,
    I try to add a new user to AD, on an test server
    My script likes so:
    $credential = Get-Credential -Credential Administrator
    connect-QADService -service ‘xxx.xxx.xxx.xxx’-Credential $credential
    New-QADUser -name ‘Jan Peter’ -FirstName ‘Jan’ -LastName ‘Peter’ -DisplayName ‘Peter Jan’ -Description ‘Medewerker binnendienst’ -samAccountName ‘JanPeter’ -Office ‘Binnendienst’ -Initials ‘J.P.’ -UserPassword ‘p@55w0rd’ -HomePhone ‘(0229) 547 000’ -WebPage ‘http://www.mywebsite.nl’ -StreetAddress ‘Straatnaam 1’ -PostOfficeBox ‘123456’ -City ‘Stad’ -PostalCode ‘1234 AA’ -MobilePhone ‘(06) 12345678’ -Fax ‘(000) 12345678’ -Title ‘Functie omschrijving’ -Department ‘Afdeling’ -Company ‘Companyname group’ -ParentContainer ‘CN=Users,DC=Testing,DC=local’

    I get the error:
    new-qaduser : a device attached to the system is not functioning.
    what am I doing wrong?

    Thanks for help.

  14. 20 Sandy November 9, 2012 at 12:55 pm

    Super info…

    I need to export users list and with they respective Group’s and OU’s from multiple groups (800 odd groups) under a sub OU. Please let me know how could we do this…

  15. 22 js3rd December 15, 2014 at 11:26 am

    Hello there, I’m super new to PowerShell and at this point, I have very basic needs to use it.

    I would like to create multiple OUs with description under the root of AD. The named would be read from a TXT or CSV files, I’m not sure which is better.
    I looked everywhere and I found a lot of fancy scripts but they don’t deliver.

    I used a simple script that creates the OUs but I could not add the description

    I would also like to know how to create multiple GROUPS, USERS and COMPUTERS using the same method.

    Could someone help me with that please?

    Thank you,


  1. 1 Extend AD cmdlets' reach « Dmitry’s PowerBlog Trackback on May 30, 2007 at 9:50 pm
  2. 2 Quick Reference to AD cmdlets 1.0.4 « Dmitry’s PowerBlog: PowerShell and beyond Trackback on August 30, 2007 at 10:13 am
  3. 3 Favorite Blog for Powershell stuff | Live@EDU Pearls Trackback on April 22, 2011 at 3:12 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s




My Recent Tweets

Legal

The posts on this blog are provided “as is” with no warranties and confer no rights. The opinions expressed on this site are mine and mine alone, and do not necessarily represent those of my employer - WSO2 or anyone else for that matter. All trademarks acknowledged.

© 2007-2014 Dmitry Sotnikov

May 2007
M T W T F S S
 123456
78910111213
14151617181920
21222324252627
28293031  

%d bloggers like this: