Skip to content

Instantly share code, notes, and snippets.

@earthdiver
Created June 9, 2025 14:38
Show Gist options
  • Select an option

  • Save earthdiver/ebb1409fe6e9aabcb45e1612925abe4a to your computer and use it in GitHub Desktop.

Select an option

Save earthdiver/ebb1409fe6e9aabcb45e1612925abe4a to your computer and use it in GitHub Desktop.
backup_file_on_update.bat
@PowerShell -NoP -W Hidden -C "$PSCP='%~f0';$PSSR='%~dp0'.TrimEnd('\');&([ScriptBlock]::Create((gc '%~f0'|?{$_.ReadCount -gt 1}|Out-String)))" & exit/b
# by earthdiver1
if ($PSCommandPath) {
$PSCP = $PSCommandPath
$PSSR = $PSScriptRoot
$code = '[DllImport("user32.dll")]public static extern bool ShowWindowAsync(IntPtr hWnd,int nCmdShow);'
$type = Add-Type -MemberDefinition $code -Name Win32ShowWindowAsync -PassThru
[void]$type::ShowWindowAsync((Get-Process -PID $PID).MainWindowHandle,0) }
Add-Type -AssemblyName System.Windows.Forms, System.Drawing
$menuItem = New-Object System.Windows.Forms.MenuItem "Exit"
$menuItem.add_Click({$notifyIcon.Visible=$False;while(-not $status.IsCompleted){Start-Sleep 1};$appContext.ExitThread()})
$contextMenu = New-Object System.Windows.Forms.ContextMenu
$contextMenu.MenuItems.AddRange($menuItem)
$notifyIcon = New-Object System.Windows.Forms.NotifyIcon
$notifyIcon.ContextMenu = $contextMenu
$notifyIcon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($PSCP)
$notifyIcon.Text = (Get-ChildItem $PSCP).BaseName
$notifyIcon.Visible = $True
$_syncHash = [hashtable]::Synchronized(@{})
$_syncHash.NI = $notifyIcon
$_syncHash.PSCP = $PSCP
$_syncHash.PSSR = $PSSR
$runspace = [RunspaceFactory]::CreateRunspace()
$runspace.ApartmentState = "STA"
$runspace.ThreadOptions = "ReuseThread"
$runspace.Open()
$runspace.SessionStateProxy.SetVariable("_syncHash",$_syncHash)
$scriptBlock = Get-Content $PSCP | ?{ $on -or $_[1] -eq "!" }| %{ $on=1; $_ } | Out-String
$action=[ScriptBlock]::Create(@'
# param($Param1, $Param2)
Start-Transcript -LiteralPath ($_syncHash.PSCP -Replace '\..*?$',".log") -Append
Function Start-Sleep { [CmdletBinding(DefaultParameterSetName="S")]
param([parameter(Position=0,ParameterSetName="M")][Int]$Milliseconds,
[parameter(Position=0,ParameterSetName="S")][Int]$Seconds,[Switch]$NoExit)
if ($PsCmdlet.ParameterSetName -eq "S") {
$int = 5
for ($i = 0; $i -lt $Seconds; $i += $int) {
if (-not($NoExit -or $_syncHash.NI.Visible)) { exit }
Microsoft.PowerShell.Utility\Start-Sleep -Seconds $int }
} else {
$int = 100
for ($i = 0; $i -lt $Milliseconds; $i += $int) {
if (-not($NoExit -or $_syncHash.NI.Visible)) { exit }
Microsoft.PowerShell.Utility\Start-Sleep -Milliseconds $int }}}
$script:PSCommandPath = $_syncHash.PSCP
$script:PSScriptRoot = $_syncHash.PSSR
'@ + $scriptBlock)
$PS = [PowerShell]::Create().AddScript($action) #.AddArgument($Param1).AddArgument($Param2)
$PS.Runspace = $runspace
$status = $PS.BeginInvoke()
$appContext = New-Object System.Windows.Forms.ApplicationContext
[void][System.Windows.Forms.Application]::Run($appContext)
exit
#! ---------- ScriptBlock (Line No. 28) begins here ---------- DO NOT REMOVE THIS LINE
###################################################################################################################################
$src_file = "C:\:somedir\important_file.doc"
$dst_dir = "D:\backup"
$num_copy = 20
$interval_1 = 180
$interval_2 = 15
###################################################################################################################################
$ErrorActionPreference = "Stop"
while ( -not (Test-Path $dst_dir) ) { Write-Output "$(Get-Date) Waiting..."; Start-Sleep 15 }
$old_mtime = ""
$old_hash = ""
while ( $true ) {
try {
$file = Get-Item -Path $src_file
$new_mtime = $file.LastWriteTime.ToString('yyyyMMddHHmm')
if ( $new_mtime -ne $old_mtime ) {
$new_hash = $file.GetHashCode()
if ( $new_hash -ne $old_hash ) {
$dst_file = Join-Path $dst_dir ($file.BaseName + "_" + $new_mtime + $file.Extension)
if ( -not ( Test-Path $dst_file ) ) {
Copy-Item -LiteralPath $file.FullName -Destination $dst_file -Force
$filter = $file.BaseName + "_????????????" + $file.Extension
Get-ChildItem -LiteralPath $dst_dir -Filter $filter | Sort-Object | Select-Object -SkipLast $num_copy | Remove-Item -Force
}
$old_hash = $new_hash
}
$old_mtime = $new_mtime
}
$interval = $interval_1
} catch [System.Exception] {
Write-Output $Error[0].ToString() $Error[0].InvocationInfo.PositionMessage
$interval = $interval_2
}
Start-Sleep $interval
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment