Link to home
Start Free TrialLog in
Avatar of joseph-narissi
joseph-narissi

asked on

Tring to capture when windows dock/undocks a laptop.

I have tried to get this work in C# and the event never gets caught. Here is my code:

        private ManagementEventWatcher _dockEvent;

        public Window1()
        {
            InitializeComponent();
                                   
            try
            {
                string query = "SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA \"Win32_SystemEnclosure\"";
                _dockEvent = new ManagementEventWatcher(query);
                _dockEvent.EventArrived += new EventArrivedEventHandler(dockEvent_EventArrived);
                _dockEvent.Start();
            }
            catch (ManagementException ex)
            {
            }  
        }

 public void dockEvent_EventArrived(object sender, EventArrivedEventArgs e)
        {

}


Thanks.
Avatar of joseph-narissi
joseph-narissi

ASKER

Ive looked into this and it seems that "ChassisTypes" is set to 10 regardless if it is docked or not. Is this the correct behaviour? We are using a IBM ThinkPad .
I've looked into this too and found it very hard to find the correct information. It seems to me that this class never fires events (which would explain the behavior you get) or that the events are external to the WMI (drivers can add there own events and if they behave well they are added to the WMI).

The number of chassistypes certainly isn't 10 all time, it depends on the computer you have, but I would be surpised if it changed between docking / undocking.

Sorry I can't be of much more help for the moment. It probably requires quite some research to get this trigger going.
Upon further investigation, I have come to the conclusion that using the ChassisTypes is not the way to determine when a laptop is docked/undocked. I tried three different laptops, and none of them change values for the ChassisTypes. I ran a test program to check the value of the ChassisTypes before and after docking and the value remains the same on all three, i different brands laptops.

Is there some other way to determine when the laptop is docked/undocked?

Thanks, Joe
(why "10", shouldn't it be "9" -- laptop?)

Well, I don't seem to find the information you are after other then that the detectable hardware will usually change when docking / undocking. You can check for hardware changes, but then, how would you know what change is caused by docking and what by hot plugging (a mouse for instance)?

Alternatively, but this is a bit over my head, you should be able to track that a different hardware configuration is enabled, which I believe should be visible in a change to CurrentControlSet (but I am unsure). If the WMI doesn't help, you could also monitor the registry change....
remember, ChassisTypes is an array...  so the first element will be 10 for both the docked/undocked, wheras docked gets a 2nd element
aha!
Good point graye! :)
Yeah but it is only returning one type. In fact, on a tablet PC we have it returns a value of 1. So this is not the correct field to be checking.

I believe I have ot capture the WM_DEVICECHANGE event that happens, just not sure exactly what to capture.

I have tried this so far:

      public enum DeviceEvent : int
        {
            Arrival = 0x8000,           //DBT_DEVICEARRIVAL
            QueryRemove = 0x8001,       //DBT_DEVICEQUERYREMOVE
            QueryRemoveFailed = 0x8002, //DBT_DEVICEQUERYREMOVEFAILED
            RemovePending = 0x8003,     //DBT_DEVICEREMOVEPENDING
            RemoveComplete = 0x8004,    //DBT_DEVICEREMOVECOMPLETE
            Specific = 0x8005,          //DBT_DEVICEREMOVECOMPLETE
            Custom = 0x8006             //DBT_CUSTOMEVENT
        }

      public struct BroadcastHeader   //_DEV_BROADCAST_HDR
        {
            public int Size;            //dbch_size
            public DeviceType Type;     //dbch_devicetype
            private int Reserved;       //dbch_reserved
        }

      public enum DeviceType : int
        {
            OEM = 0x00000000,           //DBT_DEVTYP_OEM
            DeviceNode = 0x00000001,    //DBT_DEVTYP_DEVNODE
            Volume = 0x00000002,        //DBT_DEVTYP_VOLUME
            Port = 0x00000003,          //DBT_DEVTYP_PORT
            Net = 0x00000004            //DBT_DEVTYP_NET
        }


        protected override void OnSourceInitialized(EventArgs e)
        {
            // Call base init.
            base.OnSourceInitialized(e);

            // HwndSource class provides access to the Win32 window handle (HWND).
            HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
            if (hwndSource != null)
            {
                // Add the event hook.
                hwndSource.AddHook(new HwndSourceHook(this.hwndSourceHook));
            }
        }

        IntPtr hwndSourceHook(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
        {
            // Check for a device change event.
            if (msg == WM_DEVICECHANGE)
            {
                // See if this is a device arrival event (DOCK).
                if ((int)wParam == DBT_DEVICEARRIVAL)
                {
                    // Get the broadcast header from pointer and then check to see if the
                    // device type is OEM (for DOCK/UNDOCK).
                    BroadcastHeader header = (BroadcastHeader)Marshal.PtrToStructure(lParam, typeof(BroadcastHeader));
                    if (header.Type == DeviceType.Port)
                    {
                        // RaiseDeviceArrived();
                    }
                   
                    int j = 25;
                }
                // otherwise see if this is a device removal event (UNDOCK).
                else if ((int)wParam == DBT_DEVICEREMOVECOMPLETE)
                {
                    BroadcastHeader header = (BroadcastHeader)Marshal.PtrToStructure(lParam, typeof(BroadcastHeader));
                    //RaiseDeviceRemoved();
                    int t = 25;
                }
            }

            return IntPtr.Zero;

        }


And I could just check for Port since that gets added/removed when docked/undocked.

Any other ideas?

Thanks again!
> Any other ideas?

did you check (manually) in the registry the change of currentcontrolset? It is not so hard to monitor the registry..., if that would give you the information you want. It may even be possible to detect a cold undock that way, on next reboot.
ASKER CERTIFIED SOLUTION
Avatar of kickenchicken57
kickenchicken57
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial