USBStartupWatch.cmd

February 28, 2023

Wanting to create an easy way for a user  to backup their files to a USB drive with minimal interaction.

Though USB Safely Remove provides this ability, it is licensed software:

Inspired by this thread, that gave me most of the powershell script, created USBStartupWatch.cmd that will:

USBStartupWatch.cmd install:




<# : batch portion
@echo off & setlocal

if /i "%1"=="install" goto :INSTALL
if /i "%1"=="stop" goto :STOPPROCESS

TITLE %~F0
setlocal enabledelayedexpansion

for /f "tokens=2 delims=," %%a in ('tasklist /v /fo csv ^| findstr /i /c:"%~F0"') do (
set "PID=%%~a"
)
echo PID=%PID%

TITLE %date% %time%: %~F0
echo %date% %time%: %~F0 Begins PID=%PID%>C:\ENH\%~N0-%PID%.log
echo %date% %time%: watch C:\ENH\%~N0-%PID%.log for activity>>C:\ENH\%~N0-%PID%.log
echo @%~F0 STOP>C:\ENH\%~N0-%PID%-Stop.cmd
FOR /F "tokens=2,*" %%A IN ('REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v Desktop') DO SET desktopFolder=%%B
if EXIST "%~DPN0.ico" (
shortcut.exe /f:"%DesktopFolder%\Stop %~N0.lnk" /a:c /t:C:\ENH\%~N0-%PID%-Stop.cmd /i:"%~DPN0.ico"

) ELSE (
shortcut.exe /f:"%DesktopFolder%\Stop %~N0.lnk" /a:c /t:C:\ENH\%~N0-%PID%-Stop.cmd /i:"%SystemRoot%\system32\shell32.dll,26"
)

powershell -noprofile -noninteractive "iex (${%~f0} | out-string)">>C:\ENH\%~N0-%PID%.log
goto :EOF

:STOPPROCESS
set CHGCOLOR=Y
chgcolor 7 >nul
if ERRORLEVEL 1 set CHGCOLOR=N
if "%CHGCOLOR%"=="Y" chgcolor 7
cls

echo.
if "%CHGCOLOR%"=="Y" chgcolor 1F
echo Stopping %~F0
if "%CHGCOLOR%"=="Y" chgcolor 8
echo.
for /f "tokens=2 delims=-." %%A in ('dir %~DPN0-*.log /b') do set PID=%%A
echo PARENT PID=%PID%
taskkill /F /T /PID %PID%
FOR /F "tokens=2,*" %%A IN ('REG QUERY "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" /v Desktop') DO SET desktopFolder=%%B

del "%desktopfolder%\Stop %~N0.lnk"
echo.
echo.
if "%CHGCOLOR%"=="Y" chgcolor 27
echo Done.
if "%CHGCOLOR%"=="Y" chgcolor 7
echo.
timeout /t 5
del %~DPN0-*.log
del %~DPN0-*.cmd
exit /b

:INSTALL
cd /d "%~DP0"
set CHGCOLOR=Y
chgcolor 7 >nul
if ERRORLEVEL 1 set CHGCOLOR=N
if NOT EXIST C:\ENH md C:\ENH
if NOT EXIST C:\ENH goto :INSTALLERROR
if "%CHGCOLOR%"=="N" curl -s -k -L https://www.dropbox.com/s/w3gku9n67lquzuj/chgcolor.exe?dl=0 -o %TEMP%\chgcolor.exe>nul
if EXIST %TEMP%\chgcolor.exe C:\ENH /y & set CHGCOLOR=Y
if EXIST %~DP0chgcolor.exe C:\ENH /y & set CHGCOLOR=Y
if "%CHGCOLOR%"=="Y" chgcolor 7
cls
echo.
TITLE %~F0

REM Get current date and time in ISO 8601 format
for /f "delims=" %%i in ('powershell -command "& {get-date -format 'yyyy-MM-ddTHH:mm:ss.fffffff'}"') do set "datetime=%%i"

type "%~F0" >"C:\ENH\%~NX0"
echo CreateObject("Wscript.Shell").Run "" ^& WScript.Arguments(0) ^& "", 0, False> C:\ENH\RunHide.vbs

for /f "tokens=1,2" %%A in ('whoami /user') do set USER=%%A & set SID=%%B
echo ^<?xml version="1.0" encoding="UTF-16"?^> >%TEMP%\%~N0.xml
echo ^<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task"^> >>%TEMP%\%~N0.xml
echo ^<RegistrationInfo^> >>%TEMP%\%~N0.xml
echo ^<Date^>%datetime%^</Date^> >>%TEMP%\%~N0.xml
echo ^<Author^>Bryan Keadle^</Author^> >>%TEMP%\%~N0.xml
echo ^<Description^>If USBStartup.cmd exist at the root of a USB drive being inserted, launch it.^</Description^> >>%TEMP%\%~N0.xml
echo ^<URI^>"C:\ENH\%~NX0"^</URI^> >>%TEMP%\%~N0.xml
echo ^</RegistrationInfo^> >>%TEMP%\%~N0.xml
echo ^<Triggers^> >>%TEMP%\%~N0.xml
echo ^<LogonTrigger^> >>%TEMP%\%~N0.xml
echo ^<Enabled^>true^</Enabled^> >>%TEMP%\%~N0.xml
echo ^</LogonTrigger^> >>%TEMP%\%~N0.xml
echo ^</Triggers^> >>%TEMP%\%~N0.xml
echo ^<Principals^> >>%TEMP%\%~N0.xml
echo ^<Principal id="Author"^> >>%TEMP%\%~N0.xml
echo ^<UserId^>%SID%^</UserId^> >>%TEMP%\%~N0.xml
echo ^<LogonType^>InteractiveToken^</LogonType^> >>%TEMP%\%~N0.xml
echo ^<RunLevel^>LeastPrivilege^</RunLevel^> >>%TEMP%\%~N0.xml
echo ^</Principal^> >>%TEMP%\%~N0.xml
echo ^</Principals^> >>%TEMP%\%~N0.xml
echo ^<Settings^> >>%TEMP%\%~N0.xml
echo ^<MultipleInstancesPolicy^>IgnoreNew^</MultipleInstancesPolicy^> >>%TEMP%\%~N0.xml
echo ^<DisallowStartIfOnBatteries^>true^</DisallowStartIfOnBatteries^> >>%TEMP%\%~N0.xml
echo ^<StopIfGoingOnBatteries^>false^</StopIfGoingOnBatteries^> >>%TEMP%\%~N0.xml
echo ^<AllowHardTerminate^>false^</AllowHardTerminate^> >>%TEMP%\%~N0.xml
echo ^<StartWhenAvailable^>false^</StartWhenAvailable^> >>%TEMP%\%~N0.xml
echo ^<RunOnlyIfNetworkAvailable^>false^</RunOnlyIfNetworkAvailable^> >>%TEMP%\%~N0.xml
echo ^<IdleSettings^> >>%TEMP%\%~N0.xml
echo ^<StopOnIdleEnd^>true^</StopOnIdleEnd^> >>%TEMP%\%~N0.xml
echo ^<RestartOnIdle^>false^</RestartOnIdle^> >>%TEMP%\%~N0.xml
echo ^</IdleSettings^> >>%TEMP%\%~N0.xml
echo ^<AllowStartOnDemand^>true^</AllowStartOnDemand^> >>%TEMP%\%~N0.xml
echo ^<Enabled^>true^</Enabled^> >>%TEMP%\%~N0.xml
echo ^<Hidden^>false^</Hidden^> >>%TEMP%\%~N0.xml
echo ^<RunOnlyIfIdle^>false^</RunOnlyIfIdle^> >>%TEMP%\%~N0.xml
echo ^<WakeToRun^>false^</WakeToRun^> >>%TEMP%\%~N0.xml
echo ^<ExecutionTimeLimit^>PT0S^</ExecutionTimeLimit^> >>%TEMP%\%~N0.xml
echo ^<Priority^>7^</Priority^> >>%TEMP%\%~N0.xml
echo ^</Settings^> >>%TEMP%\%~N0.xml
echo ^<Actions Context="Author"^> >>%TEMP%\%~N0.xml
echo ^<Exec^> >>%TEMP%\%~N0.xml
echo ^<Command^>c:\enh\RunHide.vbs^</Command^> >>%TEMP%\%~N0.xml
echo ^<Arguments^>"C:\ENH\%~NX0"^</Arguments^> >>%TEMP%\%~N0.xml
echo ^</Exec^> >>%TEMP%\%~N0.xml
echo ^</Actions^> >>%TEMP%\%~N0.xml
echo ^</Task^> >>%TEMP%\%~N0.xml
schtasks /create /tn "\KeadleWorks\%~NX0" /xml "%TEMP%\%~N0.xml"

:INSTRUCTIONS
echo.
if "%CHGCOLOR%"=="Y" chgcolor 1F
echo To test now, after editing the task, select the task, and select Run
echo.
echo Close Task Scheduler to continue
echo.
echo I'll now open Task Scheduler for you to edit the task as necessary
echo you will find it in the KeadleWorks folder under the Task Scheduler Library
echo.
if "%CHGCOLOR%"=="Y" chgcolor 1E
echo. Task = KeadleWorks\%~NX0
if "%CHGCOLOR%"=="Y" chgcolor 1E
echo.
pause
if "%CHGCOLOR%"=="Y" chgcolor 7
start /wait "" taskschd.msc /d "\KeadleWorks\"

cls
echo.
schtasks /Run /tn "\KeadleWorks\%~NX0"
echo.
if "%CHGCOLOR%"=="Y" chgcolor 27
echo Now, upon user login C:\ENH\USBAutoRunStartupWatch.cmd will launch (hidden)
echo and watch for USB connection events. When one occurs, and USBStartup.cmd exists
echo at the root of the drive, it will execute.
if "%CHGCOLOR%"=="Y" chgcolor 7
echo.
pause
goto :EOF

:SAVE
echo ^<Arguments^>"C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -NoExit -ExecutionPolicy Bypass -File C:\ENH\%~N0.ps1 >> C:\ENH\%~N0.log"^</Arguments^> >>%TEMP%\%~N0.xml

:INSTALLERROR
echo.
if "%CHGCOLOR%"=="Y" chgcolor 4F
echo ERROR!
echo Unable to create C:\ENH directory!
if "%CHGCOLOR%"=="Y" chgcolor 7
echo.
echo You must create C:\ENH and grant yourself (or users) rights to this directory
echo.
pause
goto :EOF

: end batch / begin PowerShell #>

## Powershell script below
#Requires -version 2.0
#Modified 01-18-2010: Use Any
#Driver Letter Volume Name: by J. Hill
Register-WmiEvent -Class win32_VolumeChangeEvent -SourceIdentifier volumeChange
Clear-Host
$host.ui.RawUI.WindowTitle = "USB Startup Watch"
write-host `n(get-date -format s) " Beginning script..."
do{
$newEvent = Wait-Event -SourceIdentifier volumeChange
$eventType = $newEvent.SourceEventArgs.NewEvent.EventType
$eventTypeName = switch($eventType)
{
1 {"Configuration Changed"}
2 {"Device Arrival"}
3 {"Device Removal"}
4 {"Docking"}
}

if ($eventTypeName -eq "Device Arrival") {
Write-Host "`n"
}

write-host (get-date -format s) " Event detected = " $eventTypeName
if ($eventType -eq 2)
{
$driveLetter = $newEvent.SourceEventArgs.NewEvent.DriveName
$driveLabel = ([wmi]"Win32_LogicalDisk='$driveLetter'").VolumeName
$driveType = ([wmi]"Win32_LogicalDisk='$driveLetter'").DriveType
write-host (get-date -format s) " Drive name = " $driveLetter
write-host (get-date -format s) " Drive label = " $driveLabel
# Execute process if drive matches specified condition(s)
if ($driveType -eq 2)
{
if (Test-Path $driveLetter"\USBStartUp.cmd") {
write-host (get-date -format s) " Starting task [$driveLetter\USBStartUp.cmd $driveletter] in 3 seconds..."
start-sleep -seconds 3
start-process -FilePath $driveLetter\USBStartUp.cmd -ArgumentList $driveletter -NoNewWindow
}
}
}
Remove-Event -SourceIdentifier volumeChange
} while (1-eq1) #Loop until next event
Unregister-Event -SourceIdentifier volumeChange

Download USBStartupWatch.zip


email: USBStartupWatch.cmd (at) keadle.net