Click here to monitor SSC
  • Av rating:
  • Total votes: 7
  • Total comments: 0
Joseph Moody

Managing Active Directory with PowerShell

11 November 2013

For the busy administrator of a windows domain, any regular task or housekeeping process should be automated, and the Cmdlets that are now provided with Active Directory have improved to the point that there is no serious contender to PowerShell for the task. Joseph Moody shows how to do it, with examples.

Any system administration task in that is regularly repeated should be automated! With the management of Active Directory (AD), that is a surprisingly high number of tasks. With PowerShell’s ability to easily work with AD, these tasks can made easier or completely automated!

So what is a candidate for automation? In short, any task that you regularly do within Active Directory Users and Computer (ADUC) or Active Directory Administrative Center (ADAC) should be automated! There is plenty of this type of task. For any domain administrator, the day seems somehow incomplete if you haven’t reset or unlocked a user’s account. You’d probably also created new users or new computers. As well as these routine tasks, there are the more monotonous ‘housekeeping’ tasks that tend to get delegated to the interns. Those tasks include removing accounts that are no longer needed, the bulk modification of an attribute, and renaming groups of computers in reorganization. All of these tasks can be made easier and quicker!

In this article, I’ll cover an automated PowerShell solution to each of these problems. These scripts are written to stand alone and so contain any configuration that is necessary. The first two scripts work best when embedded within your Active Directory Users and Computers console. This will allow you to use the scripts as a natural tool and will encourage automation! The last three scripts work best when linked to a scheduled task or run when needed.

Two Ways to Manage Active Directory

PowerShell syntax is relatively straightforward. Each command is comprised of a Verb and Noun (ex: Get-Command). The commands to manage Active Directory are no different. Confusion might arise when looking at scripts to manage Active Directory though. In some, you might see commands like: Get-ADComputer or Set-ADObject. In other scripts, you might see: Get-QADComputer or Set-QADObject. Why do these commands differ? Because, there are two methods of Active Directory management with PowerShell

Commands such as Get-QADComputer belong to the Quest AD PowerShell cmdlets. This module contains eighty-one PowerShell cmdlets and every command contains QAD within the name. When PowerShell was first released way back in 2006, a native Active Directory PowerShell module didn’t exist. Whilst it was possible to work with Active Directory, it was very clumsy! Because of this, Quest released their free AD cmdlets. These cmdlets are still widely used today because of their history and simplicity.

To use the Quest cmdlets, you must install the module one time on your management machine. Like any nonstandard PowerShell module, you also have to import the cmdlets into your PowerShell console before use. This is done through the command Add-PSSnapin Quest.ActiveRoles.ADManagement.

Commands such as Get-ADComputer belong to the built-in Active Directory PowerShell module. This module, released with Windows Server 2008R2+, initially contained seventy six cmdlets for managing Active Directory. With the release of Windows Server 2012 R2, that number now reaches 147. To use the Active Directory module, your domain controllers should be running Windows Server 2008 R2 or above. Active Directory Web Services (ADWS) provides the communications framework for the Active Directory PowerShell module.

In most cases, the AD and Quest commands are named identically. For example, Get-ADComputer and Get-QADComputer both query computers in Active Directory. For the duration of this article, we will be using the native Active Directory module. If you are unable to use this module in your environment, leave a comment and I will try to get you a similar script written with Quest’s cmdlets.

Resetting Passwords and Unlocking Accounts

Let’s start with a universal problem: resetting user passwords and unlocking accounts. Our first task is to define our search. We can use Read-Host to prompt for input. We can then store that input (such as a first name) in the $User variable.

$User=Read-Host "Search for a User by: First, Last, or UserName"

When a user can’t login, you probably (and painstakingly) try to gather some relevant information. Information such as:

  • The Username – I am amazed at how many users provide me their email address instead.
  • Password Age – Did the user change their password yesterday and then forgot that they changed it?
  • Lockout Status – Is their account locked out as well?

In a perfect world, it would be great to know if their password has expired and if so, whether the expiration is giving the user trouble. With PowerShell, we can make this perfect world possible through this command:

Get-ADUser -Filter "Name -like '*$User*'" -Properties
Name,SamAccountName,PasswordLastSet,PasswordExpired,AccountLockoutTime | Select-Object
Name,SamAccountName,PasswordLastSet,PasswordExpired,AccountLockoutTime

So far, we have queried for our user and gathered any relevant information that would allow us to quickly diagnose the problem. Finally, we need a way to reset the user’s password and to unlock their account. This can be done with the Set-ADAccountPassword and Unlock-ADAccount commands.

But what we will reset the user’s password to? Some organizations might use a default password such as P@ssw0rd or Change123. This can be done like:

Set-ADAccountPassword $User -NewPassword (ConvertTo-SecureString -AsPlainText “P@ssw0rd” -Force) –Reset

As an alternative, you can reset the user’s password to something that only they would likely know. Though not perfectly secure, this reset is balanced against the time frame it takes for the user to change their password. Examples include a mobile number, a birthday, or an address. Because this information can be stored in that user’s Active Directory account, we can easily modify our password reset command to retrieve these values:

Set-ADAccountPassword $User -NewPassword (ConvertTo-SecureString -AsPlainText $User.MobilePhone -Force) –Reset

The command above retrieves the MobilePhone attribute for the user and uses that value as the password.

Here is what our complete script looks like:

Import-Module ActiveDirectory

$User=Read-Host "Search for a User by: First, Last, or UserName"
Get-ADUser -Filter "Name -like '*$User*'" -Properties 
Name,SamAccountName,PasswordLastSet,PasswordExpired,AccountLockoutTime | Select-Object 
Name,SamAccountName,PasswordLastSet,PasswordExpired,AccountLockoutTime

$User = Read-Host "Enter the SamAccountName to Reset the Password"
$User = Get-ADUser -Filter "Name -like '*$User*'" -Properties *

Set-ADAccountPassword $User -NewPassword (ConvertTo-SecureString -AsPlainText $User.MobilePhone -Force) -Reset
Unlock-ADAccount $User 

Write-Host "Password set to " -nonewline; write-host $User.MobilePhone -backgroundcolor Yellow -ForegroundColor Black

In just a few lines of code, we are able to really streamline the account reset/unlock procedure!

Creating Computer/User Accounts

From a technical standpoint, computer and user account creation are nearly identical. From a data standpoint, the methods can vary. Computer accounts can be created without any outside information. User accounts require information like a name, department, etc.

When creating a new computer account with PowerShell, we are going to use the command New-ADComputer. The only information that is required is the computer name, the SamAccountName (Computername$), and the OU location. Here is an example:

New-ADComputer -Name TestPC -SamAccountName TestPC -Path "OU=Domain Computers,DC=Test,DC=Local"

It makes the process much smoother when creating a new user account by having the data stored in a CSV file. For this script, we are going to assume that our HR department outputs a CSV file that contains our user’s first name, last name, and an employee ID (which will be used as their username).

At the beginning of the script, we will need to define our CSV location. We will also specify our domain name.

Import-Module ActiveDirectory
$Domain='@TEST.local'
$Userslist=import-csv “C:\Users\Public\Users.csv”

Next, we will establish a Foreach loop and build a few attributes (such as a FullName and a HomeDirectory) for our new users:

ForEach ($User in $Userslist)

{
   $User.FirstName
   $User.LastName
   $User.ID
   
   $FullName=$User.FirstName+" "+$User.LastName
   $UPN=$User.ID+$Domain
   $UNC='\\SERVER\DATASHARE\'
   $HomeDirectory=$UNC+$User.ID

With just three pieces of data, we made some pretty cool combinations! Let’s wrap up this script by using New-ADUser, Set-ADUser, and Enable-ADAccount. We will also add our new user to a domain Security Group. In its complete form, our script looks like:

$Domain='@TEST.local'
$Userslist=import-csv “C:\Users\Public\Users.csv”

ForEach ($User in $Userslist)

{
   $User.FirstName
   $User.LastName
   $User.ID
   
   $FullName=$User.FirstName+" "+$User.LastName
   $UPN=$User.ID+$Domain
   $UNC='\\SERVER\DATASHARE\'
   $HomeDirectory=$UNC+$User.ID
   
   New-ADUser -name $FullName -GivenName $User.FirstName -Surname $User.LastName -SamAccountName $User.ID -DisplayName $FullName -UserPrincipalName $UPN -AccountPassword (ConvertTo-SecureString -AsPlainText "P@ssw0rd" -force) -Path 'OU=Domain Users,DC=TEST,DC=local' -HomeDirectory $HomeDirectory -HomeDrive 'U:'
   
   Set-ADUser -Identity $User.ID -PasswordNeverExpires $True
   Enable-ADAccount -Identity $User.Id
   Add-ADGroupMember -Identity Faculty -Members $User.ID
   
   }

Cleaning up Stale Accounts

Every AD object has a life cycle. They are created, maintained, modified, and ultimately deleted. When an account is no longer used, it should be decommissioned and deleted. Unused AD objects such as computers and users are a security concern in your domain environment. Luckily for you, PowerShell makes it easy to clean up these ‘stale’ accounts. For our example, we will be working with stale computer objects. First, we need a way of finding stale computers.

$Days = (Get-Date).Adddays(-180)

$Computers = Get-ADComputer -Filter {LastLogonTimeStamp -lt $Days} -Properties LastLogonTimeStamp

The picture below shows us a sample set of stale computer objects:

In our environment, we have four stale computers which are stored in the variable $Computers. Instead of taking the easy route and deleting the accounts, let’s decommission them properly. We will need to timestamp these computer accounts first. By using a blank attribute, like Location, we can store a date value with the computer. This command will do that:

$Computers | Set-ADComputer -Location (Get-Date)

Next, we will disable the computer account and move the account to a Stale Computers OU:

$Computers | Disable-ADAccount

$Computers | Move-ADObject -TargetPath'OU=Computers_Stale,DC=TEST,DC=local'

Our script, so far, retires stale computer objects and time stamps them with the current date. The computer objects are then disabled and moved to a dedicated OU. But we still need a way of cleaning up the Computers_Stale OU. We can do that with these final commands:

$Computers = Get-ADComputer –Filter “Name –like ‘*’”–SearchBase "OU=Computers_Stale,DC=TEST,DC=Local" | Where-Object {$_.Location -GT (Get-Date).AddMonths(-7) -and $_.Location -LT (Get-Date).AddMonths(-6)}

$Computers | Remove-ADObject 

These commands search the Computer_Stale OU for any machine with a location attribute older than 7 months and younger than 6 months from the current date. Remember from above that computer accounts are not moved into this OU until they’ve been unused for 6 months. By waiting at least 6 months to remove the object, our domain will never have a stale computer account older than a year.

Bulk Attribute Changes

For any AD administrator, the day will come when a massive change will need to be made against all users or computers. Knowing how to do this in PowerShell will make that day much smoother. Any major change follows the same procedure: filtering to the objects that need to be change, testing the change, and rolling it out.

As an example, we are going to change every user’s home directory from one server to a second server. To filter our users, we can use the Get-ADUser cmdlet to find users that have “Server1” as their home directory server.

$Users = Get-ADUser -Filter "HomeDirectory -like '\\SERVER1\*'"

From here, we can use a foreach loop to cycle through each user. By using the Set-ADUser cmdlet, we can customize the homedirectory attribute for our new server.

$Users = Get-ADUser -Filter "HomeDirectory -like '\\SERVER1\*'" 

foreach ($User in $Users){

$HomeDirectory = "\\Server2\Share2\" + $User.SamAccountName
Set-ADUser -Identity $User -HomeDirectory $HomeDirectory
}

To test our script, we can add the -WhatIf parameter to the end of our Set-ADUser command. After we run our script as a test, we can confirm our $HomeDirectory variable by using write-host.

If everything looks ok, we can remove the –WhatIf parameter and roll out our changes. Not bad for such a simple script!

Renaming Computers on a Massive Scale

This last example tackles the labor intensive task of renaming computers. When companies merge or buildings change, computers will need to be renamed. For this task, we will use Get-ADComputer to generate a list of computers to rename. The actual work of the script will be done with the Rename-Computer cmdlet.

Our first step is to select the computers that need to be renamed and to export that data to a CSV. We can use the Get-ADComputer cmdlet for this task. In the example below, we select every machine beginning with ADM, grab only the name, and export that data to .\Computers.csv

Get-ADComputer -Filter "Name -like 'ADM*'" | Select-Object Name | Export-Csv .\Computers.csv –NoTypeInformation

Next, we need to associate our old name with a new name. Edit the CSV and create a new column named NewName. Below NewName, fill in the new computer names. Excel’s autofill makes this very easy. Your end result should look like this:

Once we have our data, we can finally start renaming computers. In the script below, we will store our CSV in the $>Computers variable and start a Foreach loop. We will use the Rename-Computer cmdlet and connect to each computer under the Name column.

$Computers = import-csv .\Computers.csv

foreach ($Computer in $Computers){
Rename-Computer -NewName $Computer.NewName -ComputerName $Computer.Name
if ($? -eq $True){
(get-content .\Computers.csv) | Where-Object {$_ -notmatch $computer.name} | set-content .\Computers.csv

If we successfully rename the computer, we use the Set-Content cmdlet to remove that line from our CSV. We know that a computer was successfully renamed through the if($? –eq $True)statement. In PowerShell, $? stores the success of the previous command.

You can automate this entire task by taking the script above and putting inside of a scheduled task. By scheduling this task, computers can be renamed before or after work hours!

Time Consuming Tasks – Made Faster and Easier with PowerShell

When PowerShell is used for Active Directory management, an administrator can automate the most repetitive tasks and schedule the housekeeping work like account cleanup and object reorganization. If you do any of these items by hand, then use the scripts above and make your life just a little bit easier! If you have other tasks that you think should be automated, leave a comment below.

Joseph Moody

Author profile:

Joseph is a desktop administrator for a public school system, helping manage 5,500 computers. He specializes in Active Directory, Group Policy, deployment and software management. His blog can be found at DeployHappiness.com.

Search for other articles by Joseph Moody

Rate this article:   Avg rating: from a total of 7 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.
 

Top Rated

Migrating to Microsoft BPOS - Part II
 In his last article, Johan gave us a crystal clear guide to preparing to migrate from an on-premises... Read more...

Emulating the Exchange 2003 RUS for Out-of-Band Mailbox Provisioning in Exchange 2007
 Exchange's Recipient Update Service was important in Exchange 2000 or 2003 in order to complete the... Read more...

The Postmasters
 The Exchange Team introduces themselves, and keeps you up-to-date Read more...

For this Exchange Server Archiver, “Transparency” Fits
 Sometimes, it is a great relief when a user of your software gives it a tough test and then reports... Read more...

Hunting in Packs, Seamless-ness and Happy Holidays
 I attended DevConnections (Exchange) last month and was blown away by the technical talks. Speakers... Read more...

Most Viewed

Upgrade Exchange 2003 to Exchange 2010
  In this article, the first of two in which Jaap describes how to move from Exchange Server 2003... Read more...

Upgrade Exchange 2003 to Exchange 2010 - Part II
 In Jaap's second article on upgrading straight from Exchange Server 2003 to 2010, he explains how to... Read more...

Goodbye Exchange ExMerge, Hello Export-Mailbox
 ExMerge was a great way of exporting a mailbox to an Exchange PST file, or for removing all occurences... Read more...

Exchange E-mail Addresses and the Outlook Address Cache
 Because Exchange auto-complete cache uses X.500 addresses for e-mail sent to addresses within the... Read more...

Using Exchange 2007 for Resource Booking
 The process of booking various resources to go with a meeting room just got a whole lot easier with... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.