Most Useful PowerShell Cmdlets for Managing and Securing Active Directory

powershell hero img

In this article, I show you how to manage and secure Active Directory using PowerShell. I’ll look at the most useful PowerShell cmdlets and give examples of how to use them.

Create New Active Directory Users

The New-ADUser cmdlet is for creating new AD users. You can optionally specify where to create new users with the -Path parameter. In the example below, the new user will be created in the Accounts Organizational Unit (OU). The -Server parameter is also optional. It is used to determine on which domain controller (DC) the new user will be created. Note that you cannot specify a password in plaintext in the -AccountPassword parameter. You must convert it to a secure string using the ConvertTo-SecureString cmdlet.

New-ADUser -DisplayName:"Russell Smith" -GivenName:"Russell" -Name:"Russell Smith" -Path:"OU=Accounts,DC=ad,DC=contoso,DC=com" -SamAccountName:"russellsmith" -Server:"" -Surname:"Smith" -Type:"user" -AccountPassword (ConvertTo-SecureString Pas$W0rd!!11 -AsPlainText -Force) -Enabled $true

Create Active Directory Groups

Adding groups to AD is easy with the New-ADGroup cmdlet. -Server and -Path parameters are both optional.

New-ADGroup -GroupCategory:"Security" -GroupScope:"Global" -Name:"Netwrix" -Path:"OU=Accounts,DC=ad,DC=contoso,DC=com" -SamAccountName:"Netwrix" -Server:""

Add Users to Groups

Once you have some users and groups in your domain, you can add users to groups with the Add-ADGroupMember cmdlet.

Add-ADGroupMember -Identity Netwrix -Members russellsmith,bob.trent

Create New Organizational Units

Use the New-ADOrganizationalUnit cmdlet to create new Organizational Units (OU) in AD. Note that the -ProtectedFromAccidentalDeletion flag is optional. When set to $true, you can’t delete the OU without first changing the status of the flag to $false.

New-ADOrganizationalUnit -Name:"Sensitive" -Path:"OU=Accounts,DC=ad,DC=contoso,DC=com" -ProtectedFromAccidentalDeletion:$true -Server:""

Deleting Active Directory Objects

The ‘Remove’ verb is used in AD cmdlets to delete objects. Remove-ADUser and Remove-ADGroup are used respectively to delete users and groups.

Remove-ADUser -Identity russellsmith
Remove-ADGroup -Identity Netwrix

Before you can delete an OU, you need to set the accidental deletion flag to false using Set-ADObject.

Set-ADObject -Identity:"OU=Sensitive,OU=Accounts,DC=ad,DC=contoso,DC=com" -ProtectedFromAccidentalDeletion:$false -Server:""

Remove-ADOrganizationalUnit -Identity "OU=Sensitive,OU=Accounts,DC=ad,DC=contoso,DC=com"

Import Users from a CSV File

PowerShell makes it easy to automate tasks. In the script below, I use a comma-delimited (CSV) text file to create two users with the Import-Csv and New-ADUser cmdlets. The only trickery involved is splitting the first field of each entry in the text file so that I can separate the first and surnames for the -GiveName and -Surname parameters of the New-ADUser cmdlet.

Import-Csv -Path c:\temp\users.csv | ForEach-Object {

    $givenName = $[0]

    $surname = $[1]

    New-ADUser -Name $ -Enabled $true –GivenName $givenName –Surname $surname -Accountpassword (ConvertTo-SecureString $_.password -AsPlainText -Force) -ChangePasswordAtLogon $true -SamAccountName $_.samaccountname –UserPrincipalName ($_.samaccountname+””) -City $ -Department $_.department


The first line of the text file contains the field names. You can add as many users as you want.

Russell Smith,smithrussell,PassW0rd!!11,London,IT
David Jones,jonesdavid,4SHH$$#AAAHh,New York,Accounts

Move AD Objects

The Move-ADObject cmdlet is for moving AD objects. In the example below, I move a user account from the Accounts OU to the Users container.

Move-ADObject -Identity "CN=Russell Smith,OU=Accounts,DC=ad,DC=contoso,DC=com" -TargetPath "CN=Users,DC=ad,DC=contoso,DC=com"

Link a Group Policy Object

While PowerShell can’t be used to create Group Policy Objects (GPO), it can be used to perform other tasks related to Group Policy. The New-GPLink cmdlet is used to link existing GPOs to OUs. In the example below, I link a GPO called Firewall Settings to the Accounts OU.

New-GPLink -Name "Firewall Settings" -Target "OU=Accounts,DC=ad,DC=contoso,DC=com" -LinkEnabled Yes -Enforced Yes

Active Directory Reporting

The Get-ADObject cmdlet can be used to filter the directory and display information about objects. In the example below, I use a filter to find the Accounts OU and then pipe the results to the Get-GPInheritence cmdlet. Select-Object is then used to extract information about the GPOs linked to the OU.

Get-ADObject -Filter {name -like "Accounts*"} | Get-GPInheritance | Select-Object -Expand gpolinks | ForEach-Object {Get-GPO -Guid $_.gpoid}

One of the most useful cmdlets for AD admins is the Search-ADAccount cmdlet. In the example below, I search the domain for locked out user accounts and automatically unlock them using Unlock-ADAccount.

Search-ADAccount –LockedOut | Unlock-ADAccount

Get-ADObject can be used with complex filters. Here I list all objects created after the specified date ($Date).

$Date = [Datetime]"02/07/2019"
Get-ADObject -Filter 'WhenCreated -GT $Date'

Filters can get quite complex. In the next command, I list all deleted objects where the change attribute is later than the specified date, and that can be restored, excluding the Deleted Objects container.

Get-ADObject -Filter 'whenChanged -gt $Date -and isDeleted -eq $True -and name -ne "Deleted Objects"' -IncludeDeletedObjects

Finally, I use Get-EventLog to search the event logs on each DC for login event ID 4624. Note the use of Get-ADDomainController to return all the DCs in the domain. Once I’ve retrieved the necessary information, I use Write-Host to write the output to the terminal window, with information separated by tabs to make it easier to read.

$DCs = Get-ADDomainController -Filter *
$startDate = (get-date).AddDays(-1)
foreach ($DC in $DCs){
$slogonevents = Get-Eventlog -LogName Security -ComputerName $DC.Hostname -after $startDate | Where-Object {$_.eventID -eq 4624 }}
 foreach ($e in $slogonevents){

 if (($e.EventID -eq 4624 ) -and ($e.ReplacementStrings[8] -eq 2)){
 write-host "Type: Local Logon`tDate: "$e.TimeGenerated "`tStatus: Success`tUser: "$e.ReplacementStrings[5] "`tWorkstation: "$e.ReplacementStrings[11]

 if (($e.EventID -eq 4624 ) -and ($e.ReplacementStrings[8] -eq 10)){
 write-host "Type: Remote Logon`tDate: "$e.TimeGenerated "`tStatus: Success`tUser: "$e.ReplacementStrings[5] "`tWorkstation: "$e.ReplacementStrings[11] "`tIP Address: "$e.ReplacementStrings[18]

Related Article: