- Introduction
- Chapter 1: PowerShell Fundamentals and Setup
- Chapter 2: Core Administrative Commands and Help System
- Chapter 3: File and Folder Management
- Chapter 4: User and Group Management
- Chapter 5: System Information and Monitoring
- Chapter 6: Network Administration and Troubleshooting
- Chapter 7: Security and Permissions Management
- Chapter 8: Scripting, Automation, and Advanced Administration
- Summary and Implementation Roadmap
Introduction

Windows PowerShell has revolutionized system administration, transforming how IT professionals manage Windows environments. Whether you’re a seasoned administrator looking to automate repetitive tasks or a newcomer seeking to master modern Windows management, PowerShell is your gateway to efficient, scalable system administration.
PowerShell isn’t just another command-line tool—it’s a powerful object-oriented shell and scripting language built on the .NET Framework. Unlike traditional command-line interfaces that work with text, PowerShell works with .NET objects, enabling rich data manipulation and seamless integration with Windows systems and services.
What makes PowerShell indispensable for administrators is its consistency and discoverability. Every PowerShell command (called a cmdlet) follows a Verb-Noun syntax that makes learning intuitive. Whether you’re managing files, users, services, or network settings, the same principles apply throughout the entire PowerShell ecosystem.
This comprehensive guide will take you from PowerShell basics to advanced administrative techniques. You’ll learn essential commands for daily administration, discover powerful scripting capabilities, and implement automation solutions that will transform your IT operations from reactive to proactive.
Chapter 1: PowerShell Fundamentals and Setup
Understanding PowerShell Versions and Editions
PowerShell Evolution:
- Windows PowerShell (1.0-5.1): Built on .NET Framework, Windows-only
- PowerShell Core (6.x-7.x): Built on .NET Core, cross-platform
- PowerShell 7+: Unified version combining Windows PowerShell and PowerShell Core features
Current Recommendations:
- PowerShell 7+: For new deployments and cross-platform environments
- Windows PowerShell 5.1: Still widely used in enterprise environments
- Compatibility: Most administrative scripts work across versions with minor adjustments
Installation and Initial Setup
Installing PowerShell 7+:
# Using Windows Package Manager
winget install Microsoft.PowerShell
# Using Chocolatey
choco install powershell
# Direct download from GitHub releases
# https://github.com/PowerShell/PowerShell/releases
Verifying Installation:
# Check PowerShell version
$PSVersionTable
# Check execution policy
Get-ExecutionPolicy
# Check available modules
Get-Module -ListAvailable
Execution Policies and Security
Understanding Execution Policies:
- Restricted: No scripts allowed (default on Windows clients)
- RemoteSigned: Local scripts run freely, downloaded scripts must be signed
- AllSigned: All scripts must be digitally signed
- Unrestricted: All scripts run (not recommended for production)
Setting Execution Policy:
# Set for current user (recommended for learning)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
# Set for entire machine (requires admin privileges)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine
# Check current policy
Get-ExecutionPolicy -List
PowerShell ISE vs. Visual Studio Code
PowerShell ISE (Integrated Scripting Environment):
- Built-in Windows tool
- Good for beginners and simple scripts
- Limited compared to modern editors
- Being phased out in favor of VS Code
Visual Studio Code with PowerShell Extension:
- Modern, feature-rich editor
- Excellent debugging capabilities
- Cross-platform compatibility
- Recommended for serious PowerShell development
Essential PowerShell Concepts
Cmdlets and Syntax: PowerShell commands follow a consistent Verb-Noun pattern:
# Examples of common verbs
Get-Process # Retrieve information
Set-Location # Modify settings
New-Item # Create objects
Remove-Item # Delete objects
Start-Service # Begin operations
Stop-Service # End operations
Objects vs. Text: Unlike traditional shells that return text, PowerShell returns .NET objects:
# This returns a process object, not text
$process = Get-Process notepad
# You can access object properties
$process.ProcessName
$process.WorkingSet
$process.StartTime
The Pipeline: PowerShell’s pipeline passes objects between commands:
# Get all services, filter running ones, select specific properties
Get-Service | Where-Object {$_.Status -eq 'Running'} | Select-Object Name, Status
This foundation prepares you for practical administrative commands, which we’ll explore in the next chapter.
Chapter 2: Core Administrative Commands and Help System
Getting Help and Discovery
The Help System: PowerShell’s help system is your most valuable tool for learning and troubleshooting:
# Update help files (run as administrator, one-time setup)
Update-Help
# Get help for any command
Get-Help Get-Process
Get-Help Get-Process -Examples
Get-Help Get-Process -Full
Get-Help Get-Process -Online
# Find commands by topic
Get-Help *service*
Get-Help *user*
Get-Help *file*
Command Discovery:
# Find all commands containing a keyword
Get-Command *service*
Get-Command *process*
Get-Command -Verb Get
Get-Command -Noun Service
# Get command syntax
Get-Command Get-Process -Syntax
# Show available parameters
(Get-Command Get-Process).Parameters
Essential Information Gathering Commands
System Information:
# Computer information
Get-ComputerInfo
Get-WmiObject Win32_ComputerSystem
Get-CimInstance Win32_OperatingSystem
# Hardware information
Get-WmiObject Win32_Processor
Get-WmiObject Win32_PhysicalMemory
Get-WmiObject Win32_LogicalDisk
# Network configuration
Get-NetAdapter
Get-NetIPConfiguration
Get-DnsClientServerAddress
Process and Service Management:
# Process management
Get-Process
Get-Process -Name notepad
Stop-Process -Name notepad
Start-Process notepad
# Service management
Get-Service
Get-Service -Name spooler
Start-Service -Name spooler
Stop-Service -Name spooler
Restart-Service -Name spooler
Set-Service -Name spooler -StartupType Automatic
User and Group Information
Local User Management:
# Local users (PowerShell 5.1+)
Get-LocalUser
Get-LocalUser -Name Administrator
New-LocalUser -Name "TestUser" -Password (ConvertTo-SecureString "P@ssw0rd" -AsPlainText -Force)
Set-LocalUser -Name "TestUser" -Description "Test Account"
Remove-LocalUser -Name "TestUser"
# Local groups
Get-LocalGroup
Get-LocalGroupMember -Group "Administrators"
Add-LocalGroupMember -Group "Administrators" -Member "TestUser"
Remove-LocalGroupMember -Group "Administrators" -Member "TestUser"
Active Directory Users (requires RSAT or domain controller):
# Import Active Directory module
Import-Module ActiveDirectory
# User management
Get-ADUser -Filter *
Get-ADUser -Identity "john.doe"
Get-ADUser -Filter {Name -like "*smith*"}
New-ADUser -Name "Jane Doe" -GivenName "Jane" -Surname "Doe" -SamAccountName "jane.doe"
Set-ADUser -Identity "jane.doe" -Department "IT"
Remove-ADUser -Identity "jane.doe"
Registry Management
Registry Operations:
# Navigate registry like a file system
Set-Location HKLM:\Software
Get-ChildItem
# Read registry values
Get-ItemProperty -Path "HKLM:\Software\Microsoft\Windows\CurrentVersion" -Name "ProgramFilesDir"
# Create registry entries
New-Item -Path "HKLM:\Software\MyCompany"
New-ItemProperty -Path "HKLM:\Software\MyCompany" -Name "Version" -Value "1.0" -PropertyType String
# Modify registry values
Set-ItemProperty -Path "HKLM:\Software\MyCompany" -Name "Version" -Value "2.0"
# Remove registry entries
Remove-ItemProperty -Path "HKLM:\Software\MyCompany" -Name "Version"
Remove-Item -Path "HKLM:\Software\MyCompany"
Real-World Application Example: A system administrator needs to audit all running services across multiple servers:
# Get all services and export to CSV for analysis
Get-Service |
Select-Object Name, Status, StartType, ServiceType |
Export-Csv -Path "C:\Reports\Services.csv" -NoTypeInformation
# Find all stopped services that should be running
Get-Service |
Where-Object {$_.Status -eq 'Stopped' -and $_.StartType -eq 'Automatic'} |
Select-Object Name, Status, StartType
Troubleshooting Scenario: When investigating system performance issues:
# Get top 10 processes by memory usage
Get-Process |
Sort-Object WorkingSet -Descending |
Select-Object -First 10 Name, WorkingSet, CPU
# Check disk space on all drives
Get-WmiObject Win32_LogicalDisk |
Select-Object DeviceID,
@{Name="Size(GB)";Expression={[math]::Round($_.Size/1GB,2)}},
@{Name="FreeSpace(GB)";Expression={[math]::Round($_.FreeSpace/1GB,2)}},
@{Name="PercentFree";Expression={[math]::Round(($_.FreeSpace/$_.Size)*100,2)}}
These core commands form the foundation for all PowerShell administration tasks. Next, we’ll explore file and folder management operations essential for system administration.
Chapter 3: File and Folder Management

Basic File Operations
Navigation and Exploration:
# Navigation
Set-Location "C:\Windows"
Get-Location
Push-Location "C:\Temp" # Save current location
Pop-Location # Return to saved location
# Directory listings
Get-ChildItem
Get-ChildItem -Force # Include hidden files
Get-ChildItem -Recurse # Include subdirectories
Get-ChildItem *.txt # Filter by extension
Get-ChildItem -Directory # Folders only
Get-ChildItem -File # Files only
File and Folder Creation:
# Create directories
New-Item -ItemType Directory -Path "C:\Scripts"
New-Item -ItemType Directory -Path "C:\Scripts\Backup" -Force
# Create files
New-Item -ItemType File -Path "C:\Scripts\test.txt"
New-Item -ItemType File -Path "C:\Scripts\script.ps1" -Value "# PowerShell Script"
# Create multiple items
1..5 | ForEach-Object { New-Item -ItemType File -Path "C:\Scripts\file$_.txt" }
Copying and Moving Operations:
# Copy files and folders
Copy-Item "C:\Scripts\test.txt" "C:\Backup\"
Copy-Item "C:\Scripts" "C:\Backup\Scripts" -Recurse
# Move files and folders
Move-Item "C:\Scripts\test.txt" "C:\Archive\"
Move-Item "C:\Scripts\OldFolder" "C:\Archive\"
# Rename items
Rename-Item "C:\Scripts\test.txt" "production.txt"
Advanced File Operations
File Content Management:
# Read file content
Get-Content "C:\Scripts\logfile.txt"
Get-Content "C:\Scripts\logfile.txt" -Tail 10 # Last 10 lines
Get-Content "C:\Scripts\logfile.txt" -Wait # Monitor file changes
# Write to files
"Hello World" | Out-File "C:\Scripts\hello.txt"
"Additional content" | Add-Content "C:\Scripts\hello.txt"
Set-Content "C:\Scripts\hello.txt" "Overwrite content"
# Work with CSV files
$data = Import-Csv "C:\Data\users.csv"
$data | Where-Object {$_.Department -eq "IT"} | Export-Csv "C:\Data\IT-users.csv"
File Searching and Filtering:
# Find files by various criteria
Get-ChildItem -Recurse -Filter "*.log"
Get-ChildItem -Recurse | Where-Object {$_.Length -gt 1MB}
Get-ChildItem -Recurse | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-30)}
# Search file content
Select-String -Path "C:\Logs\*.txt" -Pattern "ERROR"
Select-String -Path "C:\Scripts\*.ps1" -Pattern "function" -LineNumber
# Find and process files
Get-ChildItem -Recurse -Filter "*.tmp" | Remove-Item -Force
Get-ChildItem -Recurse | Where-Object {$_.LastWriteTime -lt (Get-Date).AddDays(-90)} | Remove-Item -Force
Permissions and Security
NTFS Permissions Management:
# Get current permissions
Get-Acl "C:\Scripts" | Format-List
(Get-Acl "C:\Scripts").Access
# Set permissions
$acl = Get-Acl "C:\Scripts"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("Domain\User","FullControl","Allow")
$acl.SetAccessRule($accessRule)
Set-Acl "C:\Scripts" $acl
# Remove permissions
$acl = Get-Acl "C:\Scripts"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule("Domain\User","FullControl","Allow")
$acl.RemoveAccessRule($accessRule)
Set-Acl "C:\Scripts" $acl
File Attributes and Properties:
# Check file attributes
Get-ItemProperty "C:\Scripts\test.txt" | Select-Object Attributes
(Get-Item "C:\Scripts\test.txt").Attributes
# Set file attributes
Set-ItemProperty "C:\Scripts\test.txt" -Name Attributes -Value "ReadOnly"
Set-ItemProperty "C:\Scripts\test.txt" -Name Attributes -Value "Hidden"
# Clear attributes
Set-ItemProperty "C:\Scripts\test.txt" -Name Attributes -Value "Normal"
Bulk Operations and Automation
Mass File Operations:
# Bulk rename files
Get-ChildItem "C:\Photos\*.jpg" |
ForEach-Object { Rename-Item $_.FullName -NewName ("IMG_" + $_.Name) }
# Organize files by date
Get-ChildItem "C:\Downloads" |
ForEach-Object {
$year = $_.LastWriteTime.Year
$month = $_.LastWriteTime.ToString("MM-MMM")
$targetPath = "C:\Archive\$year\$month"
if (!(Test-Path $targetPath)) {
New-Item -ItemType Directory -Path $targetPath -Force
}
Move-Item $_.FullName $targetPath
}
File Monitoring and Reporting:
# Generate file system report
$report = Get-ChildItem "C:\Data" -Recurse |
Group-Object Extension |
Select-Object Name, Count, @{Name="TotalSize(MB)";Expression={
[math]::Round(($_.Group | Measure-Object Length -Sum).Sum / 1MB, 2)
}} |
Sort-Object "TotalSize(MB)" -Descending
$report | Export-Csv "C:\Reports\FileSystemReport.csv"
Real-World Scenario – Log File Management:
# Archive old log files and compress them
$logPath = "C:\Logs"
$archivePath = "C:\Archive"
$cutoffDate = (Get-Date).AddDays(-30)
# Find old log files
$oldLogs = Get-ChildItem $logPath -Filter "*.log" |
Where-Object {$_.LastWriteTime -lt $cutoffDate}
foreach ($log in $oldLogs) {
$yearMonth = $log.LastWriteTime.ToString("yyyy-MM")
$archiveFolder = Join-Path $archivePath $yearMonth
# Create archive folder if it doesn't exist
if (!(Test-Path $archiveFolder)) {
New-Item -ItemType Directory -Path $archiveFolder -Force
}
# Compress and move the log file
Compress-Archive -Path $log.FullName -DestinationPath (Join-Path $archiveFolder "$($log.BaseName).zip")
Remove-Item $log.FullName
}
Disk Space Management Example:
# Find large files consuming disk space
$largeFIles = Get-ChildItem "C:\" -Recurse -ErrorAction SilentlyContinue |
Where-Object {!$_.PSIsContainer -and $_.Length -gt 100MB} |
Sort-Object Length -Descending |
Select-Object FullName, @{Name="Size(MB)";Expression={[math]::Round($_.Length/1MB,2)}}, LastWriteTime
$largeFIles | Export-Csv "C:\Reports\LargeFiles.csv" -NoTypeInformation
File management forms the backbone of system administration. Next, we’ll explore user and group management operations essential for security and access control.
Chapter 4: User and Group Management
Local User Account Management
Creating and Managing Local Users:
# Create secure password
$password = ConvertTo-SecureString "P@ssw0rd123!" -AsPlainText -Force
# Create new local user
New-LocalUser -Name "ServiceAccount" -Password $password -Description "Application Service Account"
# Set user properties
Set-LocalUser -Name "ServiceAccount" -PasswordNeverExpires $true
Set-LocalUser -Name "ServiceAccount" -UserMayChangePassword $false
Set-LocalUser -Name "ServiceAccount" -AccountNeverExpires
# Get user information
Get-LocalUser -Name "ServiceAccount"
Get-LocalUser | Where-Object {$_.Enabled -eq $false}
# Disable/Enable users
Disable-LocalUser -Name "ServiceAccount"
Enable-LocalUser -Name "ServiceAccount"
# Change password
$newPassword = ConvertTo-SecureString "NewP@ssw0rd123!" -AsPlainText -Force
Set-LocalUser -Name "ServiceAccount" -Password $newPassword
Local Group Management:
# Create local groups
New-LocalGroup -Name "DatabaseAdmins" -Description "Database Administrator Group"
# Add users to groups
Add-LocalGroupMember -Group "DatabaseAdmins" -Member "ServiceAccount"
Add-LocalGroupMember -Group "Administrators" -Member "Domain\ITAdmin"
# List group members
Get-LocalGroupMember -Group "Administrators"
Get-LocalGroupMember -Group "DatabaseAdmins"
# Remove users from groups
Remove-LocalGroupMember -Group "DatabaseAdmins" -Member "ServiceAccount"
# List all groups and their members
Get-LocalGroup | ForEach-Object {
Write-Host "Group: $($_.Name)" -ForegroundColor Green
Get-LocalGroupMember -Group $_.Name | ForEach-Object {
Write-Host " Member: $($_.Name)" -ForegroundColor Yellow
}
}
Active Directory User Management
Prerequisites and Setup:
# Install RSAT tools (Windows 10/11)
Get-WindowsCapability -Name RSAT* -Online | Add-WindowsCapability -Online
# Import Active Directory module
Import-Module ActiveDirectory
# Check domain connectivity
Test-ComputerSecureChannel
Get-ADDomain
User Account Operations:
# Create new AD user
$userParams = @{
Name = "John Smith"
GivenName = "John"
Surname = "Smith"
SamAccountName = "jsmith"
UserPrincipalName = "jsmith@company.com"
Path = "OU=Users,DC=company,DC=com"
AccountPassword = (ConvertTo-SecureString "TempP@ssw0rd123!" -AsPlainText -Force)
Enabled = $true
ChangePasswordAtLogon = $true
}
New-ADUser @userParams
# Modify user properties
Set-ADUser -Identity "jsmith" -Department "IT" -Title "Systems Administrator"
Set-ADUser -Identity "jsmith" -Office "Building A" -OfficePhone "555-1234"
# Get user information
Get-ADUser -Identity "jsmith" -Properties *
Get-ADUser -Filter {Department -eq "IT"} -Properties Name, Department, Title
# Disable/Enable users
Disable-ADAccount -Identity "jsmith"
Enable-ADAccount -Identity "jsmith"
# Reset passwords
Set-ADAccountPassword -Identity "jsmith" -NewPassword (ConvertTo-SecureString "NewP@ssw0rd!" -AsPlainText -Force)
Set-ADUser -Identity "jsmith" -ChangePasswordAtLogon $true
Group Management in Active Directory:
# Create security groups
New-ADGroup -Name "IT-Administrators" -GroupScope Global -GroupCategory Security -Path "OU=Groups,DC=company,DC=com"
# Add users to groups
Add-ADGroupMember -Identity "IT-Administrators" -Members "jsmith", "jadoe"
# Get group members
Get-ADGroupMember -Identity "IT-Administrators"
# Get user's group memberships
Get-ADPrincipalGroupMembership -Identity "jsmith" | Select-Object Name
# Remove users from groups
Remove-ADGroupMember -Identity "IT-Administrators" -Members "jsmith"
Bulk User Operations
Mass User Creation from CSV:
# CSV format: FirstName,LastName,Department,Username
# Example CSV content:
# John,Doe,IT,jdoe
# Jane,Smith,HR,jsmith
$users = Import-Csv "C:\Scripts\NewUsers.csv"
foreach ($user in $users) {
$username = $user.Username
$password = ConvertTo-SecureString "TempPass123!" -AsPlainText -Force
try {
New-ADUser -Name "$($user.FirstName) $($user.LastName)" `
-GivenName $user.FirstName `
-Surname $user.LastName `
-SamAccountName $username `
-UserPrincipalName "$username@company.com" `
-Department $user.Department `
-AccountPassword $password `
-Enabled $true `
-ChangePasswordAtLogon $true `
-Path "OU=Users,DC=company,DC=com"
Write-Host "Created user: $username" -ForegroundColor Green
}
catch {
Write-Host "Failed to create user: $username - $($_.Exception.Message)" -ForegroundColor Red
}
}
User Audit and Reporting:
# Generate user activity report
$report = Get-ADUser -Filter * -Properties LastLogonDate, PasswordLastSet, Enabled |
Select-Object Name, SamAccountName, Enabled, LastLogonDate, PasswordLastSet,
@{Name="DaysSinceLastLogon";Expression={
if ($_.LastLogonDate) {
(Get-Date) - $_.LastLogonDate | ForEach-Object Days
} else {
"Never"
}
}},
@{Name="PasswordAge";Expression={
if ($_.PasswordLastSet) {
(Get-Date) - $_.PasswordLastSet | ForEach-Object Days
} else {
"Unknown"
}
}}
# Export to CSV
$report | Export-Csv "C:\Reports\UserAudit.csv" -NoTypeInformation
# Find inactive users (no logon in 90 days)
$inactiveUsers = $report | Where-Object {
$_.DaysSinceLastLogon -ne "Never" -and $_.DaysSinceLastLogon -gt 90
}
$inactiveUsers | Export-Csv "C:\Reports\InactiveUsers.csv" -NoTypeInformation
Advanced User Management
Service Account Management:
# Create service account with specific attributes
$serviceAccountParams = @{
Name = "SQL Service Account"
SamAccountName = "sqlservice"
UserPrincipalName = "sqlservice@company.com"
AccountPassword = (ConvertTo-SecureString "SuperStr0ngP@ssw0rd!" -AsPlainText -Force)
Enabled = $true
PasswordNeverExpires = $true
CannotChangePassword = $true
Description = "SQL Server Service Account"
Path = "OU=ServiceAccounts,DC=company,DC=com"
}
New-ADUser @serviceAccountParams
# Set Service Principal Names (SPNs)
Set-ADUser -Identity "sqlservice" -ServicePrincipalNames @{Add="MSSQLSvc/server.company.com:1433"}
Group Policy and Permission Delegation:
# Find users with administrative privileges
$adminGroups = @("Domain Admins", "Enterprise Admins", "Administrators")
$adminUsers = @()
foreach ($group in $adminGroups) {
$members = Get-ADGroupMember -Identity $group -Recursive
$adminUsers += $members
}
$adminUsers | Select-Object Name, SamAccountName | Sort-Object Name -Unique
Real-World Scenario – Employee Onboarding Automation:
function New-EmployeeAccount {
param(
[string]$FirstName,
[string]$LastName,
[string]$Department,
[string]$Manager,
[string]$Title
)
# Generate username
$username = ($FirstName.Substring(0,1) + $LastName).ToLower()
# Create user account
$userParams = @{
Name = "$FirstName $LastName"
GivenName = $FirstName
Surname = $LastName
SamAccountName = $username
UserPrincipalName = "$username@company.com"
Department = $Department
Title = $Title
Manager = (Get-ADUser -Filter {Name -eq $Manager}).DistinguishedName
AccountPassword = (ConvertTo-SecureString "Welcome123!" -AsPlainText -Force)
Enabled = $true
ChangePasswordAtLogon = $true
Path = "OU=Users,DC=company,DC=com"
}
New-ADUser @userParams
# Add to department groups
$departmentGroups = Get-ADGroup -Filter {Name -like "*$Department*"}
foreach ($group in $departmentGroups) {
Add-ADGroupMember -Identity $group -Members $username
}
# Create home folder
$homePath = "\\fileserver\home\$username"
New-Item -ItemType Directory -Path $homePath -Force
# Set permissions on home folder
$acl = Get-Acl $homePath
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"company\$username", "FullControl", "ContainerInherit,ObjectInherit", "None", "Allow"
)
$acl.SetAccessRule($accessRule)
Set-Acl $homePath $acl
Write-Host "Employee account created: $username" -ForegroundColor Green
}
# Usage example
New-EmployeeAccount -FirstName "Jane" -LastName "Doe" -Department "IT" -Manager "John Smith" -Title "Systems Analyst"
User and group management provides the security foundation for your environment. Next, we’ll explore system monitoring and information gathering techniques essential for maintaining healthy systems.
Chapter 5: System Information and Monitoring
Hardware and System Information
Comprehensive System Details:
# Get detailed computer information
Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, TotalPhysicalMemory,
CsProcessors, CsModel, CsManufacturer
# CPU information
Get-WmiObject Win32_Processor | Select-Object Name, NumberOfCores, NumberOfLogicalProcessors,
MaxClockSpeed, LoadPercentage
# Memory information
Get-WmiObject Win32_PhysicalMemory | Select-Object Manufacturer, PartNumber, Capacity, Speed,
@{Name="CapacityGB";Expression={[math]::Round($_.Capacity/1GB,2)}}
# Disk information
Get-WmiObject Win32_LogicalDisk | Select-Object DeviceID, VolumeName, FileSystem,
@{Name="SizeGB";Expression={[math]::Round($_.Size/1GB,2)}},
@{Name="FreeSpaceGB";Expression={[math]::Round($_.FreeSpace/1GB,2)}},
@{Name="PercentFree";Expression={[math]::Round(($_.FreeSpace/$_.Size)*100,2)}}
Network Configuration:
# Network adapter information
Get-NetAdapter | Select-Object Name, InterfaceDescription, LinkSpeed, Status
# IP configuration
Get-NetIPConfiguration | Select-Object InterfaceAlias, IPv4Address, IPv6Address, DNSServer
# Detailed network settings
Get-WmiObject Win32_NetworkAdapterConfiguration | Where-Object {$_.IPEnabled} |
Select-Object Description, IPAddress, SubnetMask, DefaultIPGateway, DNSServerSearchOrder
# Network connectivity tests
Test-NetConnection -ComputerName "google.com" -Port 80
Test-NetConnection -ComputerName "dc01.company.com" -Port 389 # LDAP
Test-NetConnection -ComputerName "fileserver.company.com" -Port 445 # SMB
Process and Service Monitoring
Process Management and Monitoring:
# Get running processes with detailed information
Get-Process | Select-Object Name, Id, CPU, WorkingSet, StartTime |
Sort-Object WorkingSet -Descending | Select-Object -First 10
# Monitor specific processes
Get-Process -Name "w3wp" | Select-Object Name, Id, CPU, WorkingSet, Handles
# Find processes by criteria
Get-Process | Where-Object {$_.WorkingSet -gt 100MB}
Get-Process | Where-Object {$_.CPU -gt 100}
# Process with full command line
Get-WmiObject Win32_Process | Select-Object Name, ProcessId, CommandLine |
Where-Object {$_.CommandLine -like "*IIS*"}
# Kill processes
Stop-Process -Name "notepad" -Force
Get-Process -Name "chrome" | Stop-Process -Force
Service Monitoring and Management:
# Service status overview
Get-Service | Group-Object Status | Select-Object Name, Count
# Critical services monitoring
$criticalServices = @("Spooler", "DHCP", "DNS", "EventLog", "LanmanServer", "Workstation")
Get-Service -Name $criticalServices | Select-Object Name, Status, StartType
# Services that should be running but aren't
Get-Service | Where-Object {$_.StartType -eq "Automatic" -and $_.Status -eq "Stopped"}
# Service dependencies
Get-Service -Name "Spooler" -DependentServices
Get-Service -Name "Spooler" -RequiredServices
# Service configuration
Get-WmiObject Win32_Service | Where-Object {$_.Name -eq "Spooler"} |
Select-Object Name, State, StartMode, StartName, PathName
Performance Monitoring
Performance Counters:
# CPU usage
Get-Counter "\Processor(_Total)\% Processor Time" -SampleInterval 2 -MaxSamples 5
# Memory usage
Get-Counter "\Memory\Available MBytes"
Get-Counter "\Memory\% Committed Bytes In Use"
# Disk performance
Get-Counter "\PhysicalDisk(_Total)\% Disk Time"
Get-Counter "\PhysicalDisk(_Total)\Disk Reads/sec"
Get-Counter "\PhysicalDisk(_Total)\Disk Writes/sec"
# Network performance
Get-Counter "\Network Interface(*)\Bytes Total/sec"
# Multiple counters at once
$counters = @(
"\Processor(_Total)\% Processor Time",
"\Memory\Available MBytes",
"\PhysicalDisk(_Total)\% Disk Time"
)
Get-Counter -Counter $counters -SampleInterval 5 -MaxSamples 12
Event Log Monitoring:
# Recent system errors
Get-WinEvent -LogName System -FilterLevel Error -MaxEvents 50 |
Select-Object TimeCreated, Id, LevelDisplayName, Message
# Application errors
Get-WinEvent -LogName Application -FilterLevel Error -MaxEvents 50 |
Select-Object TimeCreated, Id, ProviderName, Message
# Security events (failed logons)
Get-WinEvent -LogName Security | Where-Object {$_.Id -eq 4625} |
Select-Object TimeCreated, Message -First 10
# Custom event log queries
$filterHash = @{
LogName = 'System'
Level = 2,3 # Error and Warning
StartTime = (Get-Date).AddDays(-7)
}
Get-WinEvent -FilterHashtable $filterHash |
Group-Object Id | Sort-Object Count -Descending
System Health Monitoring Script
Comprehensive Health Check:
function Get-SystemHealth {
$report = @{}
# System Information
$computerInfo = Get-ComputerInfo
$report.ComputerName = $computerInfo.CsName
$report.OS = $computerInfo.WindowsProductName
$report.LastBoot = $computerInfo.CsBootUpTime
$report.Uptime = (Get-Date) - $computerInfo.CsBootUpTime
# CPU Usage
$cpu = Get-Counter "\Processor(_Total)\% Processor Time" -SampleInterval 1 -MaxSamples 3
$report.CPUUsage = [math]::Round(($cpu.CounterSamples | Measure-Object CookedValue -Average).Average, 2)
# Memory Usage
$memory = Get-WmiObject Win32_OperatingSystem
$report.MemoryUsedPercent = [math]::Round((($memory.TotalVisibleMemorySize - $memory.FreePhysicalMemory) / $memory.TotalVisibleMemorySize) * 100, 2)
# Disk Space
$disks = Get-WmiObject Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3}
$report.DiskInfo = $disks | Select-Object DeviceID,
@{Name="FreeSpacePercent";Expression={[math]::Round(($_.FreeSpace/$_.Size)*100,2)}}
# Critical Services
$criticalServices = @("Spooler", "EventLog", "LanmanServer", "Workstation")
$report.ServiceStatus = Get-Service -Name $criticalServices |
Where-Object {$_.Status -ne "Running"} | Select-Object Name, Status
# Recent Errors
$report.RecentErrors = Get-WinEvent -LogName System -FilterLevel Error -MaxEvents 5 -ErrorAction SilentlyContinue |
Select-Object TimeCreated, Id, Message
return $report
}
# Generate and display health report
$healthReport = Get-SystemHealth
$healthReport | ConvertTo-Json -Depth 3 | Out-File "C:\Reports\SystemHealth_$(Get-Date -Format 'yyyyMMdd_HHmm').json"
Automated Monitoring with Alerts:
function Start-SystemMonitoring {
param(
[int]$CPUThreshold = 80,
[int]$MemoryThreshold = 85,
[int]$DiskThreshold = 10
)
while ($true) {
# Check CPU
$cpu = Get-Counter "\Processor(_Total)\% Processor Time" -SampleInterval 1 -MaxSamples 1
$cpuUsage = $cpu.CounterSamples[0].CookedValue
if ($cpuUsage -gt $CPUThreshold) {
Write-Warning "High CPU usage detected: $([math]::Round($cpuUsage,2))%"
# Send alert email or log to event log
}
# Check Memory
$memory = Get-WmiObject Win32_OperatingSystem
$memoryUsedPercent = (($memory.TotalVisibleMemorySize - $memory.FreePhysicalMemory) / $memory.TotalVisibleMemorySize) * 100
if ($memoryUsedPercent -gt $MemoryThreshold) {
Write-Warning "High memory usage detected: $([math]::Round($memoryUsedPercent,2))%"
}
# Check Disk Space
$disks = Get-WmiObject Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3}
foreach ($disk in $disks) {
$freeSpacePercent = ($disk.FreeSpace / $disk.Size) * 100
if ($freeSpacePercent -lt $DiskThreshold) {
Write-Warning "Low disk space on $($disk.DeviceID): $([math]::Round($freeSpacePercent,2))% free"
}
}
Start-Sleep -Seconds 60 # Check every minute
}
}
# Start monitoring (run in background job)
Start-Job -ScriptBlock ${function:Start-SystemMonitoring} -ArgumentList 80, 85, 10
System monitoring provides the data needed for proactive administration. Next, we’ll explore network administration and troubleshooting techniques essential for connectivity management.
Chapter 6: Network Administration and Troubleshooting

Network Configuration and Management
Basic Network Information:
# Get all network adapters
Get-NetAdapter | Select-Object Name, InterfaceDescription, Status, LinkSpeed, FullDuplex
# IP configuration for all adapters
Get-NetIPConfiguration | Select-Object InterfaceAlias, IPv4Address, IPv4DefaultGateway, DNSServer
# Specific adapter configuration
Get-NetIPConfiguration -InterfaceAlias "Ethernet" | Select-Object *
# Get routing table
Get-NetRoute | Select-Object DestinationPrefix, NextHop, InterfaceAlias, RouteMetric
IP Address Management:
# Set static IP address
New-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress "192.168.1.100" -PrefixLength 24 -DefaultGateway "192.168.1.1"
# Set DNS servers
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ServerAddresses "8.8.8.8", "8.8.4.4"
# Enable DHCP
Set-NetIPInterface -InterfaceAlias "Ethernet" -Dhcp Enabled
Set-DnsClientServerAddress -InterfaceAlias "Ethernet" -ResetServerAddresses
# Remove IP address
Remove-NetIPAddress -InterfaceAlias "Ethernet" -IPAddress "192.168.1.100" -Confirm:$false
Network Adapter Management:
# Enable/Disable network adapters
Disable-NetAdapter -Name "Wi-Fi" -Confirm:$false
Enable-NetAdapter -Name "Wi-Fi"
# Restart network adapter
Restart-NetAdapter -Name "Ethernet"
# Get adapter properties
Get-NetAdapterAdvancedProperty -Name "Ethernet" | Select-Object DisplayName, DisplayValue
# Set adapter properties
Set-NetAdapterAdvancedProperty -Name "Ethernet" -DisplayName "Speed & Duplex" -DisplayValue "1.0 Gbps Full Duplex"
Network Connectivity Testing
Basic Connectivity Tests:
# Ping tests
Test-NetConnection -ComputerName "google.com"
Test-NetConnection -ComputerName "192.168.1.1" -InformationLevel Detailed
# Port connectivity tests
Test-NetConnection -ComputerName "mail.company.com" -Port 25 # SMTP
Test-NetConnection -ComputerName "dc01.company.com" -Port 389 # LDAP
Test-NetConnection -ComputerName "sql01.company.com" -Port 1433 # SQL Server
Test-NetConnection -ComputerName "web01.company.com" -Port 443 # HTTPS
# Trace route
Test-NetConnection -ComputerName "google.com" -TraceRoute
Advanced Network Diagnostics:
# DNS resolution tests
Resolve-DnsName -Name "company.com"
Resolve-DnsName -Name "company.com" -Type MX
Resolve-DnsName -Name "192.168.1.10" -Type PTR
# Test DNS server response
Resolve-DnsName -Name "google.com" -Server "8.8.8.8"
Resolve-DnsName -Name "google.com" -Server "1.1.1.1"
# Network statistics
Get-NetTCPConnection | Group-Object State | Select-Object Name, Count
Get-NetTCPConnection -State Listen | Select-Object LocalAddress, LocalPort, OwningProcess
# Network adapter statistics
Get-NetAdapterStatistics | Select-Object Name, BytesReceived, BytesSent, PacketsReceived, PacketsSent
Firewall Management
Windows Firewall Configuration:
# Get firewall profiles
Get-NetFirewallProfile | Select-Object Name, Enabled, DefaultInboundAction, DefaultOutboundAction
# Enable/Disable firewall
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled False
# Create firewall rules
New-NetFirewallRule -DisplayName "Allow HTTP" -Direction Inbound -Protocol TCP -LocalPort 80 -Action Allow
New-NetFirewallRule -DisplayName "Allow HTTPS" -Direction Inbound -Protocol TCP -LocalPort 443 -Action Allow
# Get existing rules
Get-NetFirewallRule | Where-Object {$_.Enabled -eq "True"} | Select-Object DisplayName, Direction, Action
# Remove firewall rule
Remove-NetFirewallRule -DisplayName "Allow HTTP"
# Block specific program
New-NetFirewallRule -DisplayName "Block Notepad" -Direction Outbound -Program "C:\Windows\System32\notepad.exe" -Action Block
Network Troubleshooting Scripts
Comprehensive Network Test:
function Test-NetworkConnectivity {
param(
[string[]]$TestHosts = @("8.8.8.8", "google.com", "microsoft.com"),
[hashtable]$PortTests = @{
"dc01.company.com" = @(53, 389, 636)
"mail.company.com" = @(25, 110, 143, 993, 995)
"web01.company.com" = @(80, 443)
}
)
Write-Host "=== Network Connectivity Test ===" -ForegroundColor Green
# Basic connectivity tests
Write-Host "`nBasic Connectivity:" -ForegroundColor Yellow
foreach ($host in $TestHosts) {
$result = Test-NetConnection -ComputerName $host -InformationLevel Quiet
$status = if ($result) { "SUCCESS" } else { "FAILED" }
$color = if ($result) { "Green" } else { "Red" }
Write-Host " $host : $status" -ForegroundColor $color
}
# DNS resolution tests
Write-Host "`nDNS Resolution:" -ForegroundColor Yellow
foreach ($host in $TestHosts | Where-Object {$_ -notmatch "^\d+\.\d+\.\d+\.\d+$"}) {
try {
$dnsResult = Resolve-DnsName -Name $host -ErrorAction Stop
Write-Host " $host : SUCCESS ($($dnsResult[0].IPAddress))" -ForegroundColor Green
}
catch {
Write-Host " $host : FAILED" -ForegroundColor Red
}
}
# Port connectivity tests
Write-Host "`nPort Connectivity:" -ForegroundColor Yellow
foreach ($server in $PortTests.Keys) {
Write-Host " $server" -ForegroundColor Cyan
foreach ($port in $PortTests[$server]) {
$result = Test-NetConnection -ComputerName $server -Port $port -InformationLevel Quiet
$status = if ($result) { "OPEN" } else { "CLOSED" }
$color = if ($result) { "Green" } else { "Red" }
Write-Host " Port $port : $status" -ForegroundColor $color
}
}
# Network adapter status
Write-Host "`nNetwork Adapters:" -ForegroundColor Yellow
Get-NetAdapter | ForEach-Object {
$color = if ($_.Status -eq "Up") { "Green" } else { "Red" }
Write-Host " $($_.Name) : $($_.Status)" -ForegroundColor $color
}
}
# Run the network test
Test-NetworkConnectivity
Network Performance Monitoring:
function Monitor-NetworkPerformance {
param(
[int]$Duration = 60, # seconds
[int]$Interval = 5 # seconds
)
$samples = $Duration / $Interval
$results = @()
Write-Host "Monitoring network performance for $Duration seconds..." -ForegroundColor Green
for ($i = 1; $i -le $samples; $i++) {
$timestamp = Get-Date
# Get network adapter statistics
$adapters = Get-NetAdapterStatistics | Where-Object {$_.Name -notlike "*Loopback*"}
foreach ($adapter in $adapters) {
$result = [PSCustomObject]@{
Timestamp = $timestamp
Adapter = $adapter.Name
BytesReceived = $adapter.BytesReceived
BytesSent = $adapter.BytesSent
PacketsReceived = $adapter.PacketsReceived
PacketsSent = $adapter.PacketsSent
}
$results += $result
}
Write-Progress -Activity "Network Monitoring" -Status "Sample $i of $samples" -PercentComplete (($i / $samples) * 100)
Start-Sleep -Seconds $Interval
}
# Calculate throughput
$grouped = $results | Group-Object Adapter
foreach ($group in $grouped) {
$first = $group.Group | Sort-Object Timestamp | Select-Object -First 1
$last = $group.Group | Sort-Object Timestamp | Select-Object -Last 1
$duration = ($last.Timestamp - $first.Timestamp).TotalSeconds
$bytesReceivedRate = ($last.BytesReceived - $first.BytesReceived) / $duration
$bytesSentRate = ($last.BytesSent - $first.BytesSent) / $duration
Write-Host "`nAdapter: $($group.Name)" -ForegroundColor Yellow
Write-Host " Receive Rate: $([math]::Round($bytesReceivedRate / 1MB, 2)) MB/s" -ForegroundColor Green
Write-Host " Send Rate: $([math]::Round($bytesSentRate / 1MB, 2)) MB/s" -ForegroundColor Green
}
return $results
}
# Monitor network performance
$networkData = Monitor-NetworkPerformance -Duration 120 -Interval 10
Wi-Fi Management:
# Get Wi-Fi profiles
netsh wlan show profiles
# Get Wi-Fi profile details
netsh wlan show profile name="YourWiFiName" key=clear
# Connect to Wi-Fi network
netsh wlan connect name="YourWiFiName"
# Add Wi-Fi profile
$profileXml = @"
<?xml version="1.0"?>
<WLANProfile xmlns="http://www.microsoft.com/networking/WLAN/profile/v1">
<name>TestNetwork</name>
<SSIDConfig>
<SSID>
<name>TestNetwork</name>
</SSID>
</SSIDConfig>
<connectionType>ESS</connectionType>
<connectionMode>auto</connectionMode>
<MSM>
<security>
<authEncryption>
<authentication>WPA2PSK</authentication>
<encryption>AES</encryption>
</authEncryption>
<sharedKey>
<keyType>passPhrase</keyType>
<protected>false</protected>
<keyMaterial>YourPassword</keyMaterial>
</sharedKey>
</security>
</MSM>
</WLANProfile>
"@
$profileXml | Out-File -FilePath "C:\temp\wifi-profile.xml" -Encoding UTF8
netsh wlan add profile filename="C:\temp\wifi-profile.xml"
Network administration skills enable you to maintain connectivity and troubleshoot issues effectively. Next, we’ll explore security and permissions management essential for maintaining secure systems.
Chapter 7: Security and Permissions Management
NTFS Permissions Management
Understanding and Managing File Permissions:
# Get current permissions on a file or folder
Get-Acl "C:\ImportantData" | Format-List
(Get-Acl "C:\ImportantData").Access | Select-Object IdentityReference, FileSystemRights, AccessControlType
# Create new permission entry
$acl = Get-Acl "C:\ImportantData"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"DOMAIN\Username", # Identity
"FullControl", # Rights
"ContainerInherit,ObjectInherit", # Inheritance
"None", # Propagation
"Allow" # Type
)
$acl.SetAccessRule($accessRule)
Set-Acl "C:\ImportantData" $acl
# Remove permissions
$acl = Get-Acl "C:\ImportantData"
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"DOMAIN\Username", "FullControl", "Allow"
)
$acl.RemoveAccessRule($accessRule)
Set-Acl "C:\ImportantData" $acl
# Set permissions for multiple users
$permissions = @{
"DOMAIN\ITAdmins" = "FullControl"
"DOMAIN\Users" = "ReadAndExecute"
"DOMAIN\Managers" = "Modify"
}
$acl = Get-Acl "C:\SharedFolder"
foreach ($user in $permissions.Keys) {
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
$user, $permissions[$user], "ContainerInherit,ObjectInherit", "None", "Allow"
)
$acl.SetAccessRule($accessRule)
}
Set-Acl "C:\SharedFolder" $acl
Advanced Permission Management:
# Copy permissions from one folder to another
$sourceAcl = Get-Acl "C:\SourceFolder"
Set-Acl "C:\DestinationFolder" $sourceAcl
# Reset permissions to default
$acl = Get-Acl "C:\Folder"
$acl.SetAccessRuleProtection($false, $false) # Enable inheritance, remove explicit permissions
Set-Acl "C:\Folder" $acl
# Disable inheritance and keep existing permissions
$acl = Get-Acl "C:\Folder"
$acl.SetAccessRuleProtection($true, $true) # Disable inheritance, keep existing
Set-Acl "C:\Folder" $acl
# Bulk permission changes
Get-ChildItem "C:\Data" -Directory | ForEach-Object {
$acl = Get-Acl $_.FullName
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
"DOMAIN\DataUsers", "ReadAndExecute", "ContainerInherit,ObjectInherit", "None", "Allow"
)
$acl.SetAccessRule($accessRule)
Set-Acl $_.FullName $acl
Write-Host "Updated permissions for $($_.Name)" -ForegroundColor Green
}
Registry Security and Management
Registry Permissions:
# Get registry key permissions
$regPath = "HKLM:\SOFTWARE\MyCompany"
$acl = Get-Acl $regPath
$acl.Access | Select-Object IdentityReference, RegistryRights, AccessControlType
# Set registry permissions
$acl = Get-Acl $regPath
$accessRule = New-Object System.Security.AccessControl.RegistryAccessRule(
"DOMAIN\Users", "ReadKey", "Allow"
)
$acl.SetAccessRule($accessRule)
Set-Acl $regPath $acl
# Create secure registry entries
New-Item -Path "HKLM:\SOFTWARE\SecureApp" -Force
New-ItemProperty -Path "HKLM:\SOFTWARE\SecureApp" -Name "APIKey" -Value "SecretValue" -PropertyType String
# Secure the registry key
$acl = Get-Acl "HKLM:\SOFTWARE\SecureApp"
$acl.SetAccessRuleProtection($true, $false) # Remove inheritance
$accessRule = New-Object System.Security.AccessControl.RegistryAccessRule(
"BUILTIN\Administrators", "FullControl", "Allow"
)
$acl.SetAccessRule($accessRule)
Set-Acl "HKLM:\SOFTWARE\SecureApp" $acl
User Account Security
Password Policy and Account Management:
# Get password policy
Get-ADDefaultDomainPasswordPolicy
# Set user account properties for security
Set-ADUser -Identity "serviceaccount" -AccountNotDelegated $true
Set-ADUser -Identity "serviceaccount" -SmartcardLogonRequired $false
Set-ADUser -Identity "serviceaccount" -TrustedForDelegation $false
# Find users with non-expiring passwords
Get-ADUser -Filter {PasswordNeverExpires -eq $true} -Properties PasswordNeverExpires |
Select-Object Name, SamAccountName, PasswordNeverExpires
# Find users with passwords older than 90 days
$cutoffDate = (Get-Date).AddDays(-90)
Get-ADUser -Filter * -Properties PasswordLastSet |
Where-Object {$_.PasswordLastSet -lt $cutoffDate} |
Select-Object Name, SamAccountName, PasswordLastSet
# Disable inactive user accounts
$inactiveDate = (Get-Date).AddDays(-90)
Get-ADUser -Filter * -Properties LastLogonDate |
Where-Object {$_.LastLogonDate -lt $inactiveDate -and $_.Enabled -eq $true} |
ForEach-Object {
Disable-ADAccount -Identity $_.SamAccountName
Write-Host "Disabled account: $($_.SamAccountName)" -ForegroundColor Yellow
}
Certificate Management
Managing Digital Certificates:
# Get certificates from local store
Get-ChildItem Cert:\LocalMachine\My
Get-ChildItem Cert:\CurrentUser\My
# Find certificates expiring soon
$expiryDate = (Get-Date).AddDays(30)
Get-ChildItem Cert:\LocalMachine\My |
Where-Object {$_.NotAfter -lt $expiryDate} |
Select-Object Subject, NotAfter, Thumbprint
# Import certificate
$certPath = "C:\Certificates\mycert.pfx"
$certPassword = ConvertTo-SecureString "password" -AsPlainText -Force
Import-PfxCertificate -FilePath $certPath -Password $certPassword -CertStoreLocation Cert:\LocalMachine\My
# Export certificate
$cert = Get-ChildItem Cert:\LocalMachine\My | Where-Object {$_.Subject -like "*myserver*"}
$certPassword = ConvertTo-SecureString "exportpassword" -AsPlainText -Force
Export-PfxCertificate -Cert $cert -FilePath "C:\Exports\mycert.pfx" -Password $certPassword
# Remove expired certificates
Get-ChildItem Cert:\LocalMachine\My |
Where-Object {$_.NotAfter -lt (Get-Date)} |
Remove-Item
Security Auditing and Monitoring
Security Event Monitoring:
# Monitor failed logon attempts
Get-WinEvent -LogName Security |
Where-Object {$_.Id -eq 4625} |
Select-Object TimeCreated, @{Name="Username";Expression={$_.Properties[5].Value}}, @{Name="SourceIP";Expression={$_.Properties[19].Value}} |
Group-Object Username | Sort-Object Count -Descending
# Monitor successful logons
Get-WinEvent -LogName Security |
Where-Object {$_.Id -eq 4624} |
Select-Object TimeCreated, @{Name="Username";Expression={$_.Properties[5].Value}}, @{Name="LogonType";Expression={$_.Properties[8].Value}}
# Monitor privilege escalation
Get-WinEvent -LogName Security |
Where-Object {$_.Id -eq 4672} |
Select-Object TimeCreated, @{Name="Username";Expression={$_.Properties[1].Value}}
# Account lockout monitoring
Get-WinEvent -LogName Security |
Where-Object {$_.Id -eq 4740} |
Select-Object TimeCreated, @{Name="Username";Expression={$_.Properties[0].Value}}, @{Name="Source";Expression={$_.Properties[1].Value}}
Comprehensive Security Audit Script:
function Invoke-SecurityAudit {
$report = @{}
$report.Timestamp = Get-Date
$report.ComputerName = $env:COMPUTERNAME
# Local administrators
$report.LocalAdmins = Get-LocalGroupMember -Group "Administrators" | Select-Object Name, ObjectClass
# Services running as system
$report.SystemServices = Get-WmiObject Win32_Service |
Where-Object {$_.StartName -eq "LocalSystem"} |
Select-Object Name, State, StartMode
# Shared folders
$report.Shares = Get-SmbShare | Select-Object Name, Path, Description
# Firewall status
$report.FirewallProfiles = Get-NetFirewallProfile | Select-Object Name, Enabled
# Recent security events
$report.RecentSecurityEvents = Get-WinEvent -LogName Security -MaxEvents 100 |
Where-Object {$_.Id -in @(4624, 4625, 4672, 4740)} |
Group-Object Id | Select-Object Name, Count
# Password policy
try {
$report.PasswordPolicy = Get-ADDefaultDomainPasswordPolicy -ErrorAction Stop |
Select-Object MinPasswordLength, PasswordHistoryCount, MaxPasswordAge
}
catch {
$report.PasswordPolicy = "Not available (not domain joined or no AD module)"
}
# User rights assignments
$report.UserRights = @{
LogonAsService = (Get-WmiObject -Class Win32_SystemAccount | Where-Object {$_.Name -eq "SeServiceLogonRight"})
LogonAsBatch = (Get-WmiObject -Class Win32_SystemAccount | Where-Object {$_.Name -eq "SeBatchLogonRight"})
}
return $report
}
# Generate security audit report
$securityAudit = Invoke-SecurityAudit
$securityAudit | ConvertTo-Json -Depth 3 | Out-File "C:\Reports\SecurityAudit_$(Get-Date -Format 'yyyyMMdd').json"
Automated Security Hardening:
function Set-SecurityHardening {
Write-Host "Applying security hardening..." -ForegroundColor Green
# Disable unnecessary services
$unnecessaryServices = @("Fax", "Browser", "TapiSrv")
foreach ($service in $unnecessaryServices) {
try {
Set-Service -Name $service -StartupType Disabled -ErrorAction Stop
Write-Host "Disabled service: $service" -ForegroundColor Yellow
}
catch {
Write-Host "Service $service not found or already disabled" -ForegroundColor Gray
}
}
# Enable Windows Firewall
Set-NetFirewallProfile -Profile Domain,Public,Private -Enabled True
Write-Host "Enabled Windows Firewall for all profiles" -ForegroundColor Green
# Set strong password policy (if domain controller)
try {
Set-ADDefaultDomainPasswordPolicy -MinPasswordLength 12 -PasswordHistoryCount 24 -MaxPasswordAge "90.00:00:00"
Write-Host "Updated domain password policy" -ForegroundColor Green
}
catch {
Write-Host "Could not update domain password policy (not a domain controller)" -ForegroundColor Gray
}
# Registry security settings
$securitySettings = @{
"HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" = @{
"LimitBlankPasswordUse" = 1
"NoLMHash" = 1
}
"HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters" = @{
"RequireSecuritySignature" = 1
}
}
foreach ($regPath in $securitySettings.Keys) {
foreach ($setting in $securitySettings[$regPath].Keys) {
Set-ItemProperty -Path $regPath -Name $setting -Value $securitySettings[$regPath][$setting]
Write-Host "Set registry setting: $regPath\$setting" -ForegroundColor Green
}
}
Write-Host "Security hardening complete!" -ForegroundColor Green
}
# Apply security hardening
Set-SecurityHardening
Security and permissions management ensures your systems remain protected. Our final chapter will cover scripting and automation techniques that tie everything together into comprehensive administrative solutions.
Chapter 8: Scripting, Automation, and Advanced Administration

PowerShell Functions and Modules
Creating Reusable Functions:
# Basic function structure
function Get-SystemInfo {
param(
[string]$ComputerName = $env:COMPUTERNAME,
[switch]$IncludeServices
)
$info = @{}
$info.ComputerName = $ComputerName
$info.OS = (Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName).Caption
$info.Memory = [math]::Round((Get-WmiObject Win32_ComputerSystem -ComputerName $ComputerName).TotalPhysicalMemory / 1GB, 2)
$info.Uptime = (Get-Date) - (Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName).ConvertToDateTime($_.LastBootUpTime)
if ($IncludeServices) {
$info.Services = Get-Service -ComputerName $ComputerName | Group-Object Status | Select-Object Name, Count
}
return [PSCustomObject]$info
}
# Advanced function with parameter validation
function Set-UserPermissions {
[CmdletBinding()]
param(
[Parameter(Mandatory=$true)]
[ValidateScript({Test-Path $_})]
[string]$Path,
[Parameter(Mandatory=$true)]
[string]$Username,
[ValidateSet("ReadAndExecute", "Modify", "FullControl")]
[string]$Permission = "ReadAndExecute",
[switch]$RemoveInheritance
)
try {
$acl = Get-Acl $Path
if ($RemoveInheritance) {
$acl.SetAccessRuleProtection($true, $true)
}
$accessRule = New-Object System.Security.AccessControl.FileSystemAccessRule(
$Username, $Permission, "ContainerInherit,ObjectInherit", "None", "Allow"
)
$acl.SetAccessRule($accessRule)
Set-Acl $Path $acl
Write-Host "Successfully set $Permission permissions for $Username on $Path" -ForegroundColor Green
}
catch {
Write-Error "Failed to set permissions: $($_.Exception.Message)"
}
}
Creating and Managing Modules:
# Create a module directory
$modulePath = "$env:PSModulePath".Split(';')[0]
$moduleFolder = Join-Path $modulePath "AdminTools"
New-Item -ItemType Directory -Path $moduleFolder -Force
# Create module manifest
$manifestParams = @{
Path = Join-Path $moduleFolder "AdminTools.psd1"
ModuleVersion = "1.0.0"
Description = "Administrative tools for Windows management"
PowerShellVersion = "5.1"
Author = "IT Administrator"
RootModule = "AdminTools.psm1"
FunctionsToExport = @("Get-SystemInfo", "Set-UserPermissions", "Invoke-SystemCleanup")
}
New-ModuleManifest @manifestParams
# Create module file (AdminTools.psm1)
$moduleContent = @'
function Get-SystemInfo {
# Function content here
}
function Set-UserPermissions {
# Function content here
}
function Invoke-SystemCleanup {
# Function content here
}
Export-ModuleMember -Function Get-SystemInfo, Set-UserPermissions, Invoke-SystemCleanup
'@
$moduleContent | Out-File -FilePath (Join-Path $moduleFolder "AdminTools.psm1") -Encoding UTF8
# Import and use the module
Import-Module AdminTools
Get-Command -Module AdminTools
Automation with Scheduled Tasks
Creating Scheduled Tasks:
# Create a simple scheduled task
$action = New-ScheduledTaskAction -Execute "PowerShell.exe" -Argument "-File C:\Scripts\SystemMaintenance.ps1"
$trigger = New-ScheduledTaskTrigger -Daily -At "2:00 AM"
$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest
$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable
Register-ScheduledTask -TaskName "System Maintenance" -Action $action -Trigger $trigger -Principal $principal -Settings $settings
# Create task with multiple triggers
$triggers = @(
New-ScheduledTaskTrigger -Daily -At "6:00 AM"
New-ScheduledTaskTrigger -AtStartup
New-ScheduledTaskTrigger -AtLogOn
)
Register-ScheduledTask -TaskName "Multi-Trigger Task" -Action $action -Trigger $triggers -Principal $principal
# Manage existing tasks
Get-ScheduledTask | Where-Object {$_.State -eq "Ready"}
Start-ScheduledTask -TaskName "System Maintenance"
Stop-ScheduledTask -TaskName "System Maintenance"
Unregister-ScheduledTask -TaskName "System Maintenance" -Confirm:$false
Advanced Automation Scripts:
# Comprehensive system maintenance script
function Invoke-SystemMaintenance {
[CmdletBinding()]
param(
[string]$LogPath = "C:\Logs\Maintenance.log",
[int]$DaysToKeepLogs = 30,
[switch]$CleanTemp,
[switch]$DefragmentDisks,
[switch]$UpdateWindows
)
function Write-Log {
param([string]$Message)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
"$timestamp - $Message" | Add-Content -Path $LogPath
Write-Host $Message
}
Write-Log "Starting system maintenance"
# Clean old log files
try {
$cutoffDate = (Get-Date).AddDays(-$DaysToKeepLogs)
Get-ChildItem "C:\Logs" -Filter "*.log" |
Where-Object {$_.LastWriteTime -lt $cutoffDate} |
Remove-Item -Force
Write-Log "Cleaned old log files"
}
catch {
Write-Log "Error cleaning log files: $($_.Exception.Message)"
}
# Clean temporary files
if ($CleanTemp) {
try {
$tempPaths = @("$env:TEMP", "C:\Windows\Temp", "C:\Windows\Prefetch")
foreach ($path in $tempPaths) {
if (Test-Path $path) {
Get-ChildItem $path -Recurse | Remove-Item -Force -Recurse -ErrorAction SilentlyContinue
}
}
Write-Log "Cleaned temporary files"
}
catch {
Write-Log "Error cleaning temp files: $($_.Exception.Message)"
}
}
# Defragment disks
if ($DefragmentDisks) {
try {
$drives = Get-WmiObject Win32_LogicalDisk | Where-Object {$_.DriveType -eq 3 -and $_.FileSystem -eq "NTFS"}
foreach ($drive in $drives) {
Start-Process -FilePath "defrag.exe" -ArgumentList "$($drive.DeviceID) /O" -Wait -NoNewWindow
Write-Log "Defragmented drive $($drive.DeviceID)"
}
}
catch {
Write-Log "Error during defragmentation: $($_.Exception.Message)"
}
}
# Generate system report
$report = @{
Timestamp = Get-Date
DiskSpace = Get-WmiObject Win32_LogicalDisk | Select-Object DeviceID, @{Name="FreeGB";Expression={[math]::Round($_.FreeSpace/1GB,2)}}
Memory = Get-WmiObject Win32_OperatingSystem | Select-Object @{Name="FreeMemoryGB";Expression={[math]::Round($_.FreePhysicalMemory/1MB,2)}}
Services = (Get-Service | Where-Object {$_.Status -eq "Stopped" -and $_.StartType -eq "Automatic"}).Count
}
$report | ConvertTo-Json | Add-Content -Path "C:\Reports\MaintenanceReport_$(Get-Date -Format 'yyyyMMdd').json"
Write-Log "Generated maintenance report"
Write-Log "System maintenance completed"
}
Remote Administration
Remote PowerShell Sessions:
# Enable PowerShell remoting (run on target machines)
Enable-PSRemoting -Force
Set-WSManQuickConfig -Force
# Create remote sessions
$session = New-PSSession -ComputerName "Server01"
$sessions = New-PSSession -ComputerName "Server01", "Server02", "Server03"
# Run commands remotely
Invoke-Command -ComputerName "Server01" -ScriptBlock { Get-Service }
Invoke-Command -Session $session -ScriptBlock { Get-Process | Sort-Object CPU -Descending | Select-Object -First 10 }
# Run script file remotely
Invoke-Command -ComputerName "Server01" -FilePath "C:\Scripts\SystemInfo.ps1"
# Interactive remote session
Enter-PSSession -ComputerName "Server01"
# ... run commands interactively ...
Exit-PSSession
# Copy files to/from remote sessions
Copy-Item -Path "C:\Scripts\*" -Destination "C:\RemoteScripts\" -ToSession $session
Copy-Item -Path "C:\RemoteLogs\*" -Destination "C:\LocalLogs\" -FromSession $session
# Clean up sessions
Remove-PSSession $session
Get-PSSession | Remove-PSSession
Bulk Remote Operations:
# Mass deployment script
function Deploy-Software {
param(
[string[]]$ComputerNames,
[string]$InstallerPath,
[string]$Arguments = "/quiet"
)
$results = @()
foreach ($computer in $ComputerNames) {
try {
# Test connectivity
if (Test-Connection -ComputerName $computer -Count 1 -Quiet) {
# Copy installer
$remotePath = "\\$computer\C$\Temp\installer.msi"
Copy-Item $InstallerPath $remotePath
# Install software
$result = Invoke-Command -ComputerName $computer -ScriptBlock {
param($installer, $args)
Start-Process "msiexec.exe" -ArgumentList "/i $installer $args" -Wait -PassThru
} -ArgumentList "C:\Temp\installer.msi", $Arguments
$results += [PSCustomObject]@{
Computer = $computer
Status = if ($result.ExitCode -eq 0) { "Success" } else { "Failed" }
ExitCode = $result.ExitCode
}
}
else {
$results += [PSCustomObject]@{
Computer = $computer
Status = "Unreachable"
ExitCode = $null
}
}
}
catch {
$results += [PSCustomObject]@{
Computer = $computer
Status = "Error"
ExitCode = $_.Exception.Message
}
}
}
return $results
}
# Usage
$computers = @("Server01", "Server02", "Workstation01", "Workstation02")
$deployResults = Deploy-Software -ComputerNames $computers -InstallerPath "C:\Software\MyApp.msi"
$deployResults | Export-Csv "C:\Reports\DeploymentResults.csv" -NoTypeInformation
Error Handling and Logging
Robust Error Handling:
function Invoke-SafeOperation {
[CmdletBinding()]
param(
[string]$Operation,
[scriptblock]$ScriptBlock,
[string]$LogPath = "C:\Logs\Operations.log"
)
$startTime = Get-Date
try {
Write-Log "Starting operation: $Operation" -LogPath $LogPath
# Execute the operation
$result = & $ScriptBlock
$duration = (Get-Date) - $startTime
Write-Log "Operation '$Operation' completed successfully in $($duration.TotalSeconds) seconds" -LogPath $LogPath
return $result
}
catch {
$duration = (Get-Date) - $startTime
$errorMessage = "Operation '$Operation' failed after $($duration.TotalSeconds) seconds. Error: $($_.Exception.Message)"
Write-Log $errorMessage -LogPath $LogPath -Level "ERROR"
# Optionally re-throw the error
throw $errorMessage
}
}
function Write-Log {
param(
[string]$Message,
[string]$LogPath,
[ValidateSet("INFO", "WARNING", "ERROR")]
[string]$Level = "INFO"
)
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logEntry = "$timestamp [$Level] $Message"
# Ensure log directory exists
$logDir = Split-Path $LogPath -Parent
if (!(Test-Path $logDir)) {
New-Item -ItemType Directory -Path $logDir -Force
}
# Write to log file
Add-Content -Path $LogPath -Value $logEntry
# Also output to console with color coding
$color = switch ($Level) {
"INFO" { "Green" }
"WARNING" { "Yellow" }
"ERROR" { "Red" }
}
Write-Host $logEntry -ForegroundColor $color
}
# Usage examples
$result = Invoke-SafeOperation -Operation "System Cleanup" -ScriptBlock {
Get-ChildItem "C:\Temp" | Remove-Item -Recurse -Force
Get-ChildItem "C:\Windows\Temp" | Remove-Item -Recurse -Force
}
Invoke-SafeOperation -Operation "Service Restart" -ScriptBlock {
Restart-Service -Name "Spooler" -Force
}
Comprehensive Administration Framework:
# Complete administrative framework
class AdminFramework {
[string]$LogPath
[hashtable]$Config
AdminFramework([string]$ConfigPath) {
$this.Config = Get-Content $ConfigPath | ConvertFrom-Json -AsHashtable
$this.LogPath = $this.Config.LogPath
}
[void] WriteLog([string]$Message, [string]$Level = "INFO") {
$timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$logEntry = "$timestamp [$Level] $Message"
Add-Content -Path $this.LogPath -Value $logEntry
$color = switch ($Level) {
"INFO" { "Green" }
"WARNING" { "Yellow" }
"ERROR" { "Red" }
}
Write-Host $logEntry -ForegroundColor $color
}
[PSObject] InvokeOperation([string]$Name, [scriptblock]$Operation) {
$this.WriteLog("Starting operation: $Name")
$startTime = Get-Date
try {
$result = & $Operation
$duration = (Get-Date) - $startTime
$this.WriteLog("Operation '$Name' completed in $($duration.TotalSeconds) seconds")
return @{
Success = $true
Result = $result
Duration = $duration
}
}
catch {
$duration = (Get-Date) - $startTime
$this.WriteLog("Operation '$Name' failed: $($_.Exception.Message)", "ERROR")
return @{
Success = $false
Error = $_.Exception.Message
Duration = $duration
}
}
}
[void] GenerateReport() {
$report = @{
Timestamp = Get-Date
ComputerName = $env:COMPUTERNAME
SystemInfo = Get-ComputerInfo | Select-Object WindowsProductName, WindowsVersion, TotalPhysicalMemory
DiskSpace = Get-WmiObject Win32_LogicalDisk | Select-Object DeviceID, @{Name="FreeSpaceGB";Expression={[math]::Round($_.FreeSpace/1GB,2)}}
Services = Get-Service | Group-Object Status | Select-Object Name, Count
Processes = Get-Process | Sort-Object WorkingSet -Descending | Select-Object -First 10 Name, WorkingSet
}
$reportPath = "C:\Reports\SystemReport_$(Get-Date -Format 'yyyyMMdd_HHmm').json"
$report | ConvertTo-Json -Depth 3 | Out-File $reportPath
$this.WriteLog("Generated system report: $reportPath")
}
}
# Configuration file (config.json)
$config = @{
LogPath = "C:\Logs\AdminFramework.log"
ReportPath = "C:\Reports"
EmailSettings = @{
SMTPServer = "mail.company.com"
From = "admin@company.com"
To = @("manager@company.com")
}
} | ConvertTo-Json
$config | Out-File "C:\Scripts\config.json"
# Usage
$admin = [AdminFramework]::new("C:\Scripts\config.json")
$result = $admin.InvokeOperation("System Cleanup", {
Get-ChildItem "C:\Temp" | Remove-Item -Recurse -Force
})
$admin.GenerateReport()
This comprehensive scripting and automation framework provides the foundation for building sophisticated administrative solutions that can scale with your environment and requirements.
Summary and Implementation Roadmap

Congratulations! You now possess comprehensive PowerShell administration skills that can transform your Windows management from manual, time-consuming tasks to automated, efficient operations. Let’s create your personalized implementation strategy:
Core Competencies Mastered:
- PowerShell Fundamentals: Command syntax, help system, and object-oriented approach
- File and User Management: NTFS permissions, Active Directory operations, and bulk processing
- System Monitoring: Performance tracking, event log analysis, and health reporting
- Network Administration: Configuration management, troubleshooting, and security
- Security Management: Permissions, certificates, auditing, and hardening
- Automation Excellence: Scripting, modules, scheduled tasks, and remote management
Essential Commands Quick Reference:
- Get-Help: Your learning companion for any command
- Get-Command: Discover available cmdlets and functions
- Get-Service/Get-Process: Monitor system components
- Get-ADUser/Set-ADUser: Manage user accounts
- Get-Acl/Set-Acl: Handle permissions and security
- Invoke-Command: Execute remote operations
- Get-WinEvent: Monitor and analyze system events
30-Day Mastery Implementation Plan:
Week 1: Foundation and Basic Operations
- Set up PowerShell environment and execution policies
- Master help system and command discovery
- Practice basic file operations and navigation
- Learn fundamental object manipulation and pipeline usage
- Goal: Comfortable with PowerShell interface and basic administration
Week 2: User and System Management
- Implement user account management workflows
- Practice service and process monitoring
- Learn registry operations and system information gathering
- Set up basic permission management procedures
- Goal: Efficient daily administrative task management
Week 3: Network and Security Administration
- Master network configuration and troubleshooting commands
- Implement security auditing and monitoring procedures
- Practice certificate management and firewall configuration
- Develop security hardening scripts
- Goal: Comprehensive network and security management capabilities
Week 4: Automation and Advanced Features
- Create reusable functions and modules
- Implement scheduled tasks and automated maintenance
- Practice remote administration and bulk operations
- Develop error handling and logging frameworks
- Goal: Fully automated administrative workflows
Environment-Specific Implementation Strategies:
Small Business (1-50 computers):
- Focus on local user management and basic automation
- Implement file server permission management
- Create simple monitoring and maintenance scripts
- Use scheduled tasks for regular maintenance
Medium Enterprise (50-500 computers):
- Implement Active Directory management workflows
- Develop centralized monitoring and reporting systems
- Create standardized deployment and configuration scripts
- Use remote administration for bulk operations
Large Enterprise (500+ computers):
- Build comprehensive automation frameworks
- Implement advanced security monitoring and compliance reporting
- Develop module libraries for consistent administration
- Create sophisticated remote management and deployment systems
Skill Development Progression:
Months 1-3: Operational Proficiency
- Master daily administrative tasks
- Develop personal script library
- Implement basic automation workflows
- Build confidence with core commands
Months 4-6: Advanced Automation
- Create sophisticated administrative functions
- Implement comprehensive monitoring systems
- Develop error handling and logging frameworks
- Build reusable module libraries
Months 7-12: Expert-Level Administration
- Design enterprise-scale automation solutions
- Implement advanced security and compliance frameworks
- Mentor others in PowerShell administration
- Contribute to organizational PowerShell standards
Return on Investment Metrics: Track these benefits to quantify your PowerShell mastery:
- Time Savings: 60-80% reduction in routine administrative tasks
- Accuracy Improvement: 90%+ reduction in manual errors
- Consistency: 100% standardized administrative procedures
- Scalability: Ability to manage 10x more systems efficiently
- Documentation: Automatic logging and reporting of all administrative actions
Continuous Learning Resources:
- Microsoft Documentation: docs.microsoft.com/powershell
- PowerShell Gallery: powershellgallery.com for community modules
- GitHub: github.com/powershell for source code and examples
- Community Forums: reddit.com/r/PowerShell and PowerShell.org
- Training: Microsoft Learn PowerShell learning paths
Best Practices for Long-Term Success:
- Start simple and build complexity gradually
- Always test scripts in non-production environments first
- Implement proper error handling and logging from the beginning
- Document your scripts and functions thoroughly
- Share knowledge with team members and build organizational expertise
- Stay updated with new PowerShell features and best practices
Common Pitfalls to Avoid:
- Rushing into complex scripts without mastering fundamentals
- Neglecting proper error handling and logging
- Not testing scripts thoroughly before production use
- Failing to implement security best practices in automation
- Over-engineering solutions when simple approaches work better
Your PowerShell administration journey transforms you from a reactive technician to a proactive automation expert. The skills you’ve learned enable you to manage Windows environments with unprecedented efficiency, consistency, and scalability.
Begin implementing these techniques today with simple tasks like user account management or system monitoring. As your confidence grows, expand into more complex automation and remote administration scenarios. Within 90 days of consistent practice, you’ll find yourself managing systems with a level of sophistication and efficiency that seemed impossible before mastering PowerShell.
The future of Windows administration is automation, and PowerShell is your key to that future. Start your transformation today!
コメント