You are here

IMPROVED: Howto: Safely remove USB Drive from batch file

23 posts / 0 new
Last post
Anonymous (not verified)
IMPROVED: Howto: Safely remove USB Drive from batch file

EDIT 3: Much better version posted later on at https://portableapps.com/node/639#comment-2238

EDIT: Updated scripts, fully working with autorun and no dos boxes are in my reply below.

EDIT 2: This doesn't work from a limited account, but doesn't cause any problems, it just won't automatically unmount if you aren't an administrator.

I don't know if this has been discussed before, I'm kind of new here, but I found a nice little way to safely remove your USB drive, without navagating through the menus in windows XP. AFAIK this will only work on WinXP, not 95/98, though I haven't tested them.

Credits to http://ask-leo.com/is_there_a_way_to_safely_remove_hardware_from_a_batch... which is where I found part of this solution.

First, get devcon from http://support.microsoft.com/?kbid=311272 This is a command line device management program.

Extract it somewhere, and run:

devcon status *

This will list all the devices on your computer. What you are looking for is usually the USB Mass Storage Device. It should be whatever the TOP line is on the screen to safely remove hardware.

In my case I get this:


USB\VID_0781&PID_7113\0001162825
Name: USB Mass Storage Device
Driver is running.

Now see if you can remove it with this line:


devcon remove "USB\VID_0781&PID_7113"

(note the quotes around the device string, and the last section cut off. Not sure why but it only works without that part)

Now you need to make two little batch files:

startmenu.bat

pstart.exe
copy devcon.exe %temp%
copy remove.bat %temp%
c:
ping -n 5 127.0.0.1
start %temp%\remove.bat

remove.bat

%temp%\devcon remove "USB\VID_0781&PID_7113"
del %temp%\remove.bat

How this works:

You run startmenu.bat. PStart pops up. Once you close PStart, it copies devcon and the remove.bat files to the temp directory. It switches to the c: drive so that it isn't holding the flash drive open, uses ping to wait 5 seconds, then runs remove.bat

Remove.bat dismounts the flash drive, then delete's itself, leaving no traces on the system.

It seems that it won't unmount the drive if there are any files still open on it, which is a good thing IMHO. But if your programs crash or something it may not unmount automatically.

I'm now trying to figure out a way to make the dos window not show up. I'll post here if I figure that out.

Rob Loach
Rob Loach's picture
Offline
Last seen: 15 years 7 months ago
Developer
Joined: 2005-12-09 17:29
Interesting

That's pretty neat. Would "USB\VID_0781&PID_7113" change from computer to computer? It would be nice to have devcon somehow return that USB string.

I also noticed that you arn't deleting devcon.exe from the temporary directory in remove.bat after you use it...

Rob Loach [Website] [Projects]

grantemsley (not verified)
the device string is the

the device string is the hardware ID for the device, so it wont change.

and I forgot to delete devcon.exe...oops.

I've just figured out how to get it to run, with a nice autorun.inf file (won't automatically launch but at least it pops up a menu and you just have to hit enter), and no dos windows appearing. Here's what I have:

Directory structure:

\autorun.inf
\Programs\pstart.exe
\Programs\devcon.exe
\Programs\startmenu.bat
\Programs\startmenu.vbs
\Programs\remove.bat

Autorun.inf:

[autorun]
shellexecute=Programs\startmenu.vbs
icon=Programs\PStart.exe
action=Launch PStart Menu

Startmenu.bat:

\programs\pstart.exe
ping -n 2 127.0.0.1
copy \programs\devcon.exe %temp%
copy \programs\remove.bat %temp%
c:
start /b %temp%\remove.bat

Startmenu.vbs:

Set WshShell = WScript.CreateObject("WScript.Shell")
Runstring = "%comspec% /c programs\startmenu.bat"
Return = WshShell.Run(RunString, 0, TRUE)
Set WshShell = Nothing

Remove.bat:

%temp%\devcon remove "USB\VID_0781&PID_7113"
del %temp%\devcon.exe
del %temp%\remove.bat

The vbs script launches the batch file without showing a dos window, so all you ever see is the pstart menu. I also changed it to only wait 2 seconds before dismounting, and fixed it so that it deletes the two files copied to the temp dir.

All you should have to do is change the line in remove.bat to whatever the device id for your flash drive is, and change the paths to your liking.

nm35
Offline
Last seen: 17 years 6 months ago
Developer
Joined: 2005-12-12 17:13
Interesting, but isn't it a

Interesting, but isn't it a little overkill?

~nm35

mexter (not verified)
There's no kill like

There's no kill like overkill. Smile I'll have to try this oen out myself, since disconnecting the drive can be a horrific task at times. Still in use indeed...

- me -

grantemsley (not verified)
Its not overkill to me.

Its not overkill to me. I've lost a flash drive before from not disconnecting it properly...actually killed the DRIVE, not just the data. So to have it automatically shut it off in case I prevent is a good thing Smile

azjerry
Offline
Last seen: 6 years 6 months ago
Joined: 2005-12-09 12:42
one minor annoyance

ON XP SP2 every time I plug in the USB drive using this scheme it goes through the popups about finding and installing a new drive. It didn't do that when my autorun just started PStart.

OK... 2 annoyances...
On XP SP2 I have to OK the default action (start PStart) before it runs. On XP SP1 (which I have at work) PStart starts automatically.
I realize this is really an SP2 issue, just had to rant.

John T. Haller
John T. Haller's picture
Online
Last seen: 9 min 56 sec ago
AdminDeveloperModeratorTranslator
Joined: 2005-11-28 22:21
I'd rather it asked

more secure. that way if you're pluggin in something you're not sure of, it won't autorun.

CDs should do that by default, too.

Sometimes, the impossible can become possible, if you're awesome!

azjerry
Offline
Last seen: 6 years 6 months ago
Joined: 2005-12-09 12:42
True but...

You're right, it does add that extra bit of security and it's not that hard to just hit Enter.

Now that I think about it, if I could just get it to stop scanning the entire drive first each time I plug it in. Just ask me about running PStart.

azjerry
Offline
Last seen: 6 years 6 months ago
Joined: 2005-12-09 12:42
cmd process left running

I noticed that each time I exit Pstart and the USB is removed by devcon, a cmd.exe process is left running.

grantemsley (not verified)
Hmm...I think that would

Hmm...I think that would have something to do with the .bat/.vbs files no longer being accessible. But I'm not sure how to fix that. Perhaps someone around here has some better experiece with VBScript than I do.

azjerry
Offline
Last seen: 6 years 6 months ago
Joined: 2005-12-09 12:42
expand capabilities?

I'm trying to expand on the capabilities of your technique. I'd like to be able to:

1. Automatically start multiple programs. This can be done by having PStart start selected portable apps when it starts. So far, so good.

2. When exiting PStart and, therefore, automatically removing the USB drive, first end all the programs that were automatically started. I tried using pskill from sysinternals to kill the process but haven't been able to get the USB drive removed. That's how I found the leftover cmd process. This could really use a command line tool to gracefully close (not kill) the programs.

grantemsley (not verified)
taskkill /im .exe This will

taskkill /im .exe

This will terminate the program gracefully (as to save changes and such). It's a part of windows, so no extra programs are needed. If you wanted to forcefully close the program, add the /f switch.

azjerry
Offline
Last seen: 6 years 6 months ago
Joined: 2005-12-09 12:42
Thanks

I'd been using Win2k for so long at my last job that I forgot about the XP specific tools. I expanded on this a bit with a batch file that first tries /im and, if the process is still running, does a /f /im:

@echo off
rem Ends a running task by attempting a gracefull close of the program. If
rem that fail then the process is terminated.

tasklist | findstr /b /i "%1"
if errorlevel 1 goto end
taskkill /t /im %1

tasklist | findstr /b /i "%1"
if errorlevel 1 goto end
taskkill /f /t /im %1

:end

grantemsley (not verified)
Better Version

I've made a VERY MUCH IMPROVED version. It won't leave any cmd.exe processes running, and adds a couple other handy features. Its pretty well commented so it should be easy to adjust to your needs.

Make an autorun.inf file to start this (as in my original post)
It requires two other programs, URLS are listed near the top of the script. Put the files in the \programs directory, or modify the paths to your liking.

(code tags don't seem to want to work for some reason...)

START OF AUTORUN.VBS

' Name: autorun.vbs
' Author: Grant Emsley
' Date: Jan 28, 2006
'
' What it does:
'
' This script takes the full path/name of where the script was run from, strips off everything except the drive letter and colon, and sets it to the environmental variable "portabledrive". It sets this in the Volatile Environment so it will remain set between different programs, but gets cleared when you logout/reboot.
' This allows you to make all your shortcuts and such in the format: %portabledrive%\programs\programname\program.exe
' This means that most programs that have trouble with relative paths will work
' ---------------------------------------------------------
' Required Programs: deveject.exe (http://www.heise.de/ct/03/16/links/208.shtml)
' unmount.exe and mnt.exe (http://www.uwe-sieber.de/files/unmnt10.zip)
'
' These are required if you want to automatically "safely remove hardware"
' -----------------------------------------------------------

Dim objShell
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")

' -------------------------------------------------------------
' get the drive letter
arrPath = Split(Wscript.ScriptFullName, "\")
strdriveletter = arrPath(0)

' create a collection to access the Volatile environment, then set the portabledrive
set colVolatileEnvVars = objShell.Environment("Volatile")
colVolatileEnvVars("portabledrive") = strdriveletter

' ----------------------------------------------------------
' I have a folder called "Portable Documents" on my drive. Lets make a shortcut in "My Documents" to my portable documents folder. This way I can just click there on any save/open dialogue box.

strMyDocs = objShell.SpecialFolders("MyDocuments")
set objSLink = objShell.CreateShortcut(strMyDocs & "\Portable Documents.lnk")
objSLink.TargetPath = strdriveletter & "\Portable Documents"
objSlink.Save
' ----------------------------------------------------------------------------------------------------

' NOTE: if you want to run something before starting pstart, do it below this line. (guide to running programs is at the end of the script)

' Now lets run pstart, and wait for it to exit before we continue
objShell.Run strdriveletter & "\programs\pstart.exe", 1, TRUE

' NOTE: If you want to run something AFTER running pstart, do it below this line.

' Pstart is done, so lets clean up
' Delete the shortcut to Portable Documents
objFSO.DeleteFile(strMyDocs & "\Portable Documents.lnk")

' Safely remove hardware
' Probably won't work if you aren't an administrator
' it WONT work if you have open files on the drive (probably a good thing)
' Warn the user that we are going to dismount the drive
Wscript.Echo "Ready to remove portable drive. Please close all programs/files on the drive, then click ok."

' First we have to change the current directory so we aren't holding the drive open.
objShell.CurrentDirectory = "C:\"
' Now we copy the files to the c drive
objFSO.CopyFile strdriveletter & "\programs\unmount.exe", "c:\", true
objFSO.CopyFile strdriveletter & "\programs\mnt.exe", "c:\", true
objFSO.CopyFile strdriveletter & "\programs\deveject.exe", "c:\", true
' First we run unmount. It waits until all files are closed on the drive then removes the drive letter.
objShell.Run "c:\unmount -l -a -e " & strdriveletter, 1, TRUE

' Now we run deveject to unmount the drive.
' You will have to modify the following line to get this to work. Run deveject with no options and it will list all the devices that can be removed. Change the device ID to the one that's listed for your drive.
objShell.Run "c:\deveject -EjectId:""USB\VID_05E3&PID_0702\6&AC549B9&0&3""", 0, TRUE
' Then we clean up after ourselves
objFSO.DeleteFile("C:\unmount.exe")
objFSO.DeleteFile("C:\mnt.exe")
objFSO.DeleteFile("C:\deveject.exe")
Wscript.Echo "Your drive should be safely removed."

Wscript.Quit

' ----------------------------------------------------------------------------------------------------
' objShell.run , ,
'
' Some good window states:
' 0 - hidden
' 1 - normal
' 2 - minimized forground
' 3 - maximized
' 7 - minimized background
'
' The last parameter takes either true or false. If true, it pauses the script and waits for it to exit before continuing. Default is false.
' ----------------------------------------------------------------------------------------------------

END OF AUTORUN.VBS

azjerry
Offline
Last seen: 6 years 6 months ago
Joined: 2005-12-09 12:42
good job

Good job Grant. I'm using this. It even got me to organize my USB drive a bit, creating a Documents folder on it. I added a section to close down processes likely to be running from the drive per my earlier post in this thread.

nm35
Offline
Last seen: 17 years 6 months ago
Developer
Joined: 2005-12-12 17:13
Interesting... I don't know

Interesting... I don't know much about VBS, but won't apps like Norton AV block it? It tends to block my VBS scripts, claiming they're a "security hazard." (So much for "smart" security.)

~nm35 {blog} {standalone apps}

grantemsley (not verified)
AV programs might block it,

AV programs might block it, but most AV programs look inside .vbs scripts for certain commands (eg. a command to format your hard drive), and block it based on that. I don't think my script uses anything that would be blocked, but the only way to find out is to give it a try.

callit
Offline
Last seen: 15 years 5 months ago
Joined: 2006-02-11 00:02
Excellent work

Excellent work - two quick questions though, 1st - A console window pops up, is there any way to hide it? I'm not very familiar with VBS scripts. and 2nd, My USB drive unmounts, and is removed from the "Safely Remove" list, but the light on the drive remains lit - any thoughts?

EDIT: I just tried it on my laptop, and it works as expected. (Dialog boxes instead of console windows, device ejecting as it should) I'm not sure what the issue is on my PC.

iMartyr
Offline
Last seen: 14 years 6 months ago
Joined: 2006-02-11 11:33
sorry for endlessly plugging this...

(this is cyberpunksi login problems) The people over at www.autohotkey.com have a great tool, a script could be made into an exe! It could do all that this script does, it might even take care of the admin problem. No disrespect to your work i'm just trying to help inform of a possible solution. I think it is great that people with extra knowhow take time to make life easier for the rest of us!

opiwer678
Offline
Last seen: 11 years 9 months ago
Joined: 2006-05-20 12:18
Improvement: removedrive.exe (and kill.exe) and Windows 2000

Thanks for this script. I sure will enjoy it.

The script worked not properly on my windows 2000 because unmount.exe not only unmounts my usb pen but also my usb mouse. But on the same homepage like unmount you find removedrive.exe which works better. And it ist much easier to use.

EDIT

I altered the script and insertet the kill.exe for users who want to kill other processes startet from usb pen. I use kill.exe instead of taskkill because taskkill works only with XP.
For example I kill pstart because I cannot kill my desktop-calendar (PTBSync.exe).


BEGIN SCRIPT

' Name: autorun.vbs
' found at (https://portableapps.com/node/639)
' Date: May 21, 2006
'
' originally by
' Author: Grant Emsley
' Date: Jan 28, 2006
'
' some improvements (for windows 2000 / w2k) by
' Florian Thomas Hofmann
'
' What it does:
'
' This script takes the full path/name of where the script was run from (USB Stick / USB pen drive / Memory stick), strips off everything except the drive letter and colon, and sets it to the environmental variable "portabledrive". It sets this in the Volatile Environment so it will remain set between different programs, but gets cleared when you logout/reboot.
' This allows you to make all your shortcuts and such in the format: %portabledrive%\programs\programname\program.exe
' This means that most programs that have trouble with relative paths will work
' After closing PStart the script will remove your usb pen.
' ---------------------------------------------------------
' Required Programs:
' RemoveDrive.exe (http://www.uwe-sieber.de/files/removedrive.zip)
' - This is required if you want to automatically "safely remove hardware"
' Kill.exe (http://www.pcwelt.de/downloads/heft-cd/03-05/107355/)
' - This kills like XP-tastkill in XP and also in Windows 95/98/ME/NT/2000 if you want to close some program before unmounting
' -----------------------------------------------------------

Dim objShell
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")

' -------------------------------------------------------------
' get the drive letter
arrPath = Split(Wscript.ScriptFullName, "\")
strdriveletter = arrPath(0)

' create a collection to access the Volatile environment, then set the portabledrive
set colVolatileEnvVars = objShell.Environment("Volatile")
colVolatileEnvVars("portabledrive") = strdriveletter

' ----------------------------------------------------------
' I have a folder called "Daten" on my drive. Lets make a shortcut in "My Documents" to my portable documents folder. This way I can just click there on any save/open dialogue box.

strMyDocs = objShell.SpecialFolders("MyDocuments")
set objSLink = objShell.CreateShortcut(strMyDocs & "\Daten.lnk")
objSLink.TargetPath = strdriveletter & "\Daten"
objSlink.Save
' ----------------------------------------------------------------------------------------------------

' NOTE: if you want to run something before starting pstart, do it below this line. (guide to running programs is at the end of the script)

' Now lets run pstart, and wait for it to exit before we continue
objShell.Run strdriveletter & "\PRG\Autostart\pstart.exe", 1, TRUE

' NOTE: If you want to run something AFTER running pstart, do it below this.
' For example here you can kill other processes which use your stick
' Use this: objShell.Run strdriveletter & "\PRG\Autostart\kill.exe Program-Name", 1, TRUE
' For details on kill.exe start kill.exe /? in a dos-window

' Pstart is done, so lets clean up
' Delete the shortcut to Portable Documents
objFSO.DeleteFile(strMyDocs & "\Daten.lnk")

' Safely remove hardware
' Probably won't work if you aren't an administrator
' it WONT work if you have open files on the drive (probably a good thing)
' Warn the user that we are going to dismount the drive
Wscript.Echo "Ready to remove portable drive. Please close all programs/files on the drive, then click ok."

' First we have to change the current directory so we aren't holding the drive open.
objShell.CurrentDirectory = "C:\"
' Now we copy the file to the c drive
objFSO.CopyFile strdriveletter & "\PRG\Autostart\RemoveDrive.exe", "c:\", true
' At last we run RemoveDrive. It waits until all files are closed on the drive then removes the drive letter ans unmountes after that.
objShell.Run "c:\RemoveDrive " & strdriveletter & " -l", 1, TRUE

' Then we clean up after ourselves
objFSO.DeleteFile("C:\RemoveDrive.exe")

Wscript.Echo "Your drive should be safely removed."

Wscript.Quit

' ----------------------------------------------------------------------------------------------------
' objShell.run , ,
'
' Some good window states:
' 0 - hidden
' 1 - normal
' 2 - minimized forground
' 3 - maximized
' 7 - minimized background
'
' The last parameter takes either true or false. If true, it pauses the script and waits for it to exit before continuing. Default is false.
' ----------------------------------------------------------------------------------------------------

END SCRIPT

Hope, you enjoy this

--- Classic ---

arqbrulo
arqbrulo's picture
Offline
Last seen: 4 years 1 month ago
Joined: 2006-08-10 16:38
Please help

First of all, I hope It's not too late to make a post here, I really hope someone reads this still and helps me out. Second, I want to thank everybody in the PA.com forum for all your input (specially the usual ones, John, Bruce, Ashes, rmccue, etc.). I went to college to study something totally different than computers, this at most is an interest to me. But when I received my 1gb U3 (I later deleted U3) drive I started looking at all the possibilities of portable apps and because of all of you, now I am able to read and understand codes. So now to my question. I wrote the vbs file as stated above (changing only the path) and i have "objShell.Run strdriveletter & "\apps\autorun\taskkill.exe /im googletalk.exe", 0, TRUE" under the "run pstart" line. The program kills google talk but then it does not eject my drive (using deveject). If I manually close googletalk, then the same script does eject my drive. Also, if I remove the taskkill line from the script, it also works. So my quesion is what am I doing wrong that the script does not eject the drive after killing googletalk?
P.S. i've also used other programs instead of taskkill and instead of deveject and it's all the same. Thank you.
p.s.2 Do you think it will work better if I use the 2 bat files as originally posted by grantemsley?

UPDATE: i decided to stick to the vbs file, and the way I fixed the little issue was to add "objShell.Run("ping -n 1 120.0.0.1"), 0, true" under taskkill. Also, the GTalk icon is not removed unless I leave the mouse in the notification area and therefore would not eject my device. But I can handle that much.

"In three words I can sum up everything I've learned about life: it goes on." -- Robert Frost
"In three words I can sum up everything I've learned about life: baby ain't mine." -- Adam Holguin

daniel_i
Offline
Last seen: 10 years 3 months ago
Joined: 2006-05-08 05:05
Link don't work!

Link http://www.uwe-sieber.de/files/removedrive.zip don't whork.
Where can I find REMOVEDRIVE.ZIP?

Thanks,

Dan

Log in or register to post comments