internal void Start()
        {
            if (!IsRunning)
            {
                _cancelEvent = NativeMethods.CreateEvent(IntPtr.Zero, false, false, Guid.NewGuid().ToString());

                Task.Run(() =>
                {
                    Console.WriteLine($"Registry Key Watcher task is started");

                    IsRunning = true;

                    IntPtr regEvent = NativeMethods.CreateEvent(IntPtr.Zero, false, false, Guid.NewGuid().ToString());
                    IntPtr reg      = IntPtr.Zero;

                    IntPtr[] waitEvents = new IntPtr[] { regEvent, _cancelEvent };

                    UIntPtr hive = UIntPtr.Zero;
                    if (Hive == RegistryHive.LocalMachine)
                    {
                        hive = NativeMethods.Registry.HKEY_LOCAL_MACHINE;
                    }
                    else if (Hive == RegistryHive.CurrentUser)
                    {
                        hive = NativeMethods.Registry.HKEY_CURRENT_USER;
                    }
                    else if (Hive == RegistryHive.Users)
                    {
                        hive = NativeMethods.Registry.HKEY_USERS;
                    }

                    if (hive == UIntPtr.Zero)
                    {
                        Console.WriteLine($"Failed to get hive pointer: Hive={Hive.ToString()}");
                        return;
                    }

                    if (0 != NativeMethods.Registry.RegOpenKeyEx(
                            hive,
                            KeyPath,
                            0,
                            (int)NativeMethods.Registry.RegistryRights.ReadKey | (View == RegistryView.Registry64 ? (int)NativeMethods.Registry.RegWow64Options.KEY_WOW64_64KEY : (int)NativeMethods.Registry.RegWow64Options.KEY_WOW64_32KEY),
                            out reg))
                    {
                        Console.WriteLine($"Failed to open registry: Hive={Hive.ToString()}, KeyPath={KeyPath}");
                        return;
                    }

                    while (true)
                    {
                        if (0 != NativeMethods.Registry.RegNotifyChangeKeyValue(reg, false, NativeMethods.Registry.REG_NOTIFY_CHANGE.LAST_SET, regEvent, true))
                        {
                            Console.WriteLine($"Failed to register RegNotify: Hive={Hive.ToString()}, KeyPath={KeyPath}");
                            break;
                        }

                        if (NativeMethods.WAIT_OBJECT_0 != NativeMethods.WaitForMultipleObjects((uint)waitEvents.Length, waitEvents, false, NativeMethods.INFINITE))
                        {
                            Console.WriteLine($"Registry Monitor Exit.");
                            break;
                        }

                        RegistryKeyChanged?.Invoke(this, new RegistryKeyChangedEventArgs(Hive.ToString(), KeyPath));
                    }

                    if (reg != IntPtr.Zero)
                    {
                        NativeMethods.CloseHandle(reg);
                        reg = IntPtr.Zero;
                    }
                    if (regEvent != IntPtr.Zero)
                    {
                        NativeMethods.CloseHandle(regEvent);
                        regEvent = IntPtr.Zero;
                    }
                    if (_cancelEvent != IntPtr.Zero)
                    {
                        NativeMethods.CloseHandle(_cancelEvent);
                        _cancelEvent = IntPtr.Zero;
                    }

                    Console.WriteLine($"Registry Key Watcher task is finished");
                });
            }
        }
 private void RegistryWatcher_EventArrived(object sender, EventArrivedEventArgs e)
 {
     RegistryKeyChanged?.Invoke(sender, new RegistryKeyChangedEventArgs(e.NewEvent));
 }