Sunday, April 19, 2015

CombineLastest on Several IObservables


// Source code at http://rxx.codeplex.com/ is the critical part of this solution
       static void Main(string[] args)
        {
            DateTime dtStart = DateTime.Now;
            var mktData = GenerateObservable<MarketData>(1, dt => new MarketData() { DepthIndex=RandomInt(10),Qty=RandomInt(777) }, 1, dt => dt < dtStart.AddSeconds(30));
            var grpByDepthMktData=   mktData.GroupBy(k => k.DepthIndex).Select(g => new QtyAt(g.Key, g));

            grpByDepthMktData.Select(d => d.Qtys.StartWith(0)).CombineLatest().Select(t => t.Sum()).Subscribe(d=>Console.WriteLine("sum all "+d));

            var mktData1 = mktData.Where(m => m.DepthIndex >= 1);
            var grpByDepthMktData1 = mktData1.GroupBy(k => k.DepthIndex).Select(g => new QtyAt(g.Key, g));

            grpByDepthMktData1.Select(d => d.Qtys.StartWith(0)).CombineLatest().Select(t => t.Sum()).Subscribe(d => Console.WriteLine(d));

         Console.ReadLine();
}

        static IObservable<T> GenerateObservable<T>(int seconds4Iteration, Func<DateTime, T> newT, int nextInSeconds, Func<DateTime, bool> continuation)
        {
            DateTime dtStart = DateTime.Now;
            return Observable.Generate(dtStart, continuation, dt => dt.AddSeconds(seconds4Iteration), newT, dt => TimeSpan.FromSeconds(nextInSeconds));
        }

       static int? RandomInt(int max)
        {
            
            Random r=new Random();
            return r.Next(max);
        }


    public class MarketData
    {
        public int? DepthIndex;
        public decimal? Qty;
    }

    public class QtyAt
    {
        public int? Depth;
        public IObservable<decimal?> Qtys;
        public QtyAt(int? depth, IObservable<MarketData> qtys)
        {
            Qtys = qtys.Select(m=>m.Qty);
        }
    }


    public static partial class Observable2
    {

        public static IObservable<Tuple<T1, T2>> CombineLatest<T1, T2>(this IObservable<T1> first, IObservable<T2> second)
        {
            return first.CombineLatest(second, Tuple.Create);
        }

        public static IObservable<IList<TSource>> CombineLatest<TSource>(this IEnumerable<IObservable<TSource>> sources)
        {
            return Observable.Defer(() =>
            {
                var count = 0;
                var completed = false;

                return sources.MarkLast()
                    .Select(tuple =>
                    {
                        count++;
                        completed = tuple.Item1;

                        return tuple.Item2;
                    })
                    .ToObservable()
                    .CombineLatest()
                    .SkipWhile(list => !completed || list.Count < count);
            });
        }

        internal static IEnumerable<Tuple<bool, TSource>> MarkLast<TSource>(this IEnumerable<TSource> source)
        {

            using (var enumerator = source.GetEnumerator())
            {
                if (enumerator.MoveNext())
                {
                    bool moveNext;

                    do
                    {
                        var value = enumerator.Current;

                        moveNext = enumerator.MoveNext();

                        yield return Tuple.Create(!moveNext, value);
                    }
                    while (moveNext);
                }
            }
        }

          public static IObservable<IList<TSource>> CombineLatest<TSource>(this IObservable<IObservable<TSource>> sources)
  {

   return Observable.Create<IList<TSource>>(
    observer =>
    {
     var gate = new object();

     var latest = new List<TSource>();
     var hasValueFlags = new List<bool>();

     var sourceCount = 0;
     var consecutiveActiveSourcesCount = 0;
     var outerCompleted = false;

     var outerSubscription = new SingleAssignmentDisposable();
     var disposables = new CompositeDisposable(outerSubscription);

     outerSubscription.Disposable = sources.Subscribe(
      source =>
      {
       int index;

       lock (gate)
       {
        sourceCount++;

        index = latest.Count;

        latest.Add(default(TSource));
        hasValueFlags.Add(false);
       }

       var subscription = new SingleAssignmentDisposable();

       disposables.Add(subscription);

       subscription.Disposable = source.Subscribe(
        value =>
        {
         lock (gate)
         {
          latest[index] = value;

          if (consecutiveActiveSourcesCount < hasValueFlags.Count)
          {
           hasValueFlags[index] = true;

           while (consecutiveActiveSourcesCount < hasValueFlags.Count && hasValueFlags[consecutiveActiveSourcesCount])
           {
            consecutiveActiveSourcesCount++;
           }
          }

          if (consecutiveActiveSourcesCount >= 2)
          {
           observer.OnNext(latest.Take(consecutiveActiveSourcesCount).ToList().AsReadOnly());
          }
         }
        },
        observer.OnError,
        () =>
        {
         bool completeNow;

         lock (gate)
         {
          disposables.Remove(subscription);

          sourceCount--;

          completeNow = outerCompleted && sourceCount == 0;
         }

         if (completeNow)
         {
          observer.OnCompleted();
         }
        });
      },
      observer.OnError,
      () =>
      {
       bool completeNow;

       lock (gate)
       {
        outerCompleted = true;

        completeNow = sourceCount == 0;
       }

       if (completeNow)
       {
        observer.OnCompleted();
       }
      });

     return disposables;
    });
  }
 
    }

Thursday, March 5, 2015

Break Gradient Color into Pieces

       void GetGradiencePieces()
        {
            
            var lgbHigh = new LinearGradientBrush(Colors.Red, Colors.White, 90.0);
            var lgbLow = new LinearGradientBrush(Colors.Orange, Colors.White, 90.0);
            Color clr;
            for (int i = 1; i < 21; i++)
            {
                if (i > 10 && i < 30)
                {
                    float f = (i - 10)/20.0f;
                     clr = GetColorSampleFromLinearGradientBrush(lgbHigh, f);
                }
            }

        }

        Color GetColorSampleFromLinearGradientBrush(LinearGradientBrush lgb, float y)
        {
            double max = lgb.GradientStops.Max(n => n.Offset);

            double min = lgb.GradientStops.Min(n => n.Offset);


            //Find gradient stops that surround the input value
            GradientStop gs0 = lgb.GradientStops.OrderBy(n => n.Offset).Last();
            GradientStop gs1 = lgb.GradientStops.OrderBy(n => n.Offset).First();
            Color cx = new Color();
            if (lgb.ColorInterpolationMode == ColorInterpolationMode.ScRgbLinearInterpolation)
            {
                float aVal = (gs1.Color.ScA - gs0.Color.ScA) * y + gs0.Color.ScA;
                float rVal = (gs1.Color.ScR - gs0.Color.ScR) * y + gs0.Color.ScR;
                float gVal = (gs1.Color.ScG - gs0.Color.ScG) * y + gs0.Color.ScG;
                float bVal = (gs1.Color.ScB - gs0.Color.ScB) * y + gs0.Color.ScB;
                cx = Color.FromScRgb(aVal, rVal, gVal, bVal);
            }
            else
            {
                byte aVal = (byte)((gs1.Color.A - gs0.Color.A) * y + gs0.Color.A);
                byte rVal = (byte)((gs1.Color.R - gs0.Color.R) * y + gs0.Color.R);
                byte gVal = (byte)((gs1.Color.G - gs0.Color.G) * y + gs0.Color.G);
                byte bVal = (byte)((gs1.Color.B - gs0.Color.B) * y + gs0.Color.B);
                cx = Color.FromArgb(aVal, rVal, gVal, bVal);
            }
            return cx;
        }

Saturday, February 28, 2015

INPC with Equality check


    public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public void SetProperty<T>(ref T field, T value, Expression<Func<T>> exp)
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return;
            field = value;
            if (PropertyChanged != null)
            {
                MemberExpression me = exp.Body as MemberExpression;
                if (me != null && me.Member != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(me.Member.Name));
            }
        }
    }

Saturday, February 7, 2015

Code Snippet to walk Visual Tree for Dev Express GridControl Specifics


        private void AssociatedObject_LayoutUpdated(object sender, EventArgs e)
        {
            var v = AssociatedObject.View;

            HierarchyPanel hp = VisualTreeHelpers.FindChild(v);
            GridRow grs = VisualTreeHelpers.FindChild(hp);
            var ie = v.FindLogicalChildren();
            var ie2 = v.FindVisualChildren();
            int i1 = ie.Count();
            int i2 = ie2.Count();

            int i3 = hp.FindVisualChildren().Count();  
        }

        private GridControl dgc;
        private bool b;
        private void AssociatedObject_MasterRowExpanded(object sender, RowEventArgs e)
        {
             dgc= AssociatedObject.GetDetail(e.RowHandle) as GridControl;
             dgc.ItemsSourceChanged+=dgc_ItemsSourceChanged;
            var i = dgc.ItemsSource;
            var col = dgc.ItemsSource as ObservableCollection;
            col.CollectionChanged += col_CollectionChanged;

        }

        private void BlankoutColumns(int rowHandle)
        {
            var dgc = AssociatedObject.GetVisibleDetail(rowHandle) as GridControl;
            var dc = dgc.View.DataControl as GridControl;
            
            for (int i = 0; i < dc.VisibleRowCount; i++)
            {
                int h = dc.GetRowHandleByVisibleIndex(i);
                foreach (var c in  dc.Columns) 
                {
                    if (c.Name == "ChildName")
                    {
                        var v = dc.GetCellValue(h, c);
                       // c.CellTemplate = new DataTemplate(); // take out data template so next update never shown
                     //   dc.SetCellValue(h, c, null); // blank out already rendered text
                    }
                }
            }
        }
            DependencyPropertyDescriptor propertyDescriptor = DependencyPropertyDescriptor.FromProperty(GridViewBase.VisibleColumnsProperty, typeof(GridViewBase));
            propertyDescriptor.AddValueChanged(AssociatedObject.View, VisibleColumnsChanged);


Thursday, January 1, 2015

Enable/Disable, Start/Stop PnP device -- not for production



namespace JQD
{
    #region Enum and StructLayout, safe handle

    internal enum DiFunction
    {
        SelectDevice = 1,
        InstallDevice = 2,
        AssignResources = 3,
        Properties = 4,
        Remove = 5,
        FirstTimeSetup = 6,
        FoundDevice = 7,
        SelectClassDrivers = 8,
        ValidateClassDrivers = 9,
        InstallClassDrivers = (int)0xa,
        CalcDiskSpace = (int)0xb,
        DestroyPrivateData = (int)0xc,
        ValidateDriver = (int)0xd,
        Detect = (int)0xf,
        InstallWizard = (int)0x10,
        DestroyWizardData = (int)0x11,
        PropertyChange = (int)0x12,
        EnableClass = (int)0x13,
        DetectVerify = (int)0x14,
        InstallDeviceFiles = (int)0x15,
        UnRemove = (int)0x16,
        SelectBestCompatDrv = (int)0x17,
        AllowInstall = (int)0x18,
        RegisterDevice = (int)0x19,
        NewDeviceWizardPreSelect = (int)0x1a,
        NewDeviceWizardSelect = (int)0x1b,
        NewDeviceWizardPreAnalyze = (int)0x1c,
        NewDeviceWizardPostAnalyze = (int)0x1d,
        NewDeviceWizardFinishInstall = (int)0x1e,
        Unused1 = (int)0x1f,
        InstallInterfaces = (int)0x20,
        DetectCancel = (int)0x21,
        RegisterCoInstallers = (int)0x22,
        AddPropertyPageAdvanced = (int)0x23,
        AddPropertyPageBasic = (int)0x24,
        Reserved1 = (int)0x25,
        Troubleshooter = (int)0x26,
        PowerMessageWake = (int)0x27,
        AddRemotePropertyPageAdvanced = (int)0x28,
        UpdateDriverUI = (int)0x29,
        Reserved2 = (int)0x30
    }

    [Flags()]
    internal enum SetupDiGetClassDevsFlags
    {
        Default = 1,
        Present = 2,
        AllClasses = 4,
        Profile = 8,
        DeviceInterface = (int)0x10
    }


    internal enum StateChangeAction
    {
        Enable = 1,
        Disable = 2,
        PropChange = 3,
        Start = 4,
        Stop = 5
    }

    [Flags()]
    internal enum Scopes
    {
        Global = 1,
        ConfigSpecific = 2,
        ConfigGeneral = 4
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct PropertyChangeParameters
    {
        public int Size;
        // part of header. It's flattened out into 1 structure.
        public DiFunction DiFunction;
        public StateChangeAction StateChange;
        public Scopes Scope;
        public int HwProfile;
    }

    internal enum SetupApiError
    {
        NoAssociatedClass = unchecked((int)0xe0000200),
        ClassMismatch = unchecked((int)0xe0000201),
        DuplicateFound = unchecked((int)0xe0000202),
        NoDriverSelected = unchecked((int)0xe0000203),
        KeyDoesNotExist = unchecked((int)0xe0000204),
        InvalidDevinstName = unchecked((int)0xe0000205),
        InvalidClass = unchecked((int)0xe0000206),
        DevinstAlreadyExists = unchecked((int)0xe0000207),
        DevinfoNotRegistered = unchecked((int)0xe0000208),
        InvalidRegProperty = unchecked((int)0xe0000209),
        NoInf = unchecked((int)0xe000020a),
        NoSuchHDevinst = unchecked((int)0xe000020b),
        CantLoadClassIcon = unchecked((int)0xe000020c),
        InvalidClassInstaller = unchecked((int)0xe000020d),
        DiDoDefault = unchecked((int)0xe000020e),
        DiNoFileCopy = unchecked((int)0xe000020f),
        InvalidHwProfile = unchecked((int)0xe0000210),
        NoDeviceSelected = unchecked((int)0xe0000211),
        DevinfolistLocked = unchecked((int)0xe0000212),
        DevinfodataLocked = unchecked((int)0xe0000213),
        DiBadPath = unchecked((int)0xe0000214),
        NoClassInstallParams = unchecked((int)0xe0000215),
        FileQueueLocked = unchecked((int)0xe0000216),
        BadServiceInstallSect = unchecked((int)0xe0000217),
        NoClassDriverList = unchecked((int)0xe0000218),
        NoAssociatedService = unchecked((int)0xe0000219),
        NoDefaultDeviceInterface = unchecked((int)0xe000021a),
        DeviceInterfaceActive = unchecked((int)0xe000021b),
        DeviceInterfaceRemoved = unchecked((int)0xe000021c),
        BadInterfaceInstallSect = unchecked((int)0xe000021d),
        NoSuchInterfaceClass = unchecked((int)0xe000021e),
        InvalidReferenceString = unchecked((int)0xe000021f),
        InvalidMachineName = unchecked((int)0xe0000220),
        RemoteCommFailure = unchecked((int)0xe0000221),
        MachineUnavailable = unchecked((int)0xe0000222),
        NoConfigMgrServices = unchecked((int)0xe0000223),
        InvalidPropPageProvider = unchecked((int)0xe0000224),
        NoSuchDeviceInterface = unchecked((int)0xe0000225),
        DiPostProcessingRequired = unchecked((int)0xe0000226),
        InvalidCOInstaller = unchecked((int)0xe0000227),
        NoCompatDrivers = unchecked((int)0xe0000228),
        NoDeviceIcon = unchecked((int)0xe0000229),
        InvalidInfLogConfig = unchecked((int)0xe000022a),
        DiDontInstall = unchecked((int)0xe000022b),
        InvalidFilterDriver = unchecked((int)0xe000022c),
        NonWindowsNTDriver = unchecked((int)0xe000022d),
        NonWindowsDriver = unchecked((int)0xe000022e),
        NoCatalogForOemInf = unchecked((int)0xe000022f),
        DevInstallQueueNonNative = unchecked((int)0xe0000230),
        NotDisableable = unchecked((int)0xe0000231),
        CantRemoveDevinst = unchecked((int)0xe0000232),
        InvalidTarget = unchecked((int)0xe0000233),
        DriverNonNative = unchecked((int)0xe0000234),
        InWow64 = unchecked((int)0xe0000235),
        SetSystemRestorePoint = unchecked((int)0xe0000236),
        IncorrectlyCopiedInf = unchecked((int)0xe0000237),
        SceDisabled = unchecked((int)0xe0000238),
        UnknownException = unchecked((int)0xe0000239),
        PnpRegistryError = unchecked((int)0xe000023a),
        RemoteRequestUnsupported = unchecked((int)0xe000023b),
        NotAnInstalledOemInf = unchecked((int)0xe000023c),
        InfInUseByDevices = unchecked((int)0xe000023d),
        DiFunctionObsolete = unchecked((int)0xe000023e),
        NoAuthenticodeCatalog = unchecked((int)0xe000023f),
        AuthenticodeDisallowed = unchecked((int)0xe0000240),
        AuthenticodeTrustedPublisher = unchecked((int)0xe0000241),
        AuthenticodeTrustNotEstablished = unchecked((int)0xe0000242),
        AuthenticodePublisherNotTrusted = unchecked((int)0xe0000243),
        SignatureOSAttributeMismatch = unchecked((int)0xe0000244),
        OnlyValidateViaAuthenticode = unchecked((int)0xe0000245)
    }

    [StructLayout(LayoutKind.Sequential)]
    internal struct DeviceInfoData
    {
        public int Size;
        public Guid ClassGuid;
        public int DevInst;
        public IntPtr Reserved;
    }

    internal class SafeDeviceInfoSetHandle : SafeHandleZeroOrMinusOneIsInvalid
    {

        public SafeDeviceInfoSetHandle()
            : base(true)
        {
        }

        protected override bool ReleaseHandle()
        {
            return NativeMethods.SetupDiDestroyDeviceInfoList(this.handle);
        }

    }

    #endregion

    internal class NativeMethods
    {

        private const string setupapi = @"setupapi.dll";

        private NativeMethods()
        {
        }

        [DllImport(@"setupapi.dll", SetLastError = true)]
        public static extern bool SetupDiClassGuidsFromName(string ClassName, ref Guid ClassGuidArray1stItem, UInt32 ClassGuidArraySize, out UInt32 RequiredSize);

        [DllImport(setupapi, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetupDiCallClassInstaller(DiFunction installFunction, SafeDeviceInfoSetHandle deviceInfoSet, [In()]
ref DeviceInfoData deviceInfoData);

        [DllImport(setupapi, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetupDiEnumDeviceInfo(SafeDeviceInfoSetHandle deviceInfoSet, int memberIndex, ref DeviceInfoData deviceInfoData);

        [DllImport(setupapi, CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode, SetLastError = true)]
        public static extern SafeDeviceInfoSetHandle SetupDiGetClassDevs([In()]ref Guid classGuid, [MarshalAs(UnmanagedType.LPWStr)]string enumerator, IntPtr hwndParent, SetupDiGetClassDevsFlags flags);

        [DllImport(@"setupapi.dll", SetLastError = true, CharSet = CharSet.Auto)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetupDiGetDeviceInstanceId(
         IntPtr DeviceInfoSet,
         ref DeviceInfoData did,
         [MarshalAs(UnmanagedType.LPTStr)] StringBuilder DeviceInstanceId,
         int DeviceInstanceIdSize,
         out int RequiredSize
        );

        [SuppressUnmanagedCodeSecurity()]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [DllImport(setupapi, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetupDiDestroyDeviceInfoList(IntPtr deviceInfoSet);

        [DllImport(setupapi, CallingConvention = CallingConvention.Winapi, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool SetupDiSetClassInstallParams(SafeDeviceInfoSetHandle deviceInfoSet, [In()]ref DeviceInfoData deviceInfoData, [In()]ref PropertyChangeParameters classInstallParams, int classInstallParamsSize);

        [DllImport("setupapi.dll", CharSet = CharSet.Auto)]
        public static extern int CM_Get_Device_ID(
           UInt32 dnDevInst,
           IntPtr buffer,
           int bufferLen,
           int flags
        );
    }
}


        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            bool enable = true;
            NewMethod(enable);
        }

        private static void NewMethod(bool enable)
        {
            Guid classGuid = new Guid("745a17a0-74d3-11d0-b6fe-00a0c90f57da");
            JQD.SafeDeviceInfoSetHandle handle = JQD.NativeMethods.SetupDiGetClassDevs(ref classGuid, null, IntPtr.Zero, JQD.SetupDiGetClassDevsFlags.Present);

            List lit = new List();
            JQD.DeviceInfoData[] diDataAll = GetDeviceInfoData(handle);
           
            foreach (JQD.DeviceInfoData did in diDataAll)
            {
                int nBytes = 32;
                IntPtr ptrInstanceBuf = Marshal.AllocHGlobal(nBytes);
                JQD.NativeMethods.CM_Get_Device_ID((uint)did.DevInst, ptrInstanceBuf, nBytes, 0);
                string InstanceID = Marshal.PtrToStringAuto(ptrInstanceBuf);
                if (InstanceID.Contains(@"VID_053A&PID_0B01"))
                {
                    lit.Add(did);
                }

                Marshal.FreeHGlobal(ptrInstanceBuf);
            }
            //return;
            //foreach (JQD.DeviceInfoData did in lit)
            //{
                JQD.DeviceInfoData diData = lit[0];

                JQD.PropertyChangeParameters @params = new JQD.PropertyChangeParameters();

                @params.Size = 8;
                @params.DiFunction = JQD.DiFunction.PropertyChange;
                @params.Scope = JQD.Scopes.Global;
                if (enable)
                {
                    @params.StateChange = JQD.StateChangeAction.Start;
                }
                else
                {
                    @params.StateChange = JQD.StateChangeAction.Stop;
                }

                bool result = JQD.NativeMethods.SetupDiSetClassInstallParams(handle, ref diData, ref @params, Marshal.SizeOf(@params));

                result = JQD.NativeMethods.SetupDiCallClassInstaller(JQD.DiFunction.PropertyChange, handle, ref diData);
            //}
        }

        private static JQD.DeviceInfoData[] GetDeviceInfoData(JQD.SafeDeviceInfoSetHandle handle)
        {
            List data = new List();
            JQD.DeviceInfoData did = new JQD.DeviceInfoData();
            int didSize = Marshal.SizeOf(did);
            did.Size = didSize;
            int index = 0;
            while (JQD.NativeMethods.SetupDiEnumDeviceInfo(handle, index, ref did))
            {
                data.Add(did);
                index += 1;
                did = new JQD.DeviceInfoData();
                did.Size = didSize;
            }
            return data.ToArray();
        }

Query PnP device health Status


            string VendorMatching = "VID_053A&PID_0B01"; // Vendor Id Prod Id Minor Revisioin
            using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_PnPEntity")) //Win32_PnPEntity Win32_USBHub
            {
                foreach (ManagementObject queryObj in searcher.Get())
                {
                    var v = new
                    {
                        ConfigManagerErrorCode = queryObj.Properties["ConfigManagerErrorCode"].Value,
                        Status = queryObj.Properties["Status"].Value,
                        StatusInfo = queryObj.Properties["StatusInfo"].Value,
                        Availability = queryObj.Properties["Availability"].Value,
                        LastErrorCode = queryObj.Properties["LastErrorCode"].Value,

                        DeviceID = queryObj.Properties["DeviceID"].Value,
                        PNPDeviceID = queryObj.Properties["PNPDeviceID"].Value,
                        ClassGuid = queryObj.Properties["ClassGuid"].Value,                        
                        HardwareID = queryObj.Properties["HardwareID"].Value,
                    };
                    if (v.DeviceID.ToString().Contains(VendorMatching)) 
                        
                        Debug.WriteLine(v);
                }
            }

// Win32_PnPEntity class has Error Code
// { ConfigManagerErrorCode = 0, Status = OK, StatusInfo = , Availability = , LastErrorCode = , DeviceID = HID\VID_053A&PID_0B01&MI_01&COL04\9&98E7406&0&0003, PNPDeviceID = HID\VID_053A&PID_0B01&MI_01&COL04\9&98E7406&0&0003, ClassGuid = {745a17a0-74d3-11d0-b6fe-00a0c90f57da}, HardwareID = System.String[] }

WMI USB Play and Play Device Add, Remove and Modify Event Watcher


        private ManagementEventWatcher watcherAttach;
        private ManagementEventWatcher watcherRemove;
        private ManagementEventWatcher watcherMod;

            watcherAttach = new ManagementEventWatcher();

              //object sender, EventArrivedEventArgs e
            watcherAttach.EventArrived += (s,e) =>
                {
                    var propData = e.NewEvent.Properties["TargetInstance"];
                    var mbObj = propData.Value as ManagementBaseObject;
                    if (mbObj.Properties["DeviceID"].Value.ToString().Contains(@"HID\VID_053A&PID_0B01"))
                    {

                     // Instance Id can be passed into various API  instId = queryObj.GetPropertyValue("PNPDeviceID").ToString();
                        Debug.WriteLine("Preh device added");
                    }
                };
            watcherAttach.Query = new WqlEventQuery("SELECT * FROM __InstanceCreationEvent " +
               "WITHIN 2 "+
              "WHERE TargetInstance ISA 'Win32_PnPEntity'");
            watcherAttach.Start();


            watcherRemove.Query =  new WqlEventQuery("SELECT * FROM __InstanceModificationEvent " +
               "WITHIN 2 " +
              "WHERE TargetInstance ISA 'Win32_PnPEntity'");

            watcherMod.Query =  new WqlEventQuery("SELECT * FROM __InstanceDeletionEvent " +
               "WITHIN 2 " +
              "WHERE TargetInstance ISA 'Win32_PnPEntity'");


            watcherAttach.Stop();
            watcherRemove.Stop();
            watcherAttach.Dispose();
            watcherRemove.Dispose();