分類:[C#]
2019/09/05(Thu) 16:42:59 編集(投稿者)
Windows10で動作させる前提、開発環境はC#でUSBメモリをイジェクトする必要があり、下記コードで作っております。
いろいろなサンプルを調べながらイジェクト自体はできております。
しかし、エクスプローラでみてみるとドライブの存在は残っており、クリックすると「USBドライブ(X:)にディスクを挿入してください。」
と表示されます。
まるでカードリーダーを差し込んでまだカード自体は差し込んでない状態のようです。
参考にさせていただいたUSBメモリのイジェクト方法はほかにもあったのですが、どの方法でも症状は同じでした。
どうすればシステムトレイからマウス操作で実施したときと同じ挙動にできるのでしょうか?
public static Boolean Eject(this DriveInfo drive)
{
using (var volume = Open(drive, false))
{
try
{
const int maxRetry = 10; // デバイスロックの最大試行回数
var locked = false;
for (var t = 0; t < maxRetry; t++)
{
if (IOControl.IOCtl(volume.DangerousGetHandle(), IOControl.FSCTL_LOCK_VOLUME))
{
locked = true;
break;
}
else
{
System.Threading.Thread.Sleep(100); // ロックできなければ1秒後に再試行
}
}
if (!locked)
throw new IOException("デバイスがビジー状態です");
if (!IOControl.IOCtl(volume.DangerousGetHandle(), IOControl.FSCTL_DISMOUNT_VOLUME))
throw new Win32Exception(Marshal.GetLastWin32Error());
unsafe
{
uint bytesReturned;
PREVENT_MEDIA_REMOVAL* inBuffer = stackalloc PREVENT_MEDIA_REMOVAL[1];
inBuffer[0].PreventMediaRemoval = 0; // FALSE
if (!IOControl.DeviceIoControl(volume.DangerousGetHandle(), IOControl.IOCTL_STORAGE_MEDIA_REMOVAL, (void*)inBuffer, (uint)Marshal.SizeOf(typeof(PREVENT_MEDIA_REMOVAL)), (void*)IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero))
throw new Win32Exception(Marshal.GetLastWin32Error());
}
if (!IOControl.IOCtl(volume.DangerousGetHandle(), IOControl.IOCTL_STORAGE_EJECT_MEDIA))
throw new Win32Exception(Marshal.GetLastWin32Error());
return true;
}
catch
{
return false;
}
}
}
/// <summary>ドライブを開いてSafeFileHandleを取得する</summary>
private static SafeFileHandle Open(DriveInfo drive, bool accessWrite)
{
uint accessFlags;
if (drive.DriveType == DriveType.CDRom)
accessFlags = GENERIC_READ;
else if (drive.DriveType == DriveType.Removable)
accessFlags = GENERIC_READ | GENERIC_WRITE;
else if (drive.DriveType == DriveType.Fixed)
accessFlags = GENERIC_READ | GENERIC_WRITE;
else
throw new NotSupportedException("リムーバブルドライブではありません");
if (accessWrite)
accessFlags |= GENERIC_WRITE;
var handle = CreateFile(string.Format(@"\\.\{0}:", drive.Name[0]),
accessFlags,
FILE_SHARE_READ | FILE_SHARE_WRITE,
IntPtr.Zero,
OPEN_EXISTING,
0,
IntPtr.Zero);
if (handle == INVALID_HANDLE_VALUE)
throw new Win32Exception(Marshal.GetLastWin32Error());
return new SafeFileHandle(handle, true);
}