C# と VB.NET の質問掲示板

わんくま同盟

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

ツリー一括表示

USBメモリのイジェクト /かつ (19/09/05(Thu) 16:41) #92259


親記事 / 返信無し
■92259 / 親階層)  USBメモリのイジェクト
□投稿者/ かつ (1回)-(2019/09/05(Thu) 16:41:51)

分類:[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);
        }

[ □ Tree ] 返信 編集キー/


管理者用

- Child Tree -