/// <exception cref="System.Security.SecurityException">
        /// Thrown when current user does not have the permission to access the key
        /// to monitor.
        /// </exception>
        /// <exception cref="System.ArgumentException">
        /// Thrown when the key to monitor does not exist.
        /// </exception>
        public RegistryWatcher(RegistryKey hive, string keyPath, string valueName)
        {
            Hive      = hive ?? throw new ArgumentNullException(nameof(hive));
            KeyPath   = keyPath ?? throw new ArgumentNullException(nameof(keyPath));
            ValueName = valueName ?? throw new ArgumentNullException(nameof(valueName));

            if (!SupportedHives.Contains(hive))
            {
                throw new ArgumentException($"{hive} not supported", nameof(hive));
            }

            // If you set the platform of this project to x86 and run it on a 64bit
            // machine, you will get the Registry Key under
            // HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node when the key path is
            // HKEY_LOCAL_MACHINE\SOFTWARE
            KeyToMonitor = hive.OpenSubKey(keyPath, true);

            if (KeyToMonitor == null)
            {
                throw new ArgumentException($@"The registry key {Hive.Name}\{KeyPath} does not exist");
            }

            if (Value == null)
            {
                throw new ArgumentException($@"The registry value {ValueName} does not exist in {Hive.Name}\{KeyPath}");
            }

            // Construct the query string.
            string queryString = $@"SELECT * FROM RegistryValueChangeEvent WHERE Hive = '{Hive.Name}' AND KeyPath = '{KeyPath.Replace(@"\", @"\\")}' AND ValueName = '{ValueName}'";

            Query = new EventQuery(queryString);

            EventArrived += RegistryWatcher_EventArrived;

            Start();
        }