10 PowerShell Automation Scripts & Best Practices for DevOps
PowerShell automation scripts examples are most useful when they solve real operational problems: onboarding users, cleaning stale records, monitoring disk space, restarting services safely, and managing virtual infrastructure without repetitive console work.
PowerShell remains one of the most practical automation tools for DevOps and sysadmin teams working in Microsoft-heavy environments. It is built for administration, has a deep module ecosystem, and passes structured objects through the pipeline instead of forcing you to parse text for every task.
[IMAGE: Code snippet showing PowerShell automation scripts examples]
This guide gives you five must-have script patterns and five best practices to make those scripts safer, reusable, and easier for a team to maintain.
Why PowerShell is Essential for Modern DevOps
Modern DevOps is not limited to application deployment. Infrastructure teams automate identity, patching, monitoring, security checks, reporting, cloud resources, and incident response. In Windows and Microsoft environments, PowerShell is often the shortest path from manual administration to repeatable automation.
PowerShell is essential because it can work directly with:
- Active Directory
- Windows Server
- Microsoft 365
- Azure
- IIS
- Windows services
- Event logs
- Scheduled tasks
- Hyper-V and virtualization tooling
- REST APIs
It also supports advanced functions, modules, error handling, remoting, and structured output. That makes it suitable for both one-off admin tasks and larger automation frameworks.
If you are deciding whether PowerShell should be your default tool, start by exploring PowerShell vs Python automation. If your team supports multiple operating systems, you will also need a strategy for cross-platform infrastructure automation scripting.
5 Must-Have PowerShell Automation Scripts Examples
The examples below are written as production-oriented patterns, not copy-paste magic. Adapt module names, paths, permissions, and validation to your environment. For any command that changes infrastructure, test in a non-production environment first.
1. Automated Active Directory User Provisioning
User provisioning is a high-volume operational task that benefits from automation, especially when HR or ticketing systems provide structured input.
A practical provisioning script should:
- Accept parameters instead of hard-coded values.
- Validate required fields.
- Check whether the user already exists.
- Create the account only when needed.
- Add group memberships idempotently.
- Log every change.
Example pattern:
function New-NoraAdUser {
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory)] [string] $SamAccountName,
[Parameter(Mandatory)] [string] $GivenName,
[Parameter(Mandatory)] [string] $Surname,
[Parameter(Mandatory)] [string] $UserPrincipalName,
[Parameter(Mandatory)] [string] $Path,
[string[]] $Groups = @()
)
$existingUser = Get-ADUser -Filter "SamAccountName -eq '$SamAccountName'" -ErrorAction SilentlyContinue
if (-not $existingUser) {
if ($PSCmdlet.ShouldProcess($SamAccountName, "Create AD user")) {
New-ADUser `
-SamAccountName $SamAccountName `
-GivenName $GivenName `
-Surname $Surname `
-UserPrincipalName $UserPrincipalName `
-Path $Path `
-Enabled $true
}
}
foreach ($group in $Groups) {
$isMember = Get-ADGroupMember -Identity $group -Recursive |
Where-Object { $_.SamAccountName -eq $SamAccountName }
if (-not $isMember) {
if ($PSCmdlet.ShouldProcess($SamAccountName, "Add to $group")) {
Add-ADGroupMember -Identity $group -Members $SamAccountName
}
}
}
}
This pattern uses an advanced function, supports -WhatIf, and avoids blindly creating duplicate accounts or group assignments.
2. Stale DNS Record Cleanup
Stale DNS records create troubleshooting noise and can point users or systems to retired resources. DNS cleanup automation should be conservative: report first, delete only after review or with explicit approval.
Example reporting pattern:
function Get-StaleDnsRecordCandidate {
[CmdletBinding()]
param(
[Parameter(Mandatory)] [string] $ZoneName,
[int] $OlderThanDays = 90
)
$cutoff = (Get-Date).AddDays(-$OlderThanDays)
Get-DnsServerResourceRecord -ZoneName $ZoneName |
Where-Object {
$_.Timestamp -and $_.Timestamp -lt $cutoff
} |
Select-Object HostName, RecordType, Timestamp, RecordData
}
A safer workflow is:
- Generate a stale-record report.
- Review exceptions.
- Export approved records to a file.
- Run deletion from the approved list.
- Keep an audit log.
Destructive automation should have friction by design.
3. Disk Space Monitoring and Alerting
Disk space checks are a classic automation win. The script should return structured output so it can feed monitoring, email, chat alerts, or a pipeline.
Example:
function Get-LowDiskSpace {
[CmdletBinding()]
param(
[string[]] $ComputerName = $env:COMPUTERNAME,
[int] $ThresholdPercentFree = 15
)
foreach ($computer in $ComputerName) {
Get-CimInstance -ClassName Win32_LogicalDisk -ComputerName $computer -Filter "DriveType=3" |
ForEach-Object {
$percentFree = [math]::Round(($_.FreeSpace / $_.Size) * 100, 2)
if ($percentFree -lt $ThresholdPercentFree) {
[pscustomobject]@{
ComputerName = $computer
Drive = $_.DeviceID
PercentFree = $percentFree
FreeGB = [math]::Round($_.FreeSpace / 1GB, 2)
SizeGB = [math]::Round($_.Size / 1GB, 2)
}
}
}
}
}
Because it returns objects, the output can be exported to CSV, converted to JSON, or sent to another tool.
4. IIS App Pool Recycling
IIS app pool recycling is often done manually during deployments or incident response. Automating it reduces mistakes, but the script should validate the target and log the action.
Example:
function Restart-NoraAppPool {
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory)] [string] $Name
)
Import-Module WebAdministration
$appPoolPath = "IIS:\AppPools\$Name"
if (-not (Test-Path $appPoolPath)) {
throw "App pool not found: $Name"
}
if ($PSCmdlet.ShouldProcess($Name, "Recycle IIS app pool")) {
Restart-WebAppPool -Name $Name
Get-WebAppPoolState -Name $Name
}
}
Use this pattern inside deployment pipelines with approvals or environment-specific gates.
5. Bulk VM Snapshot Management
Virtual machine snapshots are useful during maintenance but risky when forgotten. A PowerShell automation pattern can report old snapshots and optionally remove approved ones.
Because virtualization platforms differ, treat the following as a general pattern:
function Get-OldSnapshotCandidate {
[CmdletBinding()]
param(
[Parameter(Mandatory)] [object[]] $Snapshots,
[int] $OlderThanDays = 7
)
$cutoff = (Get-Date).AddDays(-$OlderThanDays)
$Snapshots |
Where-Object { $_.Created -lt $cutoff } |
Select-Object VMName, Name, Created, Description
}
The safe workflow is the important part:
- Report old snapshots.
- Exclude protected workloads.
- Require approval for deletion.
- Remove only explicitly approved snapshots.
- Log what was removed and by which run.
Core PowerShell Automation Best Practices
Good PowerShell automation is not just about getting the command right. It is about making scripts predictable under failure, reusable by other engineers, and safe to run repeatedly.
[IMAGE: Diagram illustrating PowerShell scripting best practices for DevOps]
Use Advanced Functions (CmdletBinding)
Advanced functions make your scripts behave more like native cmdlets. CmdletBinding() gives you support for common parameters and enables patterns like -Verbose, -WhatIf, and -Confirm.
Example:
function Invoke-NoraMaintenance {
[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Mandatory)] [string] $ComputerName
)
if ($PSCmdlet.ShouldProcess($ComputerName, "Run maintenance")) {
Write-Verbose "Running maintenance on $ComputerName"
}
}
Use advanced functions when a script will be reused, shared, scheduled, or run in a pipeline.
Implement Try/Catch/Finally Logic
PowerShell error handling requires attention because not every error is terminating by default. Use -ErrorAction Stop when you need exceptions to flow into catch.
Example:
try {
$service = Get-Service -Name "Spooler" -ErrorAction Stop
Restart-Service -Name $service.Name -ErrorAction Stop
}
catch {
Write-Error "Failed to restart service: $($_.Exception.Message)"
exit 1
}
finally {
Write-Verbose "Service maintenance attempt complete"
}
For scheduled automation, failures should be visible through logs, monitoring, or pipeline status.
Comment-Based Help
Comment-based help makes scripts easier to use and maintain. It is especially important when scripts become team tools.
Example:
function Get-NoraServerHealth {
<#+
.SYNOPSIS
Returns basic health information for one or more servers.
.PARAMETER ComputerName
The target computer names to check.
.EXAMPLE
Get-NoraServerHealth -ComputerName server01,server02
#>
[CmdletBinding()]
param([string[]] $ComputerName)
}
Include synopsis, parameters, examples, and notes about required modules or permissions.
Scaling PowerShell Scripting for DevOps Teams
PowerShell scales when you treat it like production code.
Use these team standards:
- Store scripts in Git.
- Require code review for infrastructure-changing scripts.
- Use modules for shared functions.
- Create a standard logging pattern.
- Use
-WhatIffor destructive operations. - Add comment-based help.
- Pin required module versions where practical.
- Avoid hard-coded credentials.
- Use secret management outside the repository.
- Standardize output as objects, JSON, or CSV.
- Run scripts from controlled automation runners.
- Document ownership and rollback steps.
If your team is comparing language standards, review our guide to the best language for automation in 2026. PowerShell may be the best choice for Microsoft-centered tasks, while Python may own cross-platform orchestration.
Conclusion
PowerShell scripting for DevOps is most valuable when it replaces repetitive, error-prone administration with safe, reviewable, and reusable automation.
Start with operational pain points: user provisioning, stale DNS reports, disk monitoring, IIS maintenance, and snapshot cleanup. Then apply the practices that make automation production-ready: advanced functions, try/catch/finally, comment-based help, structured output, source control, and clear ownership.
The result is not just a folder of scripts. It is an automation library your team can trust.
FAQ
What are the best practices for PowerShell automation?
Use advanced functions, parameter validation, try/catch/finally, structured output, comment-based help, source control, code review, and safe options such as -WhatIf for destructive actions.
What are good PowerShell automation scripts examples?
Good examples include Active Directory provisioning, stale DNS reporting, disk space monitoring, IIS app pool recycling, and VM snapshot cleanup.
Is PowerShell good for DevOps automation?
Yes. PowerShell is especially strong for Windows, Active Directory, Microsoft 365, Azure, IIS, and enterprise administration tasks.
How do you make PowerShell scripts reusable?
Use parameters, advanced functions, modules, comment-based help, consistent logging, and structured outputs instead of hard-coded values and one-off console commands.
Should PowerShell scripts be stored in Git?
Yes. Infrastructure automation should be version-controlled, reviewed, and documented like other production code.