Configuration Manager 2007 :: Device Monitor Pluggin for SCCM

Here's another one of the interesting utility which I wrote for a customer as an example. So apparently the scenario was that customer was suspecting the Data Could have been compromised from their workstation using USB Devices. Although they had locked USB using group policy but still they wanted to track if a storage device was attached.

Apparently SCCM does collect the Hardware Inventory but a specified interval and it is highly unlikely that the Device be connected at that time , but if it is it will be inventoried. So the solution was to somehow monitor the device activity and then trigger inventory when the event happens, there are multiple ways to do it for example, have a service running on client or probably even have a filter driver written and distributed to client workstations.

In this example we actually will use our own custom service called "MonitorDevPluggin" which will monitor the device activity and trigger inventory when a new device is added or existing device (which was detected earlier) reinserted.

How it works

=============

Although the there are many ways to achieve this , here is a very straight forward example based on WMI created in C#.

Step 1: We use Win32_DeviceChangeEvent Notification Class and subscribe to it and wait

https://msdn.microsoft.com/en-us/library/aa394124(VS.85).aspx

Step2 : Once the event is fired we simply initiate the Hardware Inventory

https://msdn.microsoft.com/en-us/library/cc145196.aspx

** We added a wait logic to wait at least 30 Seconds between two consecutive triggers.

Although more granularity can be achieved based on different API and Classes(for example only trigger for Storage Class Devices etc).

 

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Diagnostics;

using System.ServiceProcess;

using System.Text;

using System.Threading;

using System.Management;

using System.IO;

using System.Resources;

using Microsoft.Win32;

namespace MonitorDevPluggin

{

    public partial class Service1 : ServiceBase

    {

        //Global Variables for application

        public static DateTime cur_time, temp_Time;

        public static int mins;

        public static bool firsttime = true;

       

        //Log File c:\connect.log

        public static string filepath = @"c:\connect.log";

        //enable/disable logging

        public static bool debug = true;

        public static Thread runner;

        public Service1()

        {

            InitializeComponent();

        }

        protected override void OnStart(string[] args)

        {

            try

            {

                Log("Starting Thread ... ");

                runner = new Thread(new ThreadStart(Starter));

                runner.Start();

                Log("Thread Started ");

            }

            catch (Exception rt)

            {

                Log("Exception :: Thread Start " + rt.Message);

            }

        }

        protected override void OnStop()

        {

            try

            {

                Log("Stopping Thread... ");

                runner.Abort();

                Log("Thread Stopped");

            }

            catch (Exception rt)

            {

                Log("Exception :: Thread Abhort " + rt.Message);

            }

        }

       

        static void Starter()

        {

          //Create a Log File for the first time use

            if (firsttime)

            {

                try

                {

                    System.IO.StreamWriter file = new System.IO.StreamWriter(filepath);

                    file.Close();

                }

                catch (Exception p)

                {

                    if (debug) { Log("Exception ## " + p.Message); }

                }

            }

        //Check for Debug info

        // HKLM\Software\\DevicePluginSCCM\enabled : true|false

        // This will help viewing device insertion/reconfiguration events

        try{

        RegistryKey regKeyAppRoot = Registry.LocalMachine.OpenSubKey("Software\\DevicePlugginSCCM");

        if (regKeyAppRoot == null)

        {

            if (debug) { Log("Key Not Found"); }

            regKeyAppRoot = Registry.LocalMachine.CreateSubKey("Software\\DevicePlugginSCCM");

            regKeyAppRoot.SetValue("Enabled", "false", RegistryValueKind.String);

           

        }

      string strWindowsState = (string)regKeyAppRoot.GetValue("enabled");

        if (strWindowsState.ToLower() == "true")

        {

            debug = true;

            Log("Debugging is ON ");

        }

        else

        {

            debug = false;

            Log("Debugging is O ");

        }

     

            }

            catch(Exception e)

            {

                if (debug) { Log("Exception ## " + e.Message); }

            }

        if (debug) { Log("Logging is " + debug.ToString()); }

        /// END OF DEBUG LOGIC

        //subsribe to Device Insert Events // 2 Device Arrival using WMI // 1 Configuration Changed

        string query = @"SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 2 or EventType = 1";

        string managementPath = @"\\.\root\cimv2";

                  

        try

        {

            //Subscribe to the WMI Event Notification Class

            ManagementEventWatcher watcher = new ManagementEventWatcher(new WqlEventQuery(query));

            ManagementScope scope = new ManagementScope(managementPath);

            scope.Connect();

            watcher.Scope = scope;

            if (debug) { Log("Listening for Device Arrival/Modification Events"); }

            temp_Time = DateTime.Now;

            ManagementBaseObject obj;

            while (true)

            {

                obj = watcher.WaitForNextEvent();

                cur_time = DateTime.Now;

                System.TimeSpan Diff_time = cur_time.Subtract(temp_Time);

                mins = Diff_time.Seconds;

                if (debug) { Log("Device Arrival/Modification Detected"); }

                //enforcing minimum 30 seconds delay between 2 consecutive usb pluggins/removals

                        if (mins > 30 || firsttime)

                        {

                                    firsttime = false;

                                    temp_Time = DateTime.Now;

                                    cur_time = temp_Time;

                                    if (debug) { Log("Initiate H/W Inventory "); }

                                   

                                    try

                                    {

                                        RunHardwareInventory();

                               }

                                    catch (Exception Inv)

                                    {

                                        if (debug) { Log("Exception ## " + Inv.Message); }

                                    }

                        }

            }

        }

        catch (Exception n1)

        {

            if (debug) { Log("Exception ## " + n1.Message); }

        }

   

        }

        public static void Log(string s)

        {

            try

            {

                System.IO.StreamWriter file = new System.IO.StreamWriter(filepath, true);

                file.WriteLine(" " + DateTime.Now + " " + s);

                file.Close();

             }

            catch (Exception er)

         {

                if (debug) { Log("Exception ## " + er.Message.ToString()); }

            }

        }

        public static void RunHardwareInventory()

        {

            try

            {

                string actionNameToRun = "Hardware Inventory Collection Cycle";

                CPAPPLETLib.CPAppletMgr controlPanelAppletManager = new CPAPPLETLib.CPAppletMgr();

                foreach (CPAPPLETLib.ClientAction possibleClientAction in controlPanelAppletManager.GetClientActions())

                {

                    if (possibleClientAction.Name == actionNameToRun)

                    {

                        possibleClientAction.PerformAction();

                        if (debug) { Log("Ran: " + possibleClientAction.Name); }

   }

                }

            }

            catch (Exception ex)

            {

                if (debug) { Log("Exception ## " + "Failed to run action. Error: " + ex.Message); }

            }

        }

    }

}

// Below is the example of the this Application's logging

=============

c:\connect.log

=============

4/11/2009 8:37:15 AM Debugging is ON

4/11/2009 8:37:15 AM Logging is True

4/11/2009 8:37:16 AM Listening for Device Arrival/Modification Events

4/11/2009 8:40:01 AM Device Arrival/Modification Detected

4/11/2009 8:40:01 AM Initiate H/W Inventory

4/11/2009 8:40:01 AM Ran: Hardware Inventory Collection Cycle

4/11/2009 8:40:01 AM Device Arrival/Modification Detected

4/11/2009 8:40:16 AM Device Arrival/Modification Detected

4/11/2009 8:40:16 AM Device Arrival/Modification Detected

4/11/2009 8:40:21 AM Device Arrival/Modification Detected

4/11/2009 8:40:21 AM Device Arrival/Modification Detected

4/11/2009 8:40:51 AM Device Arrival/Modification Detected

4/11/2009 8:40:51 AM Initiate H/W Inventory

4/11/2009 8:40:51 AM Ran: Hardware Inventory Collection Cycle

4/11/2009 8:40:51 AM Device Arrival/Modification Detected

=================

InventoryAgent.log

=================

- <Instance ParentClass="CCM_SystemDevices" Class="CCM_SystemDevices" Namespace="\\JEEVANB2\root\cimv2\sms" Content="Updated">
- <CCM_SystemDevices>
<DeviceID>STORAGE\\VOLUME\\1&19F7E59C&0&_??_USBSTOR#DISK&VEN_CORSAIR&PROD_FLASH_VOYAGER&REV_1100#A600000000025492&0#{53F56307-B6BF-11D0-94F2-00A0C91EFB8B}</DeviceID>
<HardwareIDs>STORAGE\\Volume</HardwareIDs>
<IsPnP>0</IsPnP>
<Name>Generic\x0020volume</Name>
</CCM_SystemDevices>
</Instance>
- <Instance ParentClass="CCM_SystemDevices" Class="CCM_SystemDevices" Namespace="\\JEEVANB2\root\cimv2\sms" Content="Updated">
- <CCM_SystemDevices>
<CompatibleIDs>USB\\Class_03&SubClass_01&Prot_02</CompatibleIDs>
<CompatibleIDs>USB\\Class_03&SubClass_01</CompatibleIDs>
<CompatibleIDs>USB\\Class_03</CompatibleIDs>
<DeviceID>USB\\VID_046D&PID_C016\\5&AEE27B&0&2</DeviceID>
<HardwareIDs>USB\\VID_046D&PID_C016&REV_0340</HardwareIDs>
<HardwareIDs>USB\\VID_046D&PID_C016</HardwareIDs>
<IsPnP>1</IsPnP>
<Name>USB\x0020Human\x0020Interface\x0020Device</Name>
</CCM_SystemDevices>
</Instance>
- <Instance ParentClass="CCM_SystemDevices" Class="CCM_SystemDevices" Namespace="\\JEEVANB2\root\cimv2\sms" Content="Updated">
- <CCM_SystemDevices>
<DeviceID>UMB\\UMB\\1&841921D&0&WPDBUSENUMROOT</DeviceID>
<HardwareIDs>UMB\\UMBUS</HardwareIDs>
<IsPnP>1</IsPnP>
<Name>UMBus\x0020Enumerator</Name>
</CCM_SystemDevices>
</Instance>

Download the compiled Version from Here

I have tested this with Windows XP, Windows Vista, Windows Server 2003 and Windows Server 2008 but keep in mind that this is not an official Microsoft tool and just something that I created for DEMO use. As such, Microsoft makes no warranties or guarantee's regarding the applicability of this utility, nor does Microsoft support the use of this tool in any way. This is just one of those 'use at your own risk' type of things that hopefully you'll find helpful.

Jeevan Bisht | Support Escalation Engineer

MonitorSetup.msi