USBスティックの挿入時に自動起動し、スティックを取り外すとシャットダウンするUSB分散アプリケーションを作成する可能性を検討しています
.Net と C# を使用します。
C# を使用してこれにアプローチする方法の提案をお探しですか?
更新:これをサービスとして実装する2つの可能なソリューション。
- WndProc をオーバーライドする
、または
- ManagementEventWatcher で WMI クエリを使用する
USBスティックの挿入時に自動起動し、スティックを取り外すとシャットダウンするUSB分散アプリケーションを作成する可能性を検討しています
.Net と C# を使用します。
C# を使用してこれにアプローチする方法の提案をお探しですか?
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();
これは私にとってはうまく機能します。さらに、デバイスに関する詳細情報を見つけることができます。
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);
}
VitalyBの投稿に追加します。
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デバイスが接続されるたびにイベントが発生します。自動検出しようとしているNationalInstrumentsDAQでも動作します。
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();
}
}
}
WMIを使用して挿入イベントを検出することもできます。WM_CHANGEDEVICE メッセージの監視よりも少し複雑ですが、サービスとしてバックグラウンドで実行している場合に役立つ可能性があるウィンドウ ハンドルは必要ありません。
WM_CHANGEDEVICE処理を試してください。
これは、WPF アプリで C# .Net 4.0 を使用して行ったことです。「どのデバイスタイプが挿入/削除されたかを知る方法」に対する答えをまだ探していますが、これが始まりです:
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;
}
}