예제 #1
0
        private object TryAddInternal(
            RegistryChangedEventHandler handler,
            RegistryChangedEventArgs args,
            out bool needNewThread
            )
        {
            WatchEntry newEntry;

            needNewThread = false;

            lock (_eventsLock) {
                if (_entries.Count >= MAXIMUM_WAIT_OBJECTS)
                {
                    needNewThread = true;
                    return(null);
                }
                newEntry = WatchEntry.TryCreate(handler, args);
                if (newEntry == null)
                {
                    return(null);
                }
                _entries.Add(newEntry);
            }

            _itemAdded.Set();

            return(newEntry);
        }
예제 #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);
        }
 private void Registry_Software_Changed(object sender, RegistryChangedEventArgs e) {
     if (RegistryWatcher.Instance.TryAdd(
         e.Hive, e.View, IronPythonCorePath, Registry_Changed,
         recursive: true, notifyValueChange: true, notifyKeyChange: true
     ) != null) {
         e.CancelWatcher = true;
         Registry_Changed(sender, e);
     }
 }
예제 #4
0
 public static WatchEntry TryCreate(RegistryChangedEventHandler callback, RegistryChangedEventArgs args) {
     RegistryKey key;
     using (var baseKey = RegistryKey.OpenBaseKey(args.Hive, args.View)) {
         key = baseKey.OpenSubKey(args.Key, RegistryKeyPermissionCheck.Default, RegistryRights.Notify);
     }
     if (key == null) {
         return null;
     }
     return new WatchEntry(key, callback, args);
 }
예제 #5
0
 private WatchEntry(
     RegistryKey key,
     RegistryChangedEventHandler callback,
     RegistryChangedEventArgs args
 ) {
     _key = key;
     _eventHandle = new AutoResetEvent(false);
     _callback = callback;
     _args = args;
     Register();
 }
 public WatchEntry(RegistryChangedEventHandler callback, RegistryChangedEventArgs args)
 {
     using (var baseKey = RegistryKey.OpenBaseKey(args.Hive, args.View)) {
         _key = baseKey.OpenSubKey(args.Key, RegistryKeyPermissionCheck.Default, RegistryRights.Notify);
     }
     if (_key == null)
     {
         throw new ArgumentException("Key does not exist");
     }
     _eventHandle = new AutoResetEvent(false);
     _callback    = callback;
     _args        = args;
     Register();
 }
 private void Registry_Changed(object sender, RegistryChangedEventArgs e) {
     if (!Exists(e)) {
         // IronPython key no longer exists, so go back to watching
         // Software.
         RegistryWatcher.Instance.Add(
             RegistryHive.LocalMachine, RegistryView.Registry32, "Software",
             Registry_Software_Changed,
             recursive: false, notifyValueChange: false, notifyKeyChange: true
         );
         e.CancelWatcher = true;
     } else {
         DiscoverInterpreterFactories();
         if (_config != null) {
             e.CancelWatcher = true;
         }
     }
 }
        private object AddInternal(RegistryChangedEventHandler handler, RegistryChangedEventArgs args)
        {
            WatchEntry newEntry;

            lock (_eventsLock) {
                if (_entries.Count >= MAXIMUM_WAIT_OBJECTS)
                {
                    return(null);
                }
                newEntry = new WatchEntry(handler, args);
                _entries.Add(newEntry);
            }

            _itemAdded.Set();

            return(newEntry);
        }
예제 #9
0
        private object TryAddInternal(
            RegistryChangedEventHandler handler,
            RegistryChangedEventArgs args,
            out bool needNewThread
        ) {
            WatchEntry newEntry;
            needNewThread = false;

            lock (_eventsLock) {
                if (_entries.Count >= MAXIMUM_WAIT_OBJECTS) {
                    needNewThread = true;
                    return null;
                }
                newEntry = WatchEntry.TryCreate(handler, args);
                if (newEntry == null) {
                    return null;
                }
                _entries.Add(newEntry);
            }

            _itemAdded.Set();

            return newEntry;
        }
예제 #10
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;
        }
예제 #11
0
 private static bool Exists(RegistryChangedEventArgs e)
 {
     using (var root = RegistryKey.OpenBaseKey(e.Hive, e.View))
     using (var key = root.OpenSubKey(e.Key)) {
         return key != null;
     }
 }
예제 #12
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]);
            }
        }
예제 #13
0
 public void Raised(RegistryChangedEventArgs e) {
     Args[Index] = e;
     ArgsSet[Index].Set();
 }
예제 #14
0
 public ArgSetter(RegistryChangedEventArgs[] args, ManualResetEventSlim[] argsSet, int i) {
     Args = args;
     ArgsSet = argsSet;
     Index = i;
 }