learns CSharp
learns CSharp

Reputation: 11

Monitoring a port's USB, without WinForm, just only Console Application

I'm learning C# and I need help, please. My question: how to know whether a USB-disk has been mounted/unmounted? I found an answer for 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);

    }

and this version

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

    }

but I would like version for DBT_DEVICEARRIVAL and DBT_DEVICEREMOVECOMPLETE without WinForm. Because for WndProc need System.Windows.Form and Class must be the successor ":Form" And for WMIReceiveEvent not the best solution for my task.

Upvotes: 0

Views: 2218

Answers (3)

mstrptk
mstrptk

Reputation: 21

You can use NativeWindow instead of Form and still use WndProc(ref Message msg). It's practically an invisible form, see example:

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

Upvotes: 2

benJima
benJima

Reputation: 131

Depending on the requirements of your application you might as well do polling. You build a loop checking all possible drive letters like

System.IO.Directory.Exists(driveLetter);

and compare it to an existing drive letter array or struct or whatever. Create an event as soon as they are different.

That would be the easy way though not as fantastic regarding performance. But as I said, it depends on your requirements.

Upvotes: -1

Cody Gray
Cody Gray

Reputation: 244722

The problem with writing a Console application for this is that it doesn't have a message loop (at least, not by default; you would have to write your own).

The simpler solution is to create a Windows Forms project, but just don't show any forms. You would essentially be creating a "background" application that doesn't display any user interface. WinForms applications provide a message pump for you automatically, allowing you to catch the messages you're interested in.

Upvotes: 1

Related Questions