Posted On November 19, 2019

PowerShell: Windows Systems State Backup Daily

kimconnect 0 comments
blog.KimConnect.com >> Windows >> 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";
$storageUncPath="\\Backups\ActiveDirectory\";
$frequency="Daily";
$executionTime="2:00AM";
$retentionDays=7;
$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{
param(
$taskName="System State Backup",
$storageUncPath,
$frequency="Daily",
$time="2:00AM",
$retentionDays=7,
$cred=$credential
)

Function removeBackupScheduledTask{
param(
$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 {
Try{
$taskCreated=Register-ScheduledJob -ErrorAction Stop -Name $taskName -ScriptBlock{
param($storageUncPath,$retentionDays)

# Start a timer
$timer=[System.Diagnostics.Stopwatch]::StartNew();

# Setup backup storage location
$backupDirectory=$storageUncPath;
$dateStamp=Get-Date -Format yyyy-MM-dd;
$logFile=$backupDirectory+"backup-log.txt";
$dateStampedFolder=$backupDirectory+$dateStamp;
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
$thisComputer=$env:computername;
if($backupDirectory -ne $null){
$expiredFolders=(get-childitem $backupDirectory|?{ $_.PSIsContainer }|?{$_.LastWriteTime -lt (get-date).AddDays(-$retentionDays)}|Select FullName).FullName;
}else{
$expiredFolders=$null;
}
if($expiredFolders){
$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;
$hours=[math]::Round(($timer.Elapsed.TotalSeconds)/3600,2);
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.";};
}
catch{
$taskCreated=$false;
write-host "Waiting 10 seconds for next retry...";
$checkJob=Get-ScheduledJob $taskname -ErrorAction SilentlyContinue;
sleep 10;
continue;
}
}while($taskCreated -eq $false)
}

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

if($pdcServer){
invoke-command -Credential $cred -computername $pdcServer -scriptBlock{
param($importedFunc,$variable1,$variable2,$variable3,$variable4,$variable5)
$credential=$using:cred
[ScriptBlock]::Create($importedFunc).invoke($variable1,$variable2,$variable3,$variable4,$variable5,$credential);
} -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 *

Related Post

How to Use QRadar to Search for a Windows Account Activities

Log into https://qradar/console/qradar/jsp/QRadar.jsp Log Activity > Add Filter > Parameter=Username[Indexed] | Operator=Equals any of |…

Fix: Error”The security log on this system is full”

This may be followed by "The terminal server has exceeded the maximum number of allowed…

Resolving Active Directory Replication Issues

In Windows Active Directory 2008+ mode, Distributed File System Replication  (DFSR) succeeds the legacy File…
Other project: DragonCoin.com