【问题标题】:How to detect a USB drive has been plugged in?如何检测 USB 驱动器已插入?
【发布时间】:2011-05-14 18:05:00
【问题描述】:

我想构建一个程序来检测是否插入了一个(或两个或更多)usb (并将所有内容复制到硬盘上的任何文件夹)

有什么想法吗?我有这个,

using System.Runtime.InteropServices;

但这不是简单的方法(我相信)。我想要一些简单的东西。

我有另一个想法(如果(文件夹存在)然后复制)一些东西——但这可能有问题,我想要一个好的解决方案。

可能还有一个工具叫SerialPort;我可以用吗?如果是这样,我该如何使用它?

【问题讨论】:

  • 将其分解为单独的部分。检测 USB 驱动器的代码是一个,从中复制数据的代码是另一个。尽你所能。
  • 是的!我现在可以“复制”文件..如果不存在,程序可以使用批处理文件“创建”文件
  • 我制作了一个适用于 Windows、MacOS 和 Linux 的 NuGet 数据包:github.com/Jinjinov/Usb.Events

标签: c# file usb-drive


【解决方案1】:

检查可移动设备很容易。但是,不能保证它是 USB 设备:

var drives = DriveInfo.GetDrives()
    .Where(drive => drive.IsReady && drive.DriveType == DriveType.Removable);

这将返回当前可访问的所有可移动设备的列表。更多信息:

【讨论】:

  • 你在哪里声明“驱动器”??
  • @angel:您不必单独声明drivedrive 是我用作.Where() 扩展方法输入的lamba 表达式的输入参数。它是 .NET 框架 3.5 引入的 Linq 功能的一部分。有关 Linq 的更多信息:msdn.microsoft.com/en-us/vbasic/aa904594.
  • 那不是还给您 CD-ROM 驱动器、存储卡驱动器,有时甚至是硬盘驱动器(在我的 PC 中,我的 SATA 驱动器显示为可移动驱动器,即使它是 C 驱动器)?此外,您是否必须不断循环通过此检测以检测驱动器何时插入或是否存在某种触发器?
  • @BiggsTRC:如果您查看DriveType 枚举,您会发现CD-ROM 驱动器的值不同。我认为您无法区分存储卡驱动器和 USB 记忆棒,因为存储卡驱动器通常通过内部 USB 连接连接到主板。
  • @arthurmani - 类 DriveInfo 定义在命名空间 System.IO 中,因此您必须包含该命名空间才能使其工作。
【解决方案2】:

这是一个适合我的代码,它是上面网站的一部分,结合我的早期试验: http://www.codeproject.com/KB/system/DriveDetector.aspx

这基本上让您的表单监听 Windows 消息、USB 驱动器和 (cd-dvds) 过滤器、获取消息的 lparam 结构并提取驱动器号。

protected override void WndProc(ref Message m)
    {

        if (m.Msg == WM_DEVICECHANGE)
        {
            DEV_BROADCAST_VOLUME vol = (DEV_BROADCAST_VOLUME)Marshal.PtrToStructure(m.LParam, typeof(DEV_BROADCAST_VOLUME));
            if ((m.WParam.ToInt32() == DBT_DEVICEARRIVAL) &&  (vol.dbcv_devicetype == DBT_DEVTYPVOLUME) )
            {
                MessageBox.Show(DriveMaskToLetter(vol.dbcv_unitmask).ToString());
            }
            if ((m.WParam.ToInt32() == DBT_DEVICEREMOVALCOMPLETE) && (vol.dbcv_devicetype == DBT_DEVTYPVOLUME))
            {
                MessageBox.Show("usb out");
            }
        }
        base.WndProc(ref m);
    }

    [StructLayout(LayoutKind.Sequential)] //Same layout in mem
    public struct DEV_BROADCAST_VOLUME
    {
        public int dbcv_size;
        public int dbcv_devicetype;
        public int dbcv_reserved;
        public int dbcv_unitmask;
    }

    private static char DriveMaskToLetter(int mask)
    {
        char letter;
        string drives = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //1 = A, 2 = B, 3 = C
        int cnt = 0;
        int pom = mask / 2;
        while (pom != 0)    // while there is any bit set in the mask shift it right        
        {        
            pom = pom / 2;
            cnt++;
        }
        if (cnt < drives.Length)
            letter = drives[cnt];
        else
            letter = '?';
        return letter;
    }

不要忘记添加这个:

using System.Runtime.InteropServices;

以及以下常量:

    const int WM_DEVICECHANGE = 0x0219; //see msdn site
    const int DBT_DEVICEARRIVAL = 0x8000;
    const int DBT_DEVICEREMOVALCOMPLETE = 0x8004;
    const int DBT_DEVTYPVOLUME = 0x00000002;  

【讨论】:

  • 备注 - 在 if (m.Msg == WM_DEVICECHANGE) 周围使用 try-catch。
  • 这是否检测到具有多个分区的驱动器?
【解决方案3】:

微软 API 代码包。 ShellObjectWatcher 类。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-21
    • 2023-04-07
    • 1970-01-01
    • 2010-09-21
    • 1970-01-01
    相关资源
    最近更新 更多