PowerShell: Windows Systems State Backup Daily

# Windows-Systems-State-Backup-V0.1.ps1
# What this script does:
# 1. Create a Windows Scheduled task on an Active Directory controller to perform daily backups at a predetermined time
# 2. Output a log to include backup duration and result of last backup
# 3. Remove backup files that are outside of the retention period
# Requirements:
# Powershell 3.0 is necessary to avoid this error, "the term 'Register-ScheduledJob' is not recognized as the name of a cmdlet"

# Set variables:
$taskName="System State Backup";
$pdcServer=(Get-ADForest |Select-Object -ExpandProperty RootDomain |Get-ADDomain |Select-Object -Property PDCEmulator).PDCEmulator;

# Optional: obtain a domain admin service account credentials
$prompt = "Username and Password of Domain Admin"
$cred = $Host.UI.PromptForCredential("Credential",$prompt,"$env:userdomain\$env:username",$env:userdomain)

# Ensure that uncPath has a trailing backslash
if ($storageUncPath[$storageUncPath.length-1] -ne "\"){$storageUncPath+="\";}

Function createBackupScheduledTask{
$taskName="System State Backup",

Function removeBackupScheduledTask{
$taskName="System State Backup"
Unregister-ScheduledTask $taskname -confirm:$false -ErrorAction SilentlyContinue
Write-Host "Taskname $taskName is deleted."
$checkJob=Get-ScheduledJob $taskname -ErrorAction SilentlyContinue #This command updates the metadata related to deleted task to fully void its remnants

$backupScheduledTask=Get-ScheduledTask $taskName -ErrorAction SilentlyContinue
if ($backupScheduledTask){write-host "$taskName already exists. Program will now remove the previous task instance.";removeBackupScheduledTask;}

Do {
$taskCreated=Register-ScheduledJob -ErrorAction Stop -Name $taskName -ScriptBlock{

# Start a timer

# Setup backup storage location
$dateStamp=Get-Date -Format yyyy-MM-dd;
New-Item -ItemType Directory $dateStampedFolder -Force;
$backupStorageLocation = New-WBBackupTarget -Network $dateStampedFolder;

# Instantiate a new policy
$thisPolicy = New-WBPolicy;

#Add System State to the policy
Add-WBSystemState -Policy $thisPolicy;

#Add backup location to policy
Add-WBBackupTarget -Policy $thisPolicy -Target $backupStorageLocation;

#Start backup using policy
Start-WBBackup -Policy $thisPolicy;

# Cleanup folders that are outside of retention period
if($backupDirectory -ne $null){
$expiredFolders=(get-childitem $backupDirectory|?{ $_.PSIsContainer }|?{$_.LastWriteTime -lt (get-date).AddDays(-$retentionDays)}|Select FullName).FullName;
$removedBackupSets = $expiredFolders|%{Remove-WBBackupSet -NetworkPath $_ -ComputerName $thisComputer -Force}
if($removedBackupSets){$expiredFolders|%{for ($i=0;$i -lt 2;$i++){try{remove-item -LiteralPath $_ -Force -Recurse}catch{}}};} #First pass, delete children; second pass, delete parent

#Append result into a log
#$lastBackupTime=(Get-WinEvent -LogName Microsoft-Windows-Backup -FilterXPath "*[System[EventID=4]]"|select -First 1).TimeCreated;
$lastBackupTime=(Get-WBBackupSet|select -last 1).BackupTime;
Add-Content $logFile "`r`n$lastBackupTime` --- $thisComputer backup completed in $hours hours.`r`n$removedBackupSets";
} -ScheduledJobOption $(New-ScheduledJobOption -RunElevated) -Trigger @{Frequency = $frequency; At=$time} -ArgumentList $storageUncPath,$retentionDays -Credential $cred;
if ($taskCreated){write-host "$taskName to run $frequency at $time has been successfully created.";};
write-host "Waiting 10 seconds for next retry...";
$checkJob=Get-ScheduledJob $taskname -ErrorAction SilentlyContinue;
sleep 10;
}while($taskCreated -eq $false)

#createBackupScheduledTask -taskName $taskName -storageUncPath $storageUncPath -frequency $frequency -time $executionTime -retention $retentionDays

invoke-command -Credential $cred -computername $pdcServer -scriptBlock{
} -Args ${function:createBackupScheduledTask},$taskName,$storageUncPath,$frequency,$executionTime,$retentionDays
}else{write-host "set pdcServer variable before proceeding"}


Sample execution result:

System State Backup already exists. Program will now remove the previous task instance.
Taskname System State Backup is deleted.
System State Backup to run Daily at 2:00AM has been successfully created.

Leave a Reply

Your email address will not be published. Required fields are marked *