Example #1
0
        /// <summary>
        /// Configure change monitoring for this monitor object
        /// </summary>
        /// <param name="subKey"></param>
        private void ConfigureChangeMonitoring(RegistryKeyMonitor monitor, bool throwOnNotExist)
        {
            string key = monitor.Key;

            // assert preconditions
            Debug.Assert(monitor.hRawKey == UIntPtr.Zero);
            Debug.Assert(monitor.settingsChangedEvent == null);

            // open handle to registry key
            int result = Advapi32.RegOpenKeyEx(
                monitor.HKey,
                key,
                0, KEY.READ, out monitor.hRawKey);

            if (result != ERROR.SUCCESS)
            {
                if (throwOnNotExist)
                {
                    throw new Exception("Failed to open registry key :" + key);
                }
                else
                {
                    Debug.WriteLine("ConfigureChangeMonitoring error: " + result);
                    return;
                }
            }

            // create settings changed event
            monitor.settingsChangedEvent = new ManualResetEvent(false);

            // start monitoring changes
            RegisterForRegistryKeyChanged(monitor);
        }
Example #2
0
        /// <summary>
        /// Deregister for registry change events.
        /// </summary>
        /// <param name="hkey"></param>
        /// <param name="key"></param>
        /// <param name="callback"></param>
        public void RemoveRegistryChangeListener(UIntPtr hkey, string key, RegistryKeyEventHandler callback)
        {
            lock (this)
            {
                RegistryKeyMonitor keyMonitor = GetRegistryKeyMonitor(hkey, key);
                keyMonitor.RemoveChangeListener(callback);

                if (!keyMonitor.HasListeners())
                {
                    //TODO: deregister for change key events
                    //Debug.WriteLine("stop listening for changes to registry key: " + keyMonitor.FullKey, "RegistryMonitor");
                    keyMonitors.Remove(keyMonitor.FullKey);
                    keyMonitor.settingsChangedEvent.Close();

                    //Reset the list of monitor handles.
                    ResetMonitorHandles();

                    //if there are no more listeners, abort the monitor thread.
                    if (keyMonitors.Count == 0)
                    {
                        try
                        {
                            monitorAbortEvent.Set();
                        }
                        catch (ObjectDisposedException)
                        {
                            //occurs when removing change listeners while shutting down.
                        }
                    }
                }
            }
        }
Example #3
0
        /// <summary>
        /// Creates a key monitor object and registers it with the OS for registry change events.
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private RegistryKeyMonitor CreateRegistryKeyMonitor(UIntPtr hkey, string key, bool autoCreateKey)
        {
            if (autoCreateKey)
            {
                RegistryHelper.CreateKey(hkey, key);
            }
            RegistryKeyMonitor monitor = new RegistryKeyMonitor(this, hkey, key);

            ConfigureChangeMonitoring(monitor, false);
            return(monitor);
        }
Example #4
0
        /// <summary>
        /// Retreives the RegistryKeyMonitor associated with the specified registry key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private RegistryKeyMonitor GetRegistryKeyMonitor(UIntPtr hkey, string key, bool autoCreateKey)
        {
            string             fullKey = RegistryHelper.GetKeyString(hkey, key);
            RegistryKeyMonitor monitor = keyMonitors[fullKey] as RegistryKeyMonitor;

            if (monitor == null)
            {
                monitor = CreateRegistryKeyMonitor(hkey, key, autoCreateKey);
                keyMonitors[monitor.FullKey] = monitor;
                ResetMonitorHandles();
                //Debug.WriteLine("start listening for changes to registry key: " + monitor.FullKey, "RegistryMonitor");
            }
            return(monitor);
        }
Example #5
0
        /// <summary>
        /// Monitor changes in the registry key.
        /// </summary>
        private static void RegisterForRegistryKeyChanged(RegistryKeyMonitor monitor)
        {
            // reset the settings changed event so it will not be considered signaled until
            // another change is made to the specified key
            monitor.settingsChangedEvent.Reset();

            // request that the event be signaled when the registry key changes
            int result = Advapi32.RegNotifyChangeKeyValue(monitor.hRawKey,
                                                          false, REG_NOTIFY_CHANGE.LAST_SET, monitor.settingsChangedEvent.SafeWaitHandle, true);

            if (result != ERROR.SUCCESS)
            {
                Trace.WriteLine("Unexpeced failure to monitor reg key (Error code: " + result);
            }
        }
Example #6
0
        /// <summary>
        /// Register a method for callbacks when the specified registry key is changed.
        /// Note: this operation does not recursively register for notifcations from subkeys!
        /// </summary>
        /// <param name="hkey">the HKEY constant (HKEY.CURRENT_USER or HKEY.CLASSES_ROOT)</param>
        /// <param name="key">the registry key path (example: @"Software\AppDataLow\Software\Onfolio\Preferences\Appearance"</param>
        /// <param name="callback">the callback delegate that is invoked when the registry key changes</param>
        public void AddRegistryChangeListener(UIntPtr hkey, string key, RegistryKeyEventHandler callback, bool autoCreateKey)
        {
            if (!autoCreateKey && !RegistryHelper.KeyExists(hkey, key))
            {
                return;
            }

            lock (this)
            {
                RegistryKeyMonitor keyMonitor = GetRegistryKeyMonitor(hkey, key, autoCreateKey);
                keyMonitor.AddChangeListener(callback);

                //launch the monitor thread if it hasn't been started.
                if (monitorThread == null)
                {
                    monitorThread = new Thread(new ThreadStart(this.MonitorChanges));
                    monitorThread.IsBackground = true;
                    monitorThread.Name         = "Registry Monitor";
                    monitorThread.Start();
                }
            }
        }
        /// <summary>
        /// Monitor changes in the registry key.
        /// </summary>
        private static void RegisterForRegistryKeyChanged(RegistryKeyMonitor monitor)
        {
            // reset the settings changed event so it will not be considered signaled until
            // another change is made to the specified key
            monitor.settingsChangedEvent.Reset();

            // request that the event be signaled when the registry key changes
            int result = Advapi32.RegNotifyChangeKeyValue(monitor.hRawKey,
                false, REG_NOTIFY_CHANGE.LAST_SET, monitor.settingsChangedEvent.SafeWaitHandle, true);
            if (result != ERROR.SUCCESS)
            {
                Trace.WriteLine("Unexpeced failure to monitor reg key (Error code: " + result);
            }
        }
        /// <summary>
        /// Configure change monitoring for this monitor object
        /// </summary>
        /// <param name="subKey"></param>
        private void ConfigureChangeMonitoring(RegistryKeyMonitor monitor, bool throwOnNotExist)
        {
            string key = monitor.Key;
            // assert preconditions
            Debug.Assert(monitor.hRawKey == UIntPtr.Zero);
            Debug.Assert(monitor.settingsChangedEvent == null);

            // open handle to registry key
            int result = Advapi32.RegOpenKeyEx(
                monitor.HKey,
                key,
                0, KEY.READ, out monitor.hRawKey);
            if (result != ERROR.SUCCESS)
            {
                if (throwOnNotExist)
                    throw new Exception("Failed to open registry key :" + key);
                else
                {
                    Debug.WriteLine("ConfigureChangeMonitoring error: " + result);
                    return;
                }
            }

            // create settings changed event
            monitor.settingsChangedEvent = new ManualResetEvent(false);

            // start monitoring changes
            RegisterForRegistryKeyChanged(monitor);
        }
 /// <summary>
 /// Creates a key monitor object and registers it with the OS for registry change events.
 /// </summary>
 /// <param name="key"></param>
 /// <returns></returns>
 private RegistryKeyMonitor CreateRegistryKeyMonitor(UIntPtr hkey, string key, bool autoCreateKey)
 {
     if (autoCreateKey)
     {
         RegistryHelper.CreateKey(hkey, key);
     }
     RegistryKeyMonitor monitor = new RegistryKeyMonitor(this, hkey, key);
     ConfigureChangeMonitoring(monitor, false);
     return monitor;
 }
Example #10
0
        /// <summary>
        /// Monitor changes in the registry.
        /// Note: This operation is the main Run() loop for the Registry Monitor Thread.
        /// </summary>
        private void MonitorChanges()
        {
            //use a hashtable to keep track of bulk changes to the registry so that we only fire one event each
            //if multiple changes are made to the registry at once (like when a key is renamed)
            Hashtable regChangeList = new Hashtable();

            while (true)
            {
                SafeHandle[]         monitorHandles;
                RegistryKeyMonitor[] monitors;

                lock (this)                //lock here so that we don't encounter race conditions if registry listeners are being added/removed
                {
                    monitorHandles = MonitorHandles;
                    monitors       = (RegistryKeyMonitor[])ArrayHelper.CollectionToArray(keyMonitors.Values, (typeof(RegistryKeyMonitor)));
                }

                using (SafeHandleArrayHelper safeHandleArrayHelper = new SafeHandleArrayHelper(monitorHandles))
                {
                    uint result =
                        Kernel32.WaitForMultipleObjects((uint)monitorHandles.Length, safeHandleArrayHelper.IntPtrs, false,
                                                        Kernel32.INFINITE);
                    if (result >= 0 && result < FIXED_MONITOR_EVENTS.Length)
                    {
                        //a FIXED_MONITOR_EVENT occured, so handle it.
                        if (result == MONITOR_HANDLES_UPDATED_INDEX)
                        {
                            //the monitorHandlesUpdatedEvent was signalled, so reset it and re-loop
                            //so that we get the latest list of events to monitor.
                            monitorHandlesUpdatedEvent.Reset();
                        }
                        else if (result == MONITOR_ABORT_INDEX)
                        {
                            //the monitorAbortEvent was signaled, so exit the method.
                            //Debug.WriteLine("registry monitor stopped", "RegistryMonitor");
                            monitorAbortEvent.Reset();
                            return;
                        }
                        else
                        {
                            Debug.Fail("unknown FIXED_MONITOR_EVENT detected!");
                        }
                    }
                    else if (result >= WAIT.OBJECT_0 && result <= (WAIT.OBJECT_0 + monitorHandles.Length - 1))
                    {
                        //one or more registry keys have changed, so loop to gather up all of the signaled events
                        uint nextResult = result;
                        while ((result >= WAIT.OBJECT_0 && result <= (WAIT.OBJECT_0 + monitorHandles.Length - 1)) &&
                               !(result >= 0 && result < FIXED_MONITOR_EVENTS.Length))
                        {
                            //a registry change event occured, so add the monitor to the notification list.
                            RegistryKeyMonitor keyMonitor = monitors[result - FIXED_MONITOR_EVENTS.Length];
                            regChangeList[keyMonitor.FullKey] = keyMonitor;

                            //re-register the monitor for change events from the OS
                            RegisterForRegistryKeyChanged(keyMonitor);

                            //get the next pending event from the kernel (without blocking)
                            result =
                                Kernel32.WaitForMultipleObjects((uint)monitorHandles.Length, safeHandleArrayHelper.IntPtrs, false, 0);
                        }

                        //notify the listeners the keys have changed (use the backgroundWorkerQueue so that this thread can't get hosed!)
                        RegistryKeyMonitor[] changedMonitors =
                            (RegistryKeyMonitor[])
                            ArrayHelper.CollectionToArray(regChangeList.Values, typeof(RegistryKeyMonitor));
                        workerQueue.AddWorker(new WaitCallback(backgroundWorker_HandleRegistryKeyChanged),
                                              changedMonitors);

                        //clear the change list.
                        regChangeList.Clear();
                    }
                    else if (result == WAIT.FAILED)
                    {
                        Debug.Fail("Wait failed: " + Marshal.GetLastWin32Error());
                    }
                    else if (result == WAIT.TIMEOUT)
                    {
                        //just re-loop so that we have the latest list of events to monitor.
                    }
                    else
                    {
                        Debug.Fail("unexpected WaitForMultipleObjects() return code!: " + result);
                    }
                }
            }
        }