Replicate Computer / Disk Management eject procedure (in script)

Posted on 2009-06-29
Last Modified: 2014-03-21
Within Disk Management (of Computer Management), I'd like to write a script, .bat, .vbs, visual basic etc, that will replicate the eject feature.

Ejecting via Windows Explorer won't work. The USB cartridge for backups that I'm using, will only eject via the computer management eject procedure, so I'd like to script this.

Using windows 2008... and have VB6.

Can anyone help?
Question by:gary_sland
  • 4
LVL 29

Expert Comment

ID: 24742934
I am pretty syre they both perform the same routine.

Here is how you would eject a removable device using API.

1) Open a (volume) handle to the device using CreateFile()
2) Try to lock the volume using FSCTL_LOCK_VOLUME
3) If the call above succeeds it's safe to dismount the volume using FSCTL_DISMOUNT_VOLUME
4) You want to make sure there is no (prevent removal locks) on the volume so you call IOCTL_STORAGE_MEDIA_REMOVAL and set the structure parameter to False.
5) Use IOCTL_STORAGE_EJECT_MEDIA to eject the device.
6) Close the volume handle.

This is how all of them work but I will take a wild guess and say that maybe explorer doesn't go as far to disable any ejection locks but the disk managment eject option does.
LVL 29

Accepted Solution

nffvrxqgrcfqvvc earned 500 total points
ID: 24743057
Here is an example I wrote that should eject a removable device just like explorer or disk managment. This is an interesting question and I want to know myself if there is any difference between them. Give this a try and keep me updated! :)

Add code to a (module.bas)
Usage: SafeEject "e:\"
Option Explicit
' safe eject media vb6.
' author's name
PreventMediaRemoval As Long
End Type
Private Const INVALID_HANDLE_VALUE As Long = (-1)
Private Const FSCTL_LOCK_VOLUME As Long = &H90018
Private Const FSCTL_UNLOCK_VOLUME As Long = &H9001C
Private Const FSCTL_DISMOUNT_VOLUME As Long = &H90020
Private Const IOCTL_STORAGE_MEDIA_REMOVA<wbr ></wbr>L As Long = &H2D4804
Private Const IOCTL_STORAGE_EJECT_MEDIA As Long = &H2D4808
Private Const OPEN_EXISTING As Long = 3
Private Const GENERIC_READ As Long = &H80000000
Private Const GENERIC_WRITE As Long = &H40000000
Private Const FILE_SHARE_READ As Long = &H1
Private Const FILE_SHARE_WRITE As Long = &H2
Private Const DRIVE_REMOVABLE As Long = 2
Private Const DRIVE_CDROM As Long = 5
Private Declare Function DeviceIoControl Lib "kernel32.dll" (ByVal hDevice As Long, ByVal dwIoControlCode As Long, ByVal lpInBuffer As Long, ByVal nInBufferSize As Long, ByVal lpOutBuffer As Long, ByVal nOutBufferSize As Long, lpBytesReturned As Long, ByVal lpOverlapped As Long) As Long
Private Declare Function CreateFileW Lib "kernel32.dll" (ByVal lpFileName As Long, ByVal dwDesiredAccess As Long, ByVal dwShareMode As Long, ByVal lpSecurityAttributes As Long, ByVal dwCreationDisposition As Long, ByVal dwFlagsAndAttributes As Long, ByVal hTemplateFile As Long) As Long
Private Declare Function GetDriveTypeW Lib "kernel32.dll" (ByVal nDrive As Long) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" (ByVal hObject As Long) As Long
Sub SafeEject(ByVal szDrive As String)
Dim dwAccess As Long
Dim dwDriveType As Long
Dim hDrive As Long
Dim cb As Long
' Check if trailing backslash exists.
If InStr(szDrive, "\") = 0 Then
  Debug.Print "Please specify a full drive letter. ex. X:\"
  Exit Sub
End If
' Backslash is required for this call.
dwDriveType = GetDriveTypeW(StrPtr(szDri<wbr ></wbr>ve))
' Check if this type of drive is removable.
Select Case dwDriveType
    dwAccess = GENERIC_READ
  Case Else
    Debug.Print "This type of volume is not a removable device."
    Exit Sub
End Select
' Remove backslash.
szDrive = Replace$(szDrive, "\", vbNullString)
' This must not have a backslash.(open volume for direct access might need admin rights on vista/win7)
hDrive = CreateFileW(StrPtr("\\.\" & szDrive), dwAccess, FILE_SHARE_READ Or FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0)
' checksum
  Debug.Print "Bad handle. (try:run as admin)"
  Exit Sub
End If
' Attempt to lock the volume for safe ejection.
If DeviceIoControl(hDrive, FSCTL_LOCK_VOLUME, 0, 0, 0, 0, cb, 0) Then
  ' DISMOUNT the volume and flush cache and any associations on the systems.
  Call DeviceIoControl(hDrive, FSCTL_DISMOUNT_VOLUME, 0, 0, 0, 0, cb, 0)
  ' Make sure there is no prevent removal locks.
  udtPMR.PreventMediaRemoval<wbr ></wbr> = 0
  Call DeviceIoControl(hDrive, IOCTL_STORAGE_MEDIA_REMOVA<wbr ></wbr>L, VarPtr(udtPMR), Len(udtPMR), 0, 0, cb, 0)
  ' Eject the media.
  Call DeviceIoControl(hDrive, IOCTL_STORAGE_EJECT_MEDIA,<wbr ></wbr> 0, 0, 0, 0, cb, 0)
  ' You could still force the ejection here but any
  ' data in process would get corrupted.
  Debug.Print "It's not safe to eject this media."
End If
' Close volume handle.
CloseHandle hDrive
End Sub

Open in new window


Author Closing Comment

ID: 31597917
Hi. Many thanks for your help. This worked! I really thought I'd be stuck with this problem. There does seem to be some difference between explorer and disk management, perhaps as you say it's to do the locks.
Many thanks though!
LVL 29

Expert Comment

ID: 24747548
Great. So it seems that the computer managment is doing some additional work than explorer thats interesting.

I was messing around with the (Safe Remove Hardware option) and I noticed that it actually updates explorer and removes the drive from the explorer list. Which the code above doesn't do so in addition the safely remove hardware goes even one step further and updates explorer.

Here is how it works.

Option Explicit

Private Const SHCNE_DRIVEREMOVED As Long = &H80

Private Const SHCNF_PATHW As Long = 5

Private Declare Function SHChangeNotify Lib "shell32.dll" (ByVal wEventId As Long, _

  ByVal uFlags As Long, ByVal dwItem1 As Long, ByVal dwItem2 As Long) As Long

Private Sub Update(ByVal szDrive As String)

' Do some magic here.(must have trailing backslash)

Call SHChangeNotify(SHCNE_DRIVEREMOVED, SHCNF_PATHW, StrPtr(szDrive), 0)

End Sub

Open in new window

LVL 29

Expert Comment

ID: 24747565
Just to make sure, you would call the above method after you call the eject part.

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
Validating VB6 Function 19 56
to transfer string from C lanaguage to VBA 4 57
Please explain "Promise Pattern" and how it's used 2 54
Help me. 3 46
Introduction In a recent article ( for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
Introduction While answering a recent question about filtering a custom class collection, I realized that this could be accomplished with very little code by using the ScriptControl (SC) library.  This article will introduce you to the SC library a…
Get people started with the utilization of class modules. Class modules can be a powerful tool in Microsoft Access. They allow you to create self-contained objects that encapsulate functionality. They can easily hide the complexity of a process from…
This is Part 3 in a 3-part series on Experts Exchange to discuss error handling in VBA code written for Excel. Part 1 of this series discussed basic error handling code using VBA.…

895 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now