If you need to create a n OU in the Active Directory that is new (or it does not exist) then this script can help you, it is driven off a file called "ou.txt"
This file needs to be formatted correctly as below, here is an example of that file:
No Dash = Root OU
If we use the file contents above we will get the structure as shown below based on the dashes, this has been generated by the script with the preview option:
# Import the Active Directory module
Import-Module ActiveDirectory
# Setup logging
$logFile = "OU_Creation_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
# Function to write to both console and log file
function Write-Log {
param(
[string]$Message,
[string]$Color = "White"
)
# Get current timestamp
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
# Write to console with color
Write-Host $Message -ForegroundColor $Color
# Write to log file (without color formatting)
"$timestamp - $Message" | Out-File -FilePath $logFile -Append
}
# Function to count leading dashes in a line
function Get-DashLevel {
param([string]$line)
if ($line -match '^(-*)') {
return $matches[1].Length
}
return 0
}
# Function to clean OU name (remove dashes and trim)
function Get-CleanOUName {
param([string]$line)
return $line -replace '^-+', '' -replace '\s+$', '' -replace '^\s+', ''
}
# Function to preview OU structure
function Show-OUPreview {
param([string[]]$content)
Write-Log "`nPreviewing OU Structure:`n" "Cyan"
foreach ($line in $content) {
if ([string]::IsNullOrWhiteSpace($line)) { continue }
$level = Get-DashLevel $line
$ouName = Get-CleanOUName $line
# Create indentation based on level
$indent = " " * $level
Write-Log "$indent$ouName"
if ($level -eq 0) {
Write-Log "$indent└─── (Root Level)" "Yellow"
} elseif ($level -eq 1) {
Write-Log "$indent└─── (Sub OU)" "Green"
} else {
Write-Log "$indent└─── (Nested Sub OU)" "Magenta"
}
}
}
# Function to create OUs
function Create-OUStructure {
param([string[]]$content)
Write-Log "Starting OU creation process..." "Cyan"
# Stack to keep track of parent OUs
$ouStack = @()
$currentLevel = -1
foreach ($line in $content) {
if ([string]::IsNullOrWhiteSpace($line)) { continue }
$level = Get-DashLevel $line
$ouName = Get-CleanOUName $line
# Adjust the stack based on the current level
while ($currentLevel -ge $level) {
$ouStack.RemoveAt($ouStack.Count - 1)
$currentLevel--
}
# Create the OU path
$ouPath = ""
if ($level -eq 0) {
# Root level OU
$ouPath = "DC=bear,DC=local"
} else {
# Build the OU path from the stack
$ouPath = ($ouStack | ForEach-Object { "OU=$_" }) -join ','
$ouPath += ",DC=bear,DC=local"
}
try {
# Check if OU already exists
$existingOU = Get-ADOrganizationalUnit -Filter "Name -eq '$ouName'" -SearchBase $ouPath -ErrorAction SilentlyContinue
if (-not $existingOU) {
Write-Log "Creating OU: $ouName in $ouPath" "Green"
New-ADOrganizationalUnit -Name $ouName -Path $ouPath -ProtectedFromAccidentalDeletion $true
} else {
Write-Log "OU already exists: $ouName in $ouPath" "Yellow"
}
# Update the stack
$ouStack += $ouName
$currentLevel = $level
} catch {
Write-Log "Error creating OU '$ouName': $_" "Red"
}
}
Write-Log "`nOU creation complete!" "Cyan"
}
# Main menu function
function Show-Menu {
Clear-Host
Write-Log "=== OU Creation Tool ===" "Cyan"
Write-Log "Current log file: $logFile" "Gray"
Write-Log ""
Write-Log "1: Preview OU Structure" "Yellow"
Write-Log "2: Create OUs" "Green"
Write-Log "3: View Log File" "Purple"
Write-Log "4: Exit" "Red"
Write-Log ""
Write-Host "Please make a selection (1-4): " -NoNewline
}
# Main script execution
$ouFile = "ou.txt"
# Check if ou.txt exists
if (-not (Test-Path $ouFile)) {
Write-Log "Error: ou.txt file not found!" "Red"
Write-Log "Please create an ou.txt file in the same directory as this script." "Yellow"
exit
}
# Initialize log file with header
"=== OU Creation Tool Log ===" | Out-File -FilePath $logFile
"Script started at: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" | Out-File -FilePath $logFile -Append
"" | Out-File -FilePath $logFile -Append
# Read the content once
$content = Get-Content $ouFile
# Menu loop
do {
Show-Menu
$selection = Read-Host
switch ($selection) {
'1' {
Show-OUPreview $content
Write-Log "`nPress any key to continue..."
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
}
'2' {
Write-Log "`nPreparing to create OUs..." "Yellow"
Write-Log "Are you sure you want to proceed? (Y/N): " -NoNewline
$confirm = Read-Host
if ($confirm -eq 'Y' -or $confirm -eq 'y') {
Create-OUStructure $content
} else {
Write-Log "`nOU creation cancelled." "Yellow"
}
Write-Log "`nPress any key to continue..."
$null = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyDown')
}
'3' {
Write-Log "`nOpening log file..."
notepad.exe $logFile
}
'4' {
Write-Log "`nExiting..." "Yellow"
Write-Log "Script ended at: $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')" "Gray"
exit
}
default {
Write-Log "`nInvalid selection. Please try again." "Red"
Start-Sleep -Seconds 2
}
}
} while ($true)