11

I would like to eject/dismount an external USB drive via PowerShell.

Meaning, I want to replicate exactly the behaviour of these UI actions (Ejecting drive via Windows UI):

Ejecting drive via Windows UI

Currently I am using this script:

$drive_letter="G"
$vol = get-wmiobject -Class Win32_Volume | where{$_.Name -eq $drive_letter+":\"}  
$vol.DriveLetter = $null
$vol.Put()  
$vol.Dismount($false, $false)

This works, however, when I connect the drive again, it won't show up on the list of the drives. I assume this is because of the fact that drive letter it tied to GUID of the drive and because of this: $vol.DriveLetter = $null.

I have also tried this:

$driveEject = New-Object -comObject Shell.Application
$driveEject.Namespace(17).ParseName("G:").InvokeVerb("Eject")

but it didn't work.

For what it's worth, $driveEject.Namespace(17).ParseName("G:") returns:

Application  : System.__ComObject
Parent       : System.__ComObject
Name         : Backup (G:)
Path         : G:\
GetLink      :
GetFolder    : System.__ComObject
IsLink       : False
IsFolder     : True
IsFileSystem : True
IsBrowsable  : False
ModifyDate   : 12/30/1899 12:00:00 AM
Size         : 0
Type         : Local Disk

How can I dismount the drive so that it performs exactly the actions the user performs when ejecting the drive via Windows UI?

user73235
  • 111

4 Answers4

6

The cleanest solution would be to invoke the Eject verb, which takes care of everything.

$driveEject = New-Object -comObject Shell.Application
$driveEject.Namespace(17).ParseName("E:").InvokeVerb("Eject")
5

I had a similar issue. I fixed it by adding a slash after the drive letter G:\ instead of G:

$driveEject = New-Object -comObject Shell.Application
$driveEject.Namespace(17).ParseName("G:\").InvokeVerb("Eject")
Michel
  • 302
1

There are tools to do this as well.

Microsoft SysInternals

https://learn.microsoft.com/en-us/sysinternals/downloads/sysinternals-suite

Specifically

https://learn.microsoft.com/en-us/sysinternals/downloads/sync

sync.exe -accepteula -e x:

Yet. all-in-all, the above is doing what '@Savchenko Dmitriy', has already given you.

postanote
  • 5,136
1

$driveEject.Namespace(17) will work on normal SD Cards and USB Flash drives.

Might not work with external HDD/SSD as they are treated as SCSI devices. It does not work for me also.

I am also looking for solution to this (SCSI/USB HDD eject).

Nearest option I saw is to spawn the Safely Remove dialog via rundll, which I would prefer not to use (it has also pitfalls) if other option is available.

Edit: following might work for non ejectable USB/SCSI HDDs

$hddDevs = Get-CimInstance -ClassName Win32_DiskDrive
$externalDisks = $hddDevs | Where {$_.MediaType -like "Removable*"} | select PNPDeviceID
Disable-PnPDevice -InstanceId $externalDisks.PNPDeviceID -Confirm:$false
Enable-PnPDevice  -InstanceId $externalDisks.PNPDeviceID -Confirm:$false
mwfearnley
  • 7,889
Gergo
  • 11