2011-05-14 3 views
47

Je veux construire un programme qui détecte si un périphérique USB (ou deux ou plus) sont branchés (et copier tout le contenu dans un dossier sur un disque dur)Comment détecter qu'une clé USB a été branchée?

Toutes les idées? J'ai ceci,

using System.Runtime.InteropServices; 

Mais ce n'est pas la voie facile (que je crois). Je veux quelque chose de facile. J'ai une autre idée (si (dossier existe) puis copie) quelque chose - mais il peut y avoir un problème avec cela, et je veux une bonne solution.

Il peut également y avoir un outil appelé SerialPort; puis-je l'utiliser? Si oui, comment l'utiliser?

+2

Détaillez-le en morceaux individuels. Le code qui détecte le lecteur USB est d'une seule pièce, le code qui copie les données est un autre. Faites les pièces que vous pouvez en ce moment. –

+0

ouais! je peux "copier" le fichier maintenant .. avec un fichier batch le programme peut "créer" le fichier s'il n'existe pas – angel

+0

Connexes: http://stackoverflow.com/questions/620144/detecting-usb-drive-insertion-and-removal -using-windows-service-et-c-sharp – DuckMaestro

Répondre

53

Il est facile de vérifier amovible appareils, mais il ne garantit pas que c'est un périphérique USB:

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

Cela renvoie une liste de tous les périphériques amovibles qui sont actuellement accessibles. Plus d'informations:

+0

où déclarez-vous "drive" ?? – angel

+3

@angel: Vous n'avez pas à déclarer séparément 'drive':' drive' est le paramètre d'entrée pour l'expression de lamba que j'utilise comme entrée pour la méthode d'extension '.Where()'. Cela fait partie des fonctionnalités Linq qui ont été intruduced avec le framework .NET 3.5. Plus d'infos sur Linq: http://msdn.microsoft.com/en-us/vbasic/aa904594. –

+0

Cela ne vous donnera-t-il pas aussi des lecteurs de CD-ROM, des lecteurs de carte mémoire, et parfois même des disques durs (dans mon PC, mon lecteur SATA apparaît comme amovible même s'il s'agit du lecteur C)? Aussi, auriez-vous besoin de passer en boucle cette détection continuellement afin de détecter quand un lecteur est branché ou est-ce qu'il y a une sorte de déclencheur? – IAmTimCorey

18

La détection de l'insertion d'une clé USB n'est pas simple. Cependant, c'est certainement possible et le travail a été fait pour vous. Voici deux liens que chaque détail une réponse sur la façon de le faire en C#:

http://www.codeproject.com/KB/system/DriveDetector.aspx

http://www.codeproject.com/Messages/2126647/Re-Csharp-USB-Detection.aspx

solution soit devrait fonctionner correctement pour vous. Vous pouvez les adapter à vos besoins.

Edit: Voici une troisième solution dans le cas où vous vouliez plus d'options (fondamentalement, ils sont tous les mêmes, mais le choix est bon, non?):

http://tempuzfugit.wordpress.com/2007/10/08/external-storage-unit-detection-with-c-in-net-usb-card-readers-etc/

2

code Microsoft API Pack. Classe ShellObjectWatcher.

11

Voici un code qui fonctionne pour moi, qui fait partie du site ci-dessus combiné avec mes premiers essais: http://www.codeproject.com/KB/system/DriveDetector.aspx

Cela rend fondamentalement votre forme écouter les messages des fenêtres, des filtres pour les lecteurs USB et (cd -dvds), récupère la structure lparam du message et extrait la lettre du lecteur.

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; 
    } 

Ne pas oublier d'ajouter ceci:

using System.Runtime.InteropServices; 

et les constantes suivantes:

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

One Remarque - Utilisez try-catch autour de if (m.Msg == WM_DEVICECHANGE). – Onsightfree

Questions connexes