Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


Replicate Computer / Disk Management eject procedure (in script)

Posted on 2009-06-29
Medium Priority
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
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 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 2000 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

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

Question has a verified solution.

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

Background What I'm presenting in this article is the result of 2 conditions in my work area: We have a SQL Server production environment but no development or test environment; andWe have an MS Access front end using tables in SQL Server but we a…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
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 lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…

721 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