2009-03-06 4 views
50

를 사용하여 스틱을 제거 할 때
USB 드라이브 삽입을 감지 및 제거 Windows 서비스 및 C#

닷넷를 사용하고 USB 스틱 및 종료의 삽입시 자동으로 시작됩니다 응용 프로그램
기음#.
제안을 찾으려면 C#을 사용하여이 방법에 접근하는 방법을 원하십니까?


업데이트 : 서비스로이를 구현하는 두 가지 가능한 솔루션을 제공합니다.
- WM_CHANGEDEVICE 처리를 시도 ManagementEventWatcher

+1

좋은 질문입니다. 나의 첫 번째 생각은 서비스를 "데스크톱과 상호 작용하도록 허용"으로 표시 한 다음 숨겨진 창을 만들어야한다는 것입니다. 안전한 옵션은 시작시 실행되는 윈도우 응용 프로그램을 만드는 데 아마 -이 창을 만든 다음 SVC –

+0

관련 통신 할 수 있습니다 : HTTP : // 유래.com/questions/6003822/USB 드라이브 감지 방법 – DuckMaestro

답변

44

당신은 WMI를 사용할 수 있습니다, 그것은 쉽게 그리고 서비스의 WndProc 솔루션보다 훨씬 더 작동합니다.

다음은 간단한 예입니다 :

using System.Management; 

ManagementEventWatcher watcher = new ManagementEventWatcher(); 
WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_VolumeChangeEvent WHERE EventType = 2"); 
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived); 
watcher.Query = query; 
watcher.Start(); 
watcher.WaitForNextEvent(); 

그리고 그것 뿐이다 :)

다음
+4

잘 작동하지만 삽입 된 USB의 드라이브 문자는 어떻게 얻을 수 있습니까? –

+0

[이 기사] (http://www.ravichaganti.com/blog/monitoring-volume-change-events-in-powershell-using-wmi/) Powershell에서이 정보를 얻는 것 같습니다. C#으로 번역하기가 너무 힘들지 않아야합니다. – VitalyB

+3

이벤트 처리기에서 'e.NewEvent.Properties [ "DriveName"] .Value.ToString()' – lambinator

4

와 WMI 쿼리를 사용 - 또는
의 WndProc
우선합니다.

5

또한 삽입 이벤트를 감지 WMI를 사용할 수 있습니다. WM_CHANGEDEVICE 메시지를 모니터링하는 것보다 조금 더 복잡하지만 서비스로 백그라운드에서 실행중인 경우 유용 할 수있는 창 핸들은 필요하지 않습니다.

+2

@ John Conrad : +1 WMI를 선택하는 것이 좋습니다. 또한 이것에 대한 주제를 발견 : http://stackoverflow.com/questions/39704/wmi-and-win32devicechangeevent-wrong-event-type-returned –

+0

사실 WMI는 훨씬 간단한 솔루션입니다. 나는 다른 해결책으로 그것을 아래에 게시하고있다. – VitalyB

4

우리가 WPF 응용 프로그램에서 C# 닷넷 4.0했던 것입니다. 우리는 여전히 "어떻게 삽입/제거 된 장치 유형 이야기하는"에 대한 해답을 찾고있다, 그러나 이것은 시작이다 : VitalyB의 게시물에 추가

using System.Windows.Interop; 
... 
public partial class MainWindow : Window 
{ 
    ... 
    public MainWindow() 
    { 
    ... 
    } 

    //============================================================ 
    // WINDOWS MESSAGE HANDLERS 
    // 

    private const int WM_DEVICECHANGE = 0x0219; // int = 537 
    private const int DEVICE_NOTIFY_ALL_INTERFACE_CLASSES = 0x00000004; 

    /// <summary> 
    /// 
    /// </summary> 
    /// <param name="e"></param> 
    protected override void OnSourceInitialized(EventArgs e) 
    { 
     base.OnSourceInitialized(e); 
     HwndSource source = PresentationSource.FromVisual(this) as HwndSource; 
     source.AddHook(WndProc); 
    } 

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) 
    { 
     if (msg == WM_DEVICECHANGE) 
     { 
      ReadDongleHeader(); 
     } 
     return IntPtr.Zero; 
    } 

} 
+2

삽입 된 장치 파악에 대한 개선 사항은 무엇입니까? – Kcvin

+0

@Kevin 이것은 다른 곳에서 쉽게 장치 목록을 찾을 수 있습니다. 여기에 내가 먼저 얻은 완전한 해결책이있다. 나를 위해 WM_DEVICECHANGE 만 해고됩니다. https://social.msdn.microsoft.com/Forums/vstudio/en-US/ea183afd-d070-4abd-8e00-a1784fdfedc5/detecting-usb-device-insertion-and-removalforforum=csharpgeneral – CularBytes

19

.

사용 다음, ANY USB 디바이스가 삽입 된 이벤트를 발생 :

var watcher = new ManagementEventWatcher(); 
var query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2"); 
watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived); 
watcher.Query = query; 
watcher.Start(); 

이것은 USB 장치가 연결될 때마다 이벤트를 발생시킬 것이다. NI-DAQ은 자동 감지를 위해 노력하고 있습니다.

+0

@Lee Taylor That 잘 작동하지만 삽입 된 USB의 드라이브 문자는 어떻게 얻을 수 있습니까? –

+0

@NeverQuit - 질문 만 편집하고 @Syn에게 질문하십시오! 또한 새로운 질문이 있으면 자유롭게 질문을 만드십시오. –

+0

@Syn 잘 작동하지만 삽입 된 USB의 드라이브 문자는 어떻게 얻을 수 있습니까? –

29

이 나를 위해 잘 작동, 플러스 당신이 장치에 대한 자세한 정보를 찾을 수 있습니다.

using System.Management; 

private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e) 
{ 
    ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"]; 
    foreach (var property in instance.Properties) 
    { 
     Console.WriteLine(property.Name + " = " + property.Value); 
    } 
} 

private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e) 
{ 
    ManagementBaseObject instance = (ManagementBaseObject)e.NewEvent["TargetInstance"]; 
    foreach (var property in instance.Properties) 
    { 
     Console.WriteLine(property.Name + " = " + property.Value); 
    } 
}    

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
{ 
    WqlEventQuery insertQuery = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'"); 

    ManagementEventWatcher insertWatcher = new ManagementEventWatcher(insertQuery); 
    insertWatcher.EventArrived += new EventArrivedEventHandler(DeviceInsertedEvent); 
    insertWatcher.Start(); 

    WqlEventQuery removeQuery = new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_USBHub'"); 
    ManagementEventWatcher removeWatcher = new ManagementEventWatcher(removeQuery); 
    removeWatcher.EventArrived += new EventArrivedEventHandler(DeviceRemovedEvent); 
    removeWatcher.Start(); 

    // Do something while waiting for events 
    System.Threading.Thread.Sleep(20000000); 
} 
+0

완벽하게 작동합니다. 삽입/제거시 다른 답변과 같은 여러 이벤트를 발생시키지 않습니다. 이것은 받아 들여진 대답이어야합니다. – samuelesque

+0

@samuelAndThe에 동의합니다. 이것이 가장 좋은 방법입니다. USB 드라이브뿐만 아니라 하드 드라이브의 변경 사항도 검색하고자한다면 'Win32_DiskDrive'클래스 –

+0

'private void backgroundWorker1_DoWork (object sender, DoWorkEventArgs e)'를 사용할 수 있습니다.'(object sender, DoWorkEventArgs e)'??? (나는 이것을위한 편집 제안을했다.) – Turtle

11

VitalyB 님의 답변은 기기의 커버를 제거하지 않습니다. 나는 이벤트를 트리거 할을 약간 변경 모두 미디어 를 삽입 가 삽입 된 미디어의 드라이브 문자를 얻을 또한 코드를 제거 할 때.

using System; 
using System.Management; 

namespace MonitorDrives 
{ 
    class Program 
    { 
     public enum EventType 
     { 
      Inserted = 2, 
      Removed = 3 
     } 

     static void Main(string[] args) 
     { 
      ManagementEventWatcher watcher = new ManagementEventWatcher(); 
      WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_VolumeChangeEvent WHERE EventType = 2 or EventType = 3"); 

      watcher.EventArrived += (s, e) => 
      { 
       string driveName = e.NewEvent.Properties["DriveName"].Value.ToString(); 
       EventType eventType = (EventType)(Convert.ToInt16(e.NewEvent.Properties["EventType"].Value)); 

       string eventName = Enum.GetName(typeof(EventType), eventType); 

       Console.WriteLine("{0}: {1} {2}", DateTime.Now, driveName, eventName); 
      }; 

      watcher.Query = query; 
      watcher.Start(); 

      Console.ReadKey(); 
     } 
    } 
} 
+0

이것은 대단한 일이지만 기기를 꽂거나 뺄 때마다 여러 번 이벤트가 여러 번 발사됩니다. 왜 이런 일이 일어나고 그것을 방지 할 수 있는지 알고 있습니까? – colmde

+0

코드를 게시하지 않았으므로 말할 필요가 없지만 이벤트를 두 번 이상 첨부 할 수 있습니다. –

+0

이것은 *** *** 코드가 아닙니다 !!! 그래서 VitalyB의 답을 여러 라인으로 대체해야합니다. – Turtle

2

위의 모든 대답에 약간 편집 :이 이벤트를 트래핑 서비스에

using System.Management; 

public partial class MainForm : Form 
{ 
    public MainForm() 
    { 
     InitializeComponent(); 

     bgwDriveDetector.DoWork += bgwDriveDetector_DoWork; 
     bgwDriveDetector.RunWorkerAsync(); 
    } 

    private void DeviceInsertedEvent(object sender, EventArrivedEventArgs e) 
    { 
     string driveName = e.NewEvent.Properties["DriveName"].Value.ToString(); 
     MessageBox.Show(driveName + " inserted"); 
    } 

    private void DeviceRemovedEvent(object sender, EventArrivedEventArgs e) 
    { 
     string driveName = e.NewEvent.Properties["DriveName"].Value.ToString(); 
     MessageBox.Show(driveName + " removed"); 
    } 

    void bgwDriveDetector_DoWork(object sender, DoWorkEventArgs e) 
    { 
     var insertQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2"); 
     var insertWatcher = new ManagementEventWatcher(insertQuery); 
     insertWatcher.EventArrived += DeviceInsertedEvent; 
     insertWatcher.Start(); 

     var removeQuery = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 3"); 
     var removeWatcher = new ManagementEventWatcher(removeQuery); 
     removeWatcher.EventArrived += DeviceRemovedEvent; 
     removeWatcher.Start(); 
    } 
}