コマンドプロンプトからUSB記憶装置を取り外そうとして失敗し続けている記録

WindowsUSBメモリなどを取り外す際にタスクトレイから行う「ハードウェアの安全な取り外し」の操作をコマンドプロンプトから実現しようとして、依然として失敗し続けている。

備忘録として、時系列順に記録を残しておこうと思う。何か進展があったら追記するつもりだ。

おま環の問題かもしれないので、もう少し具体的に背景を書く:

  1. Windows Storage Server 2016 Workgroupで運用しているNASがある。
  2. このNASには、NTFSでフォーマットしたUSB-HDDが取り付けてある。
  3. USB-HDDは、Windowsバックアップツールを利用した定例バックアップ先として使用している。
  4. USB-HDDは、定例バックアップの時だけ接続している。バックアップ終了後には、取り外し可能な状態にした上で、USB-HDD本体の電源をOFFにしている。
  5. 諸々の事情で、定例バックアップはWbadmin.exeを叩くパッチファイルをタスクスケジューラで実行することで実現している。
  6. 定例バックアップ完了後に、毎回NASにログオンして「ハードウェアの安全な取り外し」の操作をするのが面倒である。なので同様の操作をパッチファイルから実行することで自動化したい。
  7. NASは業務用として運用しているので、Windows Storage Server 2016の標準の機能か、もしくはMicrosoftが公開しているツールなどで実現したい。サードパーティのツールは導入したくない。

以上の理由より、コマンドプロンプト(正確にはパッチファイル)から標準/準標準の機能で「ハードウェアの安全な取り外し」と同等の処理を実現しようと試みているのだが、未だに成功する気配がない。

今のところ得られている結果は「そもそもアンマウントすらできない」か「運用上問題となる副作用が発生する」のどちらかである。

1. PowerShell : Shell.Application 経由で Eject

PowerShellを使ってCD-ROMドライをイジェクトするネタがあるのだが、同じ方法でUSBデバイスもいけるという情報を得たので、試してみた。

# 実行例 - F: を取り外す場合
(New-Object -ComObject Shell.Application).Namespace(17).ParseName('F:').InvokeVerb('Eject')

結果:アンマウントすらされない。

2. Windows Sysinternals : sync のオプション -e を使う

Windows Sysinternalsのsync.exe/sync64.exeのオプション-eでイジェクトできるとの情報を得たので、試してみた。

:: 実行例 - F: を取り外す場合
sync64.exe -nobanner -e F

結果:アンマウントすらされない。

3. 標準コマンド : mountvol を使う

標準コマンドmountvolのヘルプを見たところ、オプション/pにそれっぽい内容の記述があったので、試してみた。

:: 実行例 - F: を取り外す場合
mountvol F: /p

結果:ディスクがアンマウントされ、オフラインになる。その後にタスクトレイでの取り外し操作は必要だが、既にオフライン状態なので、直ぐに取り外し可能状態になる。

問題点:この後ディスクの電源をONにした時、ドライブレターの割り当てが外れている。例えば「mountvol F: /p」でFドライブのUSB-HDDを取り外した場合、そのUSB-HDDを再度接続した時、ドライブレターが全く割り当てられない(なのでエクスプローラーの「デバイスとドライブ」からはUSB-HDDにアクセスできない)。

4. PowerShell : Set-Disk でオフラインにする

PowerShellのSet-Diskでゴニョゴニョできる、という情報を得たので、試してみた。

# 実行例 - F: を取り外す場合
Get-Disk | ?{ $_.FriendlyName -eq 'I-O DATA HDJA-UT' } | Set-Disk -IsOffline:$true

結果:ディスクがアンマウントされ、オフラインになる。その後にタスクトレイでの取り外し操作は必要だが、既にオフライン状態なので、直ぐに取り外し可能状態になる。

問題点:この後ディスクの電源をONにした時、ディスクがオフラインのままになる。なのでSet-Diskを使うなどして明示的にオンライン状態にしないとUSB-HDDが使えない。