Skip to content

Instantly share code, notes, and snippets.

@mathielo
Created April 18, 2025 05:34
Show Gist options
  • Save mathielo/bbae803848fd781c4a44be1b15f4ebdc to your computer and use it in GitHub Desktop.
Save mathielo/bbae803848fd781c4a44be1b15f4ebdc to your computer and use it in GitHub Desktop.
Auto Saves Backup for Windows

Auto Saves Backup for Windows (PowerShell)

Originally developed for Crashlands, this can be used for any game with the proper adjustments in the script.

❗ Disclaimer 🚨

Use this script at your own risk. Always back up your data before running. You are the sole responsible for the integrity of your data.

Instructions

  1. Download the PowerShell script and save it locally
  2. Right click the script > Create shortcut
  3. Now right click the SHORTCUT > Properties
  4. Update the shortcut's Target field to the following:
%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy Bypass -File "C:\path\to\Crashlands Auto Backup.ps1"

Make sure you changed the last bit of the line above (C:\path\to\Crashlands Auto Backup.ps1) to point to where your script is saved.

Running the script

Once the script starts, backups will be generated in the selected interval. There is a rotation system to delete old backups after a given threshold (default 5) to prevent bloating. Deleted files are sent to the Recycle Bin (just in case) and still need to be manually purged.

At any moment R is pressed, the script will prompt the user to confirm (y/N) whether they want to restore the latest backup. Upon confirming, the latest backup is restored and the script exits.

# This script automatically backs up the Crashlands save files on the selected interval.
# It also allows the user to restore the latest backup by pressing 'R' and confirming within 5 seconds.
#
# Backups are kept in a rotation, meaning only the latest 5 backups are kept. Older backups are sent to
# the Recycle Bin (not permanently deleted).
#
# The script will run indefinitely until the user presses Ctrl+C to exit, or until the user confirms a restore.
Add-Type -AssemblyName Microsoft.VisualBasic
# Configuration
# Change these variables to suit your needs
# The source directory is the location of the Crashlands save files.
$source = Join-Path $env:LOCALAPPDATA "Crashlands\Game"
# The backup directory is where the backups will be stored.
# The default is the Downloads folder, but you can change it to any directory you prefer.
$backupRoot = Join-Path $env:USERPROFILE "Downloads"
# The interval in minutes between backups.
$intervalMinutes = 2
# The maximum number of backups to keep. Older backups will be deleted.
$maxBackups = 5
function Send-ToRecycleBin {
param([string]$path)
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteDirectory($path, 'OnlyErrorDialogs', 'SendToRecycleBin')
}
function Backup {
$logTimestamp = Get-Date -Format "HH:mm:ss"
$timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
$backupPath = Join-Path $backupRoot "crashlands-$timestamp"
Copy-Item -Path $source -Destination $backupPath -Recurse
Write-Host "[$logTimestamp] Backup created at: $backupPath"
# Cleanup old backups
$backups = Get-ChildItem -Path $backupRoot -Directory | Where-Object { $_.Name -like "crashlands-*" } | Sort-Object Name -Descending
if ($backups.Count -gt $maxBackups) {
$toDelete = $backups[$maxBackups..($backups.Count - 1)]
foreach ($dir in $toDelete) {
Write-Host "Deleting old backup: $($dir.FullName)"
Send-ToRecycleBin -path $dir.FullName
}
}
}
function Restore-Latest {
$backups = Get-ChildItem -Path $backupRoot -Directory | Where-Object { $_.Name -like "crashlands-*" } | Sort-Object Name -Descending
if ($backups.Count -eq 0) {
Write-Host "No backups found to restore."
return
}
$latestBackup = $backups[0].FullName
Write-Host "`nRestoring from backup: $latestBackup..."
# Delete current contents
Get-ChildItem -Path $source | ForEach-Object {
if ($_.PSIsContainer) {
Send-ToRecycleBin $_.FullName
} else {
[Microsoft.VisualBasic.FileIO.FileSystem]::DeleteFile($_.FullName, 'OnlyErrorDialogs', 'SendToRecycleBin')
}
}
# Copy from backup
Copy-Item -Path "$latestBackup\*" -Destination $source -Recurse
Write-Host "Restore complete."
}
# Start backup loop with user input listener
Write-Host "Crashlands backup started. Press 'R' to restore the latest backup. Press Ctrl+C to exit."
$timer = [System.Diagnostics.Stopwatch]::StartNew()
while ($true) {
if ($timer.Elapsed.TotalMinutes -ge $intervalMinutes) {
Backup
$timer.Restart()
}
if ($Host.UI.RawUI.KeyAvailable) {
$key = $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
if ($key.Character -eq 'r' -or $key.Character -eq 'R') {
Write-Host "`nRestore latest backup? [y/N] (auto-cancel in 5s): " -NoNewline
$response = ''
$stopwatch = [System.Diagnostics.Stopwatch]::StartNew()
while ($stopwatch.Elapsed.TotalSeconds -lt 5) {
if ([Console]::KeyAvailable) {
$response = [Console]::ReadKey($true).KeyChar
break
}
Start-Sleep -Milliseconds 100
}
if ($response -eq 'y' -or $response -eq 'Y') {
Restore-Latest
Write-Host "`n`nRestore complete. Please restart the program to resume automatic backups."
Start-Sleep -Seconds 3
break
} else {
Write-Host "`nRestore canceled."
}
}
# Clear any leftover key presses
while ([Console]::KeyAvailable) {
[Console]::ReadKey($true) | Out-Null
}
}
Start-Sleep -Milliseconds 500
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment