3

I have a virtual hard disk .vhd file that I would like to backup on a daily basis by clicking on a shortcut on my Windows Vista laptop. I wrote a half-hazard batch script file (BACKUP.BAT) which accomplishes the job, where it open the cmd window and copies the file to the flash drive, but I would like to mimic (macro) the way the copying is displayed when you manually drag and drop the file into the flash drive in my computer. Another problem is that depending on what computer this is done, the USB flash drive could have drive E: assigned to it (WinXP) and on other computers (Vista/7) it could be drive F:. (There doesnt seem to be a way to statically assign a fixed drive letter to the USB flash drive when it is inserted into the USB port.)

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
Joe R.
  • 2,032
  • 4
  • 36
  • 72

2 Answers2

3

I would set the volume name of the disc, and examine all connected drives and find the drive with that volume name. Here's how I do it in PowerShell:

param([parameter(mandatory=$true)]$VolumeName,
      [parameter(mandatory=$true)]$SrcDir)

# find connected backup drive:
$backupDrive = $null
get-wmiobject win32_logicaldisk | % {
    if ($_.VolumeName -eq $VolumeName) {
        $backupDrive = $_.DeviceID
    }
}
if ($backupDrive -eq $null) {
    throw "$VolumeName drive not found!"
}

# mirror 
$backupPath = $backupDrive + "\"
& robocopy.exe $SrcDir $backupPath /MIR /Z
Michael Kelley
  • 3,579
  • 4
  • 37
  • 41
  • @Michael: Your method seems more reliable, than Romans example below, as I have a flash drive for each working day of the week (labeled: BACKUP_MON, BACKUP_TUE...) It would be really clever if I could check to see if the user inserted the correct flash drive depending on the day of the week!.. does robocopy.exe perform a copy with a drag-n-drop display of the copy in progress? Do I place this powershell script in notepad, save it with a .BAT extension and execute it?..Im not familiar with powershell. – Joe R. Jun 28 '11 at 03:55
  • @Michael: the file I want to copy is always located in C:\Users\Frank\My Documents\My Virtual Machines\example.vhd and I want to copy example.vhd into the corresponding flash drive. I have 6 flash drives, one for each working day, BACKUP_MON, BACKUP_TUE ... – Joe R. Jun 28 '11 at 04:05
  • 1
    `robocopy` does show progress percentage of copying a file but not in the way Windows does, percentage is displayed in the console window. Note: `robocopy` is not pre-installed on Windows XP. – Roman Kuzmin Jun 28 '11 at 04:43
  • is it possible to record a macro when I manually drag and drop the source file (.vhd) to the destination (flash drive labeled 'BACKUP'), then play the macro in powershell?.. This is not an absolute necessity, I just thought it would be cosmetically neat for the end-user to see it being executed the same way as if they manually do it. I'm trying to automate this backup because on several ocassions, my end-users dragged and dropped in the wrong direction and accidentally clobbered a whole days work with an older backup! – Joe R. Jun 28 '11 at 04:55
  • @Michael: I tested the example script above and it failed. For example, my source to be copied will always be located in D:\vpc2007\vhd\example.vhd and destination will always be a USB flash drive labeled 'BACKUP' so can I set a global environment variable for this location and plug it into the script? Also, this is for a standalone desktop computer (not networked). Why does robocopy have 'e:\shared\'? – Joe R. Jun 28 '11 at 05:47
  • I edited the example powershell so that you have to pass in the VolumeName and the source directory (SrcDir). If you run it through the PowerShell ISE, it'll show dialog boxes asking for these parameters. If you run it from a powershell cmd prompt, it'll complain about missing parameters. – Michael Kelley Jun 28 '11 at 20:33
2

This code gets the last ready to use removable drive (e.g. an USB drive just plugged-in):

$drives = [System.IO.DriveInfo]::GetDrives()
$r = $drives | Where-Object { $_.DriveType -eq 'Removable' -and $_.IsReady }
if ($r) {
    return @($r)[-1]
}
throw "No removable drives found."

This way does not require the fixed volume name to be pre-set. We can use different USB drives without knowing/setting their names.


UPDATE To complete drag-and-drop part of the task you can do this.

Create the PowerShell script (use Notepad, for example) C:\TEMP_110628_041140\Copy-ToRemovableDrive.ps1 (the path is up to you):

param($Source)

$drives = [System.IO.DriveInfo]::GetDrives()
$r = $drives | Where-Object { $_.DriveType -eq 'Removable' -and $_.IsReady }
if (!$r) {
    throw "No removable drives found."
}

$drive = @($r)[-1]
Copy-Item -LiteralPath $Source -Destination $drive.Name -Force -Recurse

Create the file Copy-ToRemovableDrive.bat (for example on your desktop), it uses the PowerShell script:

powershell -file C:\TEMP\_110628_041140\Copy-ToRemovableDrive.ps1 %1

Now you can plug your USB drive and drag a file to the Copy-ToRemovableDrive.bat icon at your desktop. This should copy the dragged file to the just plugged USB drive.

Roman Kuzmin
  • 40,627
  • 11
  • 95
  • 117
  • **Caveat**: Presumably, this approach may not work as expected (the goal is to use the last plugged drive) if there are several removable drives used **simultaneously** and plugged and unplugged randomly. In this scenario the last plugged drive will not be returned by this code in some plug/unplug sequences. – Roman Kuzmin Jun 28 '11 at 03:41
  • @Roman: OK, now can you complete your powershell script to copy C:\Users\Frank\My Documents\My Virtual Machines\example.vhd to the most recently inserted USB flash drive and display the copy execution the way Vista shows it when you drag and drop the .vhd into the flash drive?.. I was under the impresion one could pre-define an environment variable for the flash drive and statically set a permanent drive letter for it, no matter how many other USB devices are pluged in or out.. I dont understand why windows keps reassigning different drive letters. – Joe R. Jun 28 '11 at 03:44
  • @Roman: Im not experienced with powershell, just DOS BAT scripts.. Do I enter the your powershell script into a notepad, save it with a .BAT extension and then execute it? – Joe R. Jun 28 '11 at 03:47
  • See the updated answer. If you use USBs with known volume names then use the solution provided by @Michael Kelley – Roman Kuzmin Jun 28 '11 at 04:11
  • I dont understand, can I just create a shortcut to the .ps1 ? Im also thinking it might be better for the powershell script to seach for the appropiate label on the flash drive, since I can assign a permanent label for each one of the six flash drives I rotate for backups, rather than chance your caveat. if today is Monday, then I plug in flash drive labeled BACKUP_MON. Is there a way the ps script can obtain the day of the week and only perform the backup if the correct flash drive is connected? Im also assuming powershell doesnt work on WinXP machines? – Joe R. Jun 28 '11 at 04:20
  • @Frank Computer, you have changed the question and the task in your comments. It might be better if you open another well defined question for this. Otherwise it's going to be messy in here. – Roman Kuzmin Jun 28 '11 at 04:24
  • PowerShell is not pre-installed on Windows XP. Make sure you have it installed and its execution policy set appropriately. – Roman Kuzmin Jun 28 '11 at 04:30
  • sorry, perhaps because of my inexperience in explaining this.. perhaps I should just settle for labeling all six flash drives with the same name 'BACKUP' and physically marking with indelible ink each flash drive with the day of the week!.. I have different computers that need this backup done, some are WinXP, others are Vista and 7. Does powershell work on XP? – Joe R. Jun 28 '11 at 04:31