Exemplo n.º 1
0
            /// <summary>
            /// Invokes the associated event handler.
            /// </summary>
            /// <returns>True if the watcher will be run again; false if the
            /// entry has been closed and can be removed.</returns>
            public bool Invoke(RegistryWatcher sender) {
                if (_key == null) {
                    // Returns true so we don't try and remove null entries from
                    // the list.
                    return true;
                }

                if (!_registered) {
                    return false;
                }

                _callback(sender, _args);

                if (_args.CancelWatcher) {
                    Unregister();
                    return false;
                }

                lock (this) {
                    // only re-register if we haven't been closed
                    if (_registered) {
                        try {
                            Register();
                        } catch (Win32Exception ex) {
                            // If we fail to re-register (probably because the
                            // key has been deleted), there's nothing that can
                            // be done. Fail if we're debugging, otherwise just
                            // continue without registering the watcher again.
                            Debug.Fail("Error registering registry watcher: " + ex.ToString());
                            _registered = false;
                        }
                    }
                }
                return true;
            }
Exemplo n.º 2
0
        /// <summary>
        /// Starts listening for notifications in the specified registry key.
        ///
        /// Each part of the key must be provided separately so that the watcher
        /// can open its own handle.
        /// </summary>
        /// <param name="hive">The hive to watch</param>
        /// <param name="view">The view to watch</param>
        /// <param name="key">The key to watch</param>
        /// <param name="handler">The event handler to invoke</param>
        /// <param name="recursive">True to watch all subkeys as well</param>
        /// <param name="notifyValueChange">
        /// True to notify if a value is added, removed or updated.
        /// </param>
        /// <param name="notifyKeyChange">
        /// True to notify if a subkey is added or removed.
        /// </param>
        /// <param name="tag">
        /// An arbitrary identifier to include with any raised events.
        /// </param>
        /// <returns>
        /// An opaque token that can be pased to Remove, or null if the watcher
        /// could not be added.
        /// </returns>
        public object TryAdd(
            RegistryHive hive,
            RegistryView view,
            string key,
            RegistryChangedEventHandler handler,
            bool recursive         = false,
            bool notifyValueChange = true,
            bool notifyKeyChange   = true,
            object tag             = null
            )
        {
            if (key == null)
            {
                throw new ArgumentNullException("key");
            }
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }
            if (!(notifyValueChange | notifyKeyChange))
            {
                throw new InvalidOperationException("Must wait for at least one type of change");
            }

            var args = new RegistryChangedEventArgs(
                hive,
                view,
                key,
                recursive,
                notifyValueChange,
                notifyKeyChange,
                tag
                );

            int             currentWatcher = -1;
            RegistryWatcher watcher;
            bool            needNewThread;
            var             token = TryAddInternal(handler, args, out needNewThread);

            while (needNewThread)
            {
                if (_extraWatchers == null)
                {
                    _extraWatchers = new List <RegistryWatcher>();
                }
                currentWatcher += 1;
                if (currentWatcher >= _extraWatchers.Count)
                {
                    watcher = new RegistryWatcher();
                    _extraWatchers.Add(watcher);
                }
                else
                {
                    watcher = _extraWatchers[currentWatcher];
                }
                token = watcher.TryAddInternal(handler, args, out needNewThread);
            }
            return(token);
        }
Exemplo n.º 3
0
 object AddWatch(RegistryWatcher watcher,
                 string subkey,
                 Action<RegistryChangedEventArgs> callback,
                 bool recursive = false,
                 bool notifyValueChange = true,
                 bool notifyKeyChange = true) {
     return watcher.Add(
         RegistryHive.CurrentUser,
         RegistryView.Default,
         GetKey(subkey),
         (s, e) => { callback(e); },
         recursive,
         notifyValueChange,
         notifyKeyChange);
 }
Exemplo n.º 4
0
        /// <summary>
        /// Starts listening for notifications in the specified registry key.
        /// 
        /// Each part of the key must be provided separately so that the watcher
        /// can open its own handle.
        /// </summary>
        /// <param name="hive">The hive to watch</param>
        /// <param name="view">The view to watch</param>
        /// <param name="key">The key to watch</param>
        /// <param name="handler">The event handler to invoke</param>
        /// <param name="recursive">True to watch all subkeys as well</param>
        /// <param name="notifyValueChange">
        /// True to notify if a value is added, removed or updated.
        /// </param>
        /// <param name="notifyKeyChange">
        /// True to notify if a subkey is added or removed.
        /// </param>
        /// <param name="tag">
        /// An arbitrary identifier to include with any raised events.
        /// </param>
        /// <returns>
        /// An opaque token that can be pased to Remove, or null if the watcher
        /// could not be added.
        /// </returns>
        public object TryAdd(
            RegistryHive hive,
            RegistryView view,
            string key,
            RegistryChangedEventHandler handler,
            bool recursive = false,
            bool notifyValueChange = true,
            bool notifyKeyChange = true,
            object tag = null
        ) {
            if (key == null) {
                throw new ArgumentNullException("key");
            }
            if (handler == null) {
                throw new ArgumentNullException("handler");
            }
            if (!(notifyValueChange | notifyKeyChange)) {
                throw new InvalidOperationException("Must wait for at least one type of change");
            }

            var args = new RegistryChangedEventArgs(
                hive,
                view,
                key,
                recursive,
                notifyValueChange,
                notifyKeyChange,
                tag
            );

            int currentWatcher = -1;
            RegistryWatcher watcher;
            bool needNewThread;
            var token = TryAddInternal(handler, args, out needNewThread);
            while (needNewThread) {
                if (_extraWatchers == null) {
                    _extraWatchers = new List<RegistryWatcher>();
                }
                currentWatcher += 1;
                if (currentWatcher >= _extraWatchers.Count) {
                    watcher = new RegistryWatcher();
                    _extraWatchers.Add(watcher);
                } else {
                    watcher = _extraWatchers[currentWatcher];
                }
                token = watcher.TryAddInternal(handler, args, out needNewThread);
            }
            return token;
        }
Exemplo n.º 5
0
        public void RegistryWatcherUpdateNonRecursive() {
            string keyName = "RegistryWatcherUpdateNonRecursive";

            SetValue(keyName, "TestValue", "ABC");
            SetValue(keyName + "\\TestKey", "Value", 123);

            using (var watcher = new RegistryWatcher()) {
                RegistryChangedEventArgs args = null;
                var argsSet = new ManualResetEventSlim();

                var watch1 = AddWatch(watcher, keyName,
                    e => { args = e; argsSet.Set(); });

                // Value is set, but does not actually change
                SetValue(keyName, "TestValue", "ABC");
                Assert.IsFalse(argsSet.Wait(TIMEOUT));
                Assert.IsNull(args);

                // Value is changed
                SetValue(keyName, "TestValue", "DEF");
                Assert.IsTrue(argsSet.Wait(TIMEOUT));
                Assert.IsNotNull(args);
                Assert.AreEqual(GetKey(keyName), args.Key);
                argsSet.Reset();
                args = null;

                // Value in subkey is changed, but we don't notice
                SetValue(keyName + "\\TestKey", "Value", 456);
                Assert.IsFalse(argsSet.Wait(TIMEOUT));
                Assert.IsNull(args);

                watcher.Remove(watch1);

                // Value is changed back, but we don't get notified
                SetValue(keyName, "TestValue", "ABC");
                Assert.IsFalse(argsSet.Wait(TIMEOUT));
                Assert.IsNull(args);

                // Value in subkey is changed back, but we don't notice
                SetValue(keyName + "\\TestKey", "Value", 123);
                Assert.IsFalse(argsSet.Wait(TIMEOUT));
                Assert.IsNull(args);
            }
        }
Exemplo n.º 6
0
        public void RegistryWatcher100Keys() {
            string keyName = "RegistryWatcher100Keys";

            for (int i = 0; i < 100; ++i) {
                SetValue(string.Format("{0}\\Key{1}", keyName, i), "Value", "ABC");
            }

            using (var watcher = new RegistryWatcher()) {
                var args = new RegistryChangedEventArgs[100];
                var argsSet = args.Select(_ => new ManualResetEventSlim()).ToArray();
                var tokens = new object[100];

                for (int i = 0; i < 100; ++i) {
                    tokens[i] = AddWatch(watcher, string.Format("{0}\\Key{1}", keyName, i),
                        new ArgSetter(args, argsSet, i).Raised);
                }

                // Change the first value
                SetValue(keyName + "\\Key0", "Value", "DEF");
                Assert.IsTrue(argsSet[0].Wait(TIMEOUT));
                Assert.IsNotNull(args[0]);
                Assert.AreEqual(GetKey(keyName + "\\Key0"), args[0].Key);
                argsSet[0].Reset();
                args[0] = null;

                // Change the last value
                SetValue(keyName + "\\Key99", "Value", "DEF");
                Assert.IsTrue(argsSet[99].Wait(TIMEOUT));
                Assert.IsNotNull(args[99]);
                Assert.AreEqual(GetKey(keyName + "\\Key99"), args[99].Key);
                argsSet[99].Reset();
                args[99] = null;

                watcher.Remove(tokens[0]);
                watcher.Remove(tokens[99]);

                // Change the first value
                SetValue(keyName + "\\Key0", "Value", "GHI");
                Assert.IsFalse(argsSet[0].Wait(TIMEOUT));
                Assert.IsNull(args[0]);

                // Change the last value
                SetValue(keyName + "\\Key99", "Value", "GHI");
                Assert.IsFalse(argsSet[99].Wait(TIMEOUT));
                Assert.IsNull(args[99]);
            }
        }
Exemplo n.º 7
0
        public void RegistryWatcherDeleteRecursive() {
            string keyName = "RegistryWatcherDeleteRecursive";

            SetValue(keyName, "TestValue1", "ABC");
            SetValue(keyName, "TestValue2", "DEF");
            SetValue(keyName, "TestValue3", "GHI");
            SetValue(keyName + "\\TestKey1", "Value", 123);
            SetValue(keyName + "\\TestKey2", "Value", 456);

            using (var watcher = new RegistryWatcher()) {
                RegistryChangedEventArgs args = null;
                var argsSet = new ManualResetEventSlim();

                var watch1 = AddWatch(watcher, keyName,
                    e => { args = e; argsSet.Set(); },
                    recursive: true);

                // Value is deleted
                DeleteValue(keyName, "TestValue2");
                Assert.IsTrue(argsSet.Wait(TIMEOUT));
                Assert.IsNotNull(args);
                Assert.AreEqual(GetKey(keyName), args.Key);
                argsSet.Reset();
                args = null;

                // Value in subkey is deleted
                DeleteValue(keyName + "\\TestKey1", "Value");
                Assert.IsTrue(argsSet.Wait(TIMEOUT));
                Assert.IsNotNull(args);
                Assert.AreEqual(GetKey(keyName), args.Key);
                argsSet.Reset();
                args = null;

                // Subkey is deleted
                DeleteKey(keyName + "\\TestKey1");
                Assert.IsTrue(argsSet.Wait(TIMEOUT));
                Assert.IsNotNull(args);
                Assert.AreEqual(GetKey(keyName), args.Key);
                argsSet.Reset();
                args = null;

                watcher.Remove(watch1);

                // Another value is deleted, but we don't get notified
                DeleteValue(keyName, "TestValue3");
                Assert.IsFalse(argsSet.Wait(TIMEOUT));
                Assert.IsNull(args);

                // Another key is deleted, but we don't get notified
                DeleteKey(keyName + "\\TestKey2");
                Assert.IsFalse(argsSet.Wait(TIMEOUT));
                Assert.IsNull(args);
            }
        }