C# 弹出指定USB设备

原以为只是一个小功能,但是实际上手写才发现不好实现,网上也没有找到什么很好的代码,所以这里就分享一下过程,直接上代码:

//返回设备句柄
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr CreateFile(
     string lpFileName,
     uint dwDesiredAccess,
     uint dwShareMode,
     IntPtr SecurityAttributes,
     uint dwCreationDisposition,
     uint dwFlagsAndAttributes,
     IntPtr hTemplateFile
);

[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool DeviceIoControl(
    IntPtr hDevice,
    uint dwIoControlCode,
    IntPtr lpInBuffer,
    uint nInBufferSize,
    IntPtr lpOutBuffer,
    uint nOutBufferSize,
    out uint lpBytesReturned,
    IntPtr lpOverlapped
);

[DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)]
private static extern bool DeviceIoControl(
    IntPtr hDevice,
    uint dwIoControlCode,
    byte[] lpInBuffer,
    uint nInBufferSize,
    IntPtr lpOutBuffer,
    uint nOutBufferSize,
    out uint lpBytesReturned,
    IntPtr lpOverlapped
);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]

private static extern bool CloseHandle(IntPtr hObject);
private static IntPtr handle = IntPtr.Zero;
const uint GENERIC_READ = 0x80000000;
const int GENERIC_WRITE = 0x40000000;
const int FILE_SHARE_READ = 0x1;
const int FILE_SHARE_WRITE = 0x2;
const int FSCTL_LOCK_VOLUME = 0x00090018;
const int FSCTL_DISMOUNT_VOLUME = 0x00090020;
const int IOCTL_STORAGE_EJECT_MEDIA = 0x2D4808;
const int IOCTL_STORAGE_MEDIA_REMOVAL = 0x002D4804;

public static async void EjectUsbAsync(string driveLetter)
{
    await Task.Run(() =>
    {
        EjectUsb(driveLetter);
    });
}

public static void EjectUsb(string driveLetter)
{
    try
    {
        string filename = @"\\.\" + driveLetter[0] + ":";
        handle = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, 0x3, 0, IntPtr.Zero);
        if (LockVolume(handle) && DismountVolume(handle))
        {
            PreventRemovalOfVolume(handle, true);
            AutoEjectVolume(handle)
        }
    }
    catch (Exception ex)
    {
        Log.Error($"弹出USB设备{driveLetter}出错:{ex}");
    }
}

private static bool LockVolume(IntPtr handle)
{
    uint byteReturned;
    for (int i = 0; i < 10; i++)
    {
        if (DeviceIoControl(handle, FSCTL_LOCK_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero))
        {
            return true;
        }
        Thread.Sleep(500);
    }
    return false;
}

private static bool PreventRemovalOfVolume(IntPtr handle, bool prevent)
{
     byte[] buf = new byte[1];
     uint retVal;
     buf[0] = (prevent) ? (byte)1 : (byte)0;
     return DeviceIoControl(handle, IOCTL_STORAGE_MEDIA_REMOVAL, buf, 1, IntPtr.Zero, 0, out retVal, IntPtr.Zero);
}

private static bool DismountVolume(IntPtr handle)
{
    uint byteReturned;
    return DeviceIoControl(handle, FSCTL_DISMOUNT_VOLUME, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero);
}

private static bool AutoEjectVolume(IntPtr handle)
{
    uint byteReturned;
    return DeviceIoControl(handle, IOCTL_STORAGE_EJECT_MEDIA, IntPtr.Zero, 0, IntPtr.Zero, 0, out byteReturned, IntPtr.Zero);
}
posted @ 2026-08-10 10:55  Poetindusk  阅读(2)  评论(0)    收藏  举报