コード例 #1
0
 internal static extern int RegNotifyChangeKeyValue(
     SafeRegistryHandle hKey,
     [MarshalAs(UnmanagedType.Bool)] bool watchSubtree,
     RegistryChangeNotificationFilters notifyFilter,
     SafeWaitHandle hEvent,
     [MarshalAs(UnmanagedType.Bool)] bool asynchronous);
コード例 #2
0
        /// <summary>
        /// Returns a Task that completes when the specified registry key changes.
        /// </summary>
        /// <param name="registryKeyHandle">The handle to the open registry key to watch for changes.</param>
        /// <param name="watchSubtree"><c>true</c> to watch the keys descendent keys as well; <c>false</c> to watch only this key without descendents.</param>
        /// <param name="change">Indicates the kinds of changes to watch for.</param>
        /// <param name="cancellationToken">A token that may be canceled to release the resources from watching for changes and complete the returned Task as canceled.</param>
        /// <returns>
        /// A task that completes when the registry key changes, the handle is closed, or upon cancellation.
        /// </returns>
        private static async Task WaitForRegistryChangeAsync(SafeRegistryHandle registryKeyHandle, bool watchSubtree, RegistryChangeNotificationFilters change, CancellationToken cancellationToken)
        {
            IDisposable dedicatedThreadReleaser = null;

            try
            {
                using (var evt = new ManualResetEventSlim())
                {
                    Action registerAction = delegate
                    {
                        int win32Error = NativeMethods.RegNotifyChangeKeyValue(
                            registryKeyHandle,
                            watchSubtree,
                            change,
                            evt.WaitHandle.SafeWaitHandle,
                            true);
                        if (win32Error != 0)
                        {
                            throw new Win32Exception(win32Error);
                        }
                    };

                    if (LightUps.IsWindows8OrLater)
                    {
                        change |= NativeMethods.REG_NOTIFY_THREAD_AGNOSTIC;
                        registerAction();
                    }
                    else
                    {
                        // Engage our downlevel support by using a single, dedicated thread to guarantee
                        // that we request notification on a thread that will not be destroyed later.
                        // Although we *could* await this, we synchronously block because our caller expects
                        // subscription to have begun before we return: for the async part to simply be notification.
                        // This async method we're calling uses .ConfigureAwait(false) internally so this won't
                        // deadlock if we're called on a thread with a single-thread SynchronizationContext.
                        dedicatedThreadReleaser = DownlevelRegistryWatcherSupport.ExecuteOnDedicatedThreadAsync(registerAction).GetAwaiter().GetResult();
                    }

                    await evt.WaitHandle.ToTask(cancellationToken : cancellationToken).ConfigureAwait(false);
                }
            }
            finally
            {
                dedicatedThreadReleaser?.Dispose();
            }
        }
コード例 #3
0
                    static void DoNotify(SafeRegistryHandle registryKeyHandle, bool watchSubtree, RegistryChangeNotificationFilters change, WaitHandle evt)
                    {
                        int win32Error = NativeMethods.RegNotifyChangeKeyValue(
                            registryKeyHandle,
                            watchSubtree,
                            change,
                            evt.SafeWaitHandle,
                            true);

                        if (win32Error != 0)
                        {
                            throw new Win32Exception(win32Error);
                        }
                    }
コード例 #4
0
        /// <summary>
        /// Returns a Task that completes when the specified registry key changes.
        /// </summary>
        /// <param name="registryKey">The registry key to watch for changes.</param>
        /// <param name="watchSubtree"><c>true</c> to watch the keys descendent keys as well; <c>false</c> to watch only this key without descendents.</param>
        /// <param name="change">Indicates the kinds of changes to watch for.</param>
        /// <param name="cancellationToken">A token that may be canceled to release the resources from watching for changes and complete the returned Task as canceled.</param>
        /// <returns>
        /// A task that completes when the registry key changes, the handle is closed, or upon cancellation.
        /// </returns>
        public static Task WaitForChangeAsync(this RegistryKey registryKey, bool watchSubtree = true, RegistryChangeNotificationFilters change = RegistryChangeNotificationFilters.Value | RegistryChangeNotificationFilters.Subkey, CancellationToken cancellationToken = default(CancellationToken))
        {
            Requires.NotNull(registryKey, nameof(registryKey));

            return(WaitForRegistryChangeAsync(registryKey.Handle, watchSubtree, change, cancellationToken));
        }
コード例 #5
0
        /// <summary>
        /// Returns a Task that completes when the specified registry key changes.
        /// </summary>
        /// <param name="registryKeyHandle">The handle to the open registry key to watch for changes.</param>
        /// <param name="watchSubtree"><c>true</c> to watch the keys descendent keys as well; <c>false</c> to watch only this key without descendents.</param>
        /// <param name="change">Indicates the kinds of changes to watch for.</param>
        /// <param name="cancellationToken">A token that may be canceled to release the resources from watching for changes and complete the returned Task as canceled.</param>
        /// <returns>
        /// A task that completes when the registry key changes, the handle is closed, or upon cancellation.
        /// </returns>
        private static async Task WaitForRegistryChangeAsync(SafeRegistryHandle registryKeyHandle, bool watchSubtree, RegistryChangeNotificationFilters change, CancellationToken cancellationToken)
        {
            IDisposable?dedicatedThreadReleaser = null;

            try
            {
                using (var evt = new ManualResetEvent(false))
                {