Exemplo n.º 1
0
        private void MonitorThread()
        {
            try
            {
                IntPtr ptr = IntPtr.Zero;

                lock (this)
                {
                    if (RegistryPath.StartsWith("HKEY_CLASSES_ROOT"))
                    {
                        _monitorKey = Registry.ClassesRoot.OpenSubKey(RegistryPath.Substring(18));
                    }
                    else if (RegistryPath.StartsWith("HKCR"))
                    {
                        _monitorKey = Registry.ClassesRoot.OpenSubKey(RegistryPath.Substring(5));
                    }
                    else if (RegistryPath.StartsWith("HKEY_CURRENT_USER"))
                    {
                        _monitorKey = Registry.CurrentUser.OpenSubKey(RegistryPath.Substring(18));
                    }
                    else if (RegistryPath.StartsWith("HKCU"))
                    {
                        _monitorKey = Registry.CurrentUser.OpenSubKey(RegistryPath.Substring(5));
                    }
                    else if (RegistryPath.StartsWith("HKEY_LOCAL_MACHINE"))
                    {
                        _monitorKey = Registry.LocalMachine.OpenSubKey(RegistryPath.Substring(19));
                    }
                    else if (RegistryPath.StartsWith("HKLM"))
                    {
                        _monitorKey = Registry.LocalMachine.OpenSubKey(RegistryPath.Substring(5));
                    }
                    else if (RegistryPath.StartsWith("HKEY_USERS"))
                    {
                        _monitorKey = Registry.Users.OpenSubKey(RegistryPath.Substring(11));
                    }
                    else if (RegistryPath.StartsWith("HKU"))
                    {
                        _monitorKey = Registry.Users.OpenSubKey(RegistryPath.Substring(4));
                    }
                    else if (RegistryPath.StartsWith("HKEY_CURRENT_CONFIG"))
                    {
                        _monitorKey = Registry.CurrentConfig.OpenSubKey(RegistryPath.Substring(20));
                    }
                    else if (RegistryPath.StartsWith("HKCC"))
                    {
                        _monitorKey = Registry.CurrentConfig.OpenSubKey(RegistryPath.Substring(5));
                    }

                    // Fetch the native handle
                    if (_monitorKey != null)
                    {
                        object hkey = typeof(RegistryKey).InvokeMember(
                            "hkey",
                            BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic,
                            null,
                            _monitorKey,
                            null
                            );

                        ptr = (IntPtr)typeof(SafeHandle).InvokeMember(
                            "handle",
                            BindingFlags.GetField | BindingFlags.Instance | BindingFlags.NonPublic,
                            null,
                            hkey,
                            null);
                    }
                }

                if (ptr != IntPtr.Zero)
                {
                    while (true)
                    {
                        // If this._monitorThread is null that probably means Dispose is being called. Don't monitor anymore.
                        if ((_monitorThread == null) || (_monitorKey == null))
                        {
                            break;
                        }

                        // RegNotifyChangeKeyValue blocks until a change occurs.
                        int result = AdvApi32.RegNotifyChangeKeyValue(ptr, true, _filter, IntPtr.Zero, false);

                        if ((_monitorThread == null) || (_monitorKey == null))
                        {
                            break;
                        }

                        if (result == 0)
                        {
                            if (Changed != null)
                            {
                                RegistryChangeEventArgs e = new RegistryChangeEventArgs(this);
                                Changed(this, e);

                                if (e.Stop)
                                {
                                    break;
                                }
                            }
                        }
                        else
                        {
                            if (Error != null)
                            {
                                Win32Exception ex = new Win32Exception();

                                // Unless the exception is thrown, nobody is nice enough to set a good stacktrace for us. Set it ourselves.
                                typeof(Exception).InvokeMember(
                                    "_stackTrace",
                                    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.SetField,
                                    null,
                                    ex,
                                    new object[] { new StackTrace(true) }
                                    );

                                RegistryChangeEventArgs e = new RegistryChangeEventArgs(this)
                                {
                                    Exception = ex
                                };
                                Error(this, e);
                            }

                            break;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                if (Error != null)
                {
                    RegistryChangeEventArgs e = new RegistryChangeEventArgs(this)
                    {
                        Exception = ex
                    };
                    Error(this, e);
                }
            }
            finally
            {
                Stop();
            }
        }