🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

10134閲覧

C#でUSBメモリの安全な取り外しがしたい

退会済みユーザー

退会済みユーザー

総合スコア0

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

0クリップ

投稿2019/09/10 05:50

前提・実現したいこと

WPFを用いてUSBメモリの取り外しを行いたいと思っています。
取り外しはできているようなのですが、下記のコードで確認するとドライブが残っています。

C#

1Directory.GetLogicalDrives()

完全な取り外しはできないでしょうか?

MainWindow.xaml

C#

1 private void Button_Click_1(object sender, RoutedEventArgs e) 2 { 3 USB lusb = new USB(); 4 lusb.Eject("D"); 5 }

USB.cs

C#

1using System; 2 3using System.Runtime.InteropServices; 4using System.Threading; 5using System.Windows; 6 7namespace test1_wpf 8{ 9 class USB 10 { 11 12 [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)] 13 private static extern IntPtr CreateFile( 14 string lpFileName, 15 uint dwDesiredAccess, 16 uint dwShareMode, 17 IntPtr SecurityAttributes, 18 uint dwCreationDisposition, 19 uint dwFlagsAndAttributes, 20 IntPtr hTemplateFile 21 ); 22 23 [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)] 24 private static extern bool DeviceIoControl( 25 IntPtr hDevice, 26 uint dwIoControlCode, 27 IntPtr lpInBuffer, 28 uint nInBufferSize, 29 IntPtr lpOutBuffer, 30 uint nOutBufferSize, 31 out uint lpBytesReturned, 32 IntPtr lpOverlapped 33 ); 34 35 [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)] 36 private static extern bool DeviceIoControl( 37 IntPtr hDevice, 38 uint dwIoControlCode, 39 byte[] lpInBuffer, 40 uint nInBufferSize, 41 IntPtr lpOutBuffer, 42 uint nOutBufferSize, 43 out uint lpBytesReturned, 44 IntPtr lpOverlapped 45 ); 46 47 [DllImport("kernel32.dll", SetLastError = true)] 48 [return: MarshalAs(UnmanagedType.Bool)] 49 private static extern bool CloseHandle(IntPtr hObject); 50 51 private IntPtr handle = IntPtr.Zero; 52 53 const uint GENERIC_READ = 0x80000000; 54 const uint GENERIC_WRITE = 0x40000000; 55 const int FILE_SHARE_READ = 0x1; 56 const int FILE_SHARE_WRITE = 0x2; 57 const int FSCTL_LOCK_VOLUME = 0x00090018; 58 const int FSCTL_DISMOUNT_VOLUME = 0x00090020; 59 const int IOCTL_STORAGE_EJECT_MEDIA = 0x2D4808; 60 const int IOCTL_STORAGE_MEDIA_REMOVAL = 0x002D4804; 61 62 public IntPtr USBEject(string driveLetter) 63 { 64 string filename = @"\.\" + driveLetter[0] + ":"; 65 return CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, 0x3, 0, IntPtr.Zero); 66 } 67 68 public bool Eject(IntPtr handle) 69 { 70 bool result = false; 71 72 if (LockVolume(handle) && DismountVolume(handle)) 73 { 74 PreventRemovalOfVolume(handle, false); 75 result = AutoEjectVolume(handle); 76 } 77 CloseHandle(handle); 78 return result; 79 } 80 81 private bool LockVolume(IntPtr handle) 82 { 83 uint byteReturned; 84 85 for (int i = 0; i < 10; i++) 86 { 87 if (DeviceIoControl(handle, FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero)) 88 { 89 MessageBox.Show("Lock success!"); 90 return true; 91 } 92 Thread.Sleep(500); 93 } 94 return false; 95 } 96 97 private bool PreventRemovalOfVolume(IntPtr handle, bool prevent) 98 { 99 byte[] buf = new byte[1]; 100 uint retVal; 101 102 buf[0] = (prevent) ? (byte)1 : (byte)0; 103 return DeviceIoControl(handle, IOCTL_STORAGE_MEDIA_REMOVAL, buf, 1, IntPtr.Zero, 0, out retVal, IntPtr.Zero); 104 } 105 106 private bool DismountVolume(IntPtr handle) 107 { 108 uint byteReturned; 109 return DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero); 110 } 111 112 private bool AutoEjectVolume(IntPtr handle) 113 { 114 uint byteReturned; 115 return DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero); 116 } 117 118 private bool CloseVolume(IntPtr handle) 119 { 120 return CloseHandle(handle); 121 } 122 123 124 public void EjectDrive(char driveLetter) 125 { 126 string path = @"\.\" + driveLetter + @":"; 127 IntPtr handle = CreateFile(path, GENERIC_READ | GENERIC_WRITE, 128 FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, 0x3, 0, IntPtr.Zero); 129 130 if ((long)handle == -1) 131 { 132 MessageBox.Show("Unable to open drive " + driveLetter); 133 return; 134 } 135 136 uint dummy = 0; 137 138 DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, 139 IntPtr.Zero, 0, out dummy, IntPtr.Zero); 140 141 CloseHandle(handle); 142 143 MessageBox.Show("OK to remove drive."); 144 } 145 } 146} 147

補足情報(FW/ツールのバージョンなど)

Windows 10 Pro
Visual Studio 2017
.NetFramework 4.0

  • 実行前

イメージ説明

  • 実行後

イメージ説明

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

CM_Request_Device_Ejectを利用されてみてはどうでしょうか?
こちらこちらとか参考になりませんか?

投稿2019/09/10 06:01

編集2019/09/10 06:29
YAmaGNZ

総合スコア10469

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/09/10 07:25

参考URLありがとうございます。 ```C# enum PNP_VETO_TYPE : int { PNP_VetoTypeUnknown = 0, PNP_VetoLegacyDevice = 1, PNP_VetoPendingClose = 2, PNP_VetoWindowsApp = 3, PNP_VetoWindowsService = 4, PNP_VetoOutstandingOpen = 5, PNP_VetoDevice = 6, PNP_VetoDriver = 7, PNP_VetoIllegalDeviceRequest = 8, PNP_VetoInsufficientPower = 9, PNP_VetoNonDisableable = 10, PNP_VetoLegacyDriver = 11, PNP_VetoInsufficientRights = 12 } [DllImport("setupapi.dll", CharSet = CharSet.Auto)] static extern int CM_Request_Device_Eject( UInt32 devinst, out PNP_VETO_TYPE pVetoType, System.Text.StringBuilder pszVetoName, int ulNameLength, int ulFlags ); ・・・ CM_Request_Device_Eject((uint)devinst, out pnp_veto_type, sb, sb.Capacity, 0); ``` 安直に、CreateFileで生成したIntPtrを入れても動作しないようです。。。 参考サイトを正しく認識できていない点が大きいとは思いますが。
退会済みユーザー

退会済みユーザー

2019/09/11 00:14

ありがとうございます!ご提示いただいたサイトを参考に問題なく動きました! これを自力で実装はほぼ不可能に近いので大変助かりました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問