我正在学习C#,我需要帮助。 我的问题:如何知道USB磁盘是否已安装/卸载? 我找到了WndProd的答案
const int WM_DEVICECHANGE = 0x0219;
const int DBT_DEVICEARRIVAL = 0x8000;
const int DBT_DEVICEREMOVECOMPLETE = 0x8004;
[StructLayout(LayoutKind.Sequential)]
public struct DEV_BROADCAST_HDR
{
public int dbch_size;
public int dbch_devicetype;
public int dbch_reserved;
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_DEVICECHANGE)
{
int EventCode = m.WParam.ToInt32();
Log(string.Format("WM_DEVICECHANGE. Код={0}", EventCode));
switch (EventCode)
{
case DBT_DEVICEARRIVAL:
{
Log("Добавление устройства");
break;
}
case DBT_DEVICEREMOVECOMPLETE:
{
Log("Удаление устройства");
break;
}
}
}
base.WndProc (ref m);
}
和这个版本
public class WMIReceiveEvent
{
public WMIReceiveEvent()
{
try
{
WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent");
ManagementEventWatcher watcher = new ManagementEventWatcher(query);
Console.WriteLine("Waiting for an event...");
watcher.EventArrived += new EventArrivedEventHandler(HandleEvent);
// Start listening for events
watcher.Start();
// Do something while waiting for events
System.Threading.Thread.Sleep(20000);
// Stop listening for events
//watcher.Stop();
//return;
}
catch (ManagementException err)
{
}
}
private void HandleEvent(object sender, EventArrivedEventArgs e)
{
Console.WriteLine("Win32_DeviceChangeEvent event occurred. "+ e.NewEvent.ClassPath.ClassName.ToString());
Console.WriteLine("2_Win32_DeviceChangeEvent event occurred. " + e.NewEvent.Properties.ToString());
Console.ReadLine();
}
}
但是我想要没有WinForm的 DBT_DEVICEARRIVAL 和 DBT_DEVICEREMOVECOMPLETE 的版本。因为对于WndProc需要 System.Windows.Form 而Class必须是后继者“:Form ” 对于WMIReceiveEvent而言,这不是我任务的最佳解决方案。
答案 0 :(得分:2)
您可以使用NativeWindow
代替Form
,仍然使用WndProc(ref Message msg)
。
它实际上是一种看不见的形式,见例:
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
public class MyMessageHandler : NativeWindow
{
private event EventHandler<MyEventArgs> messageReceived;
public event EventHandler<MyEventArgs> MessageReceived
{
add
{
if (messageReceived == null || !messageReceived.GetInvocationList().Contains(value))
messageReceived += value;
}
remove
{
messageReceived -= value;
}
}
public MyMessageHandler()
{
var cp = new CreateParams();
CreateHandle(cp);
}
[System.Security.Permissions.PermissionSet(System.Security.Permissions.SecurityAction.Demand, Name = "FullTrust")]
protected override void WndProc(ref Message msg)
{
var handler = messageReceived;
if (handler != null)
handler(this, new MyEventArgs(msg));
base.WndProc(ref msg);
}
}
答案 1 :(得分:1)
为此编写一个Console应用程序的问题是它没有消息循环(至少,默认情况下不是;你必须自己编写)。
更简单的解决方案是创建Windows窗体项目,但不要显示任何窗体。您实际上将创建一个不显示任何用户界面的“后台”应用程序。 WinForms应用程序会自动为您提供消息泵,使您可以捕获您感兴趣的消息。
答案 2 :(得分:-1)
根据您的应用程序的要求,您也可以进行轮询。您构建一个循环来检查所有可能的驱动器号,如
System.IO.Directory.Exists(为驱动器);
并将其与现有的驱动器号阵列或结构或其他内容进行比较。只要它们不同就创建一个事件。
这将是一个简单的方法,虽然不是很出色的性能。但正如我所说,这取决于你的要求。