📌  相关文章
📜  连接 USB 设备时自动打开文件资源管理器 (1)

📅  最后修改于: 2023-12-03 15:41:55.878000             🧑  作者: Mango

连接 USB 设备时自动打开文件资源管理器

有时候我们需要在连接 USB 设备时自动打开文件资源管理器,以方便我们进行文件的查看和操作。在 Windows 操作系统中,我们可以使用 C# 编写程序实现该功能。

方法一:使用 System.Management 命名空间监听 USB 设备插入事件
1. 引用命名空间
using System.Management;
2. 监听 USB 设备插入事件
ManagementEventWatcher watcher = new ManagementEventWatcher();
WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2"); // EventType 2 表示插入事件
watcher.EventArrived += new EventArrivedEventHandler(USBInserted);
watcher.Query = query;
watcher.Start();
3. 处理 USB 设备插入事件
public static void USBInserted(object sender, EventArrivedEventArgs e)
{
    ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"];
    if (instance.Properties["InterfaceType"].Value.ToString() == "USB") // 判断是否为 USB 设备
    {
        string driveLetter = instance.Properties["Name"].Value.ToString().Substring(0, 2); // 获取 USB 设备的盘符
        string path = driveLetter + @"\";
        System.Diagnostics.Process.Start("explorer.exe", path); // 打开文件资源管理器并跳转到 USB 设备的根目录
    }
}
4. 停止监听
watcher.Stop();
方法二:使用 Windows API 监听 USB 设备插入事件
1. 引用命名空间和定义常量
using System.Runtime.InteropServices;
using Microsoft.Win32;
const int WM_DEVICECHANGE = 0x219; // 设备状态改变消息
const int DBT_DEVICEARRIVAL = 0x8000; // 设备插入消息
const int DBT_DEVTYP_VOLUME = 0x00000002; // 逻辑卷设备
2. 监听 USB 设备插入消息
protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    if (m.Msg == WM_DEVICECHANGE)
    {
        int wParam = m.WParam.ToInt32();
        if (wParam == DBT_DEVICEARRIVAL) // 设备插入
        {
            DEV_BROADCAST_VOLUME vol = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
            if (vol.dbcv_devicetype == DBT_DEVTYP_VOLUME) // 逻辑卷设备
            {
                string driveLetter = GetDriveLetter(vol.dbcv_unitmask);
                string path = driveLetter + @"\";
                System.Diagnostics.Process.Start("explorer.exe", path); // 打开文件资源管理器并跳转到 USB 设备的根目录
            }
        }
    }
}

private string GetDriveLetter(int mask)
{
    char[] drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".ToCharArray();
    for (int i = 0; i < 26; i++)
    {
        int bit = 1 << i;
        if ((mask & bit) != 0)
        {
            string drive = drives[i].ToString();
            return drive + ":";
        }
    }
    return "";
}
3. 注册事件
protected override void OnLoad(EventArgs e)
{
    base.OnLoad(e);
    RegisterUSBEvent();
}

protected override void OnClosed(EventArgs e)
{
    base.OnClosed(e);
    UnregisterUSBEvent();
}

private void RegisterUSBEvent()
{
    DEV_BROADCAST_DEVICEINTERFACE dbi = new DEV_BROADCAST_DEVICEINTERFACE();
    dbi.dbcc_size = Marshal.SizeOf(dbi);
    dbi.dbcc_devicetype = 5; // DBT_DEVTYP_DEVICEINTERFACE
    dbi.dbcc_reserved = 0;
    dbi.dbcc_classguid = new Guid("{53f56307-b6bf-11d0-94f2-00a0c91efb8b}"); // GUID_DEVINTERFACE_VOLUME
    IntPtr buffer = Marshal.AllocHGlobal(Marshal.SizeOf(dbi));
    Marshal.StructureToPtr(dbi, buffer, true);
    IntPtr hwnd = this.Handle;
    uint flags = 0;
    IntPtr hDevNotify = RegisterDeviceNotification(hwnd, buffer, flags);
}

private void UnregisterUSBEvent()
{
    DEV_BROADCAST_DEVICEINTERFACE dbi = new DEV_BROADCAST_DEVICEINTERFACE();
    dbi.dbcc_size = Marshal.SizeOf(dbi);
    dbi.dbcc_devicetype = 5; // DBT_DEVTYP_DEVICEINTERFACE
    dbi.dbcc_reserved = 0;
    dbi.dbcc_classguid = new Guid("{53f56307-b6bf-11d0-94f2-00a0c91efb8b}"); // GUID_DEVINTERFACE_VOLUME
    IntPtr buffer = Marshal.AllocHGlobal(Marshal.SizeOf(dbi));
    Marshal.StructureToPtr(dbi, buffer, true);
    IntPtr hwnd = this.Handle;
    uint flags = 0;
    UnregisterDeviceNotification(hDevNotify);
}

[StructLayout(LayoutKind.Sequential)]
public struct DEV_BROADCAST_DEVICEINTERFACE
{
    public int dbcc_size;
    public int dbcc_devicetype;
    public int dbcc_reserved;
    public Guid dbcc_classguid;
    public char dbcc_name;
}

[StructLayout(LayoutKind.Sequential)]
public struct DEV_BROADCAST_VOLUME
{
    public int dbcv_size;
    public int dbcv_devicetype;
    public int dbcv_reserved;
    public int dbcv_unitmask;
    public char dbcv_flags;
}

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr RegisterDeviceNotification(IntPtr hRecipient, IntPtr NotificationFilter, uint Flags);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool UnregisterDeviceNotification(IntPtr Handle);

以上是两种方法实现连接 USB 设备时自动打开文件资源管理器的代码片段,可以根据实际需要选择其中的一种方法进行使用。