使用被动扩展来监视registry项

我想跟踪对registry项的更改,例如添加/删除子项,添加/删除/编辑值。 我怎样才能创build一个公开这些变化的IObservable序列?

一种方法是p /调用RegNotifyChangeKeyValue ,一个Win32函数,通知调用者有关指定注册表项的属性或内容的更改。 这个函数在检测到一个变化的时候设置一个事件。 请注意,它必须在持久线程上调用,否则只要线程退出(即使没有发生任何更改),它也会发出信号。 请参阅下面的Rx.Net可能的实现。

using System; using System.ComponentModel; using System.Reactive; using System.Reactive.Concurrency; using System.Reactive.Disposables; using System.Reactive.Linq; using System.Runtime.InteropServices; using System.Threading; using Microsoft.Win32; public class RegistryMonitoringOperations { [Flags] public enum RegChangeNotifyFilter { /// <summary>Notify the caller if a subkey is added or deleted.</summary> Key = 1, /// <summary>Notify the caller of changes to the attributes of the key, /// such as the security descriptor information.</summary> Attribute = 2, /// <summary>Notify the caller of changes to a value of the key. This can /// include adding or deleting a value, or changing an existing value.</summary> Value = 4, /// <summary>Notify the caller of changes to the security descriptor /// of the key.</summary> Security = 8 } private const int KeyQueryValue = 0x0001; private const int KeyNotify = 0x0010; private const int StandardRightsRead = 0x00020000; public static IObservable<Unit> CreateKeyValuesChangedObservable( RegistryHive hive, string subKey, RegChangeNotifyFilter filter, IScheduler registrationScheduler) { return Observable.Create<Unit>( obs => { try { var key = OpenKey(hive, subKey); return new CompositeDisposable( CreateKeyValuesChangedObservable(key, filter).SubscribeOn(registrationScheduler).Subscribe(obs), Disposable.Create(() => RegCloseKey(key))); } catch (Win32Exception e) { obs.OnError(e); return Disposable.Empty; } }); } private static IDisposable SetCallbackWhenSignalled(WaitHandle waitObject, Action action) { var registeredWait = ThreadPool.RegisterWaitForSingleObject(waitObject, (s, t) => action(), null, -1, true); return Disposable.Create(() => registeredWait.Unregister(null)); } private static IObservable<Unit> CreateKeyValuesChangedObservable(IntPtr key, RegChangeNotifyFilter filter) { return Observable.Create<Unit>( obs => { var eventNotify = new AutoResetEvent(false); var result = RegNotifyChangeKeyValue(key, true, filter, eventNotify.SafeWaitHandle.DangerousGetHandle(), true); if (result != 0) { obs.OnError(new Win32Exception(Marshal.GetLastWin32Error())); } return new CompositeDisposable( eventNotify, SetCallbackWhenSignalled( eventNotify, () => { obs.OnNext(Unit.Default); obs.OnCompleted(); })); }).Repeat(); } private static IntPtr OpenKey(RegistryHive hive, string subKey) { IntPtr registryKey; var result = RegOpenKeyEx((int)hive, subKey, 0, StandardRightsRead | KeyQueryValue | KeyNotify, out registryKey); if (result != 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return registryKey; } 

以下是这个函数的一个典型用法:

  RegistryMonitoringOperations.CreateKeyValuesChangedObservable( RegistryHive.LocalMachine, "somepath", RegistryMonitoringOperations.RegChangeNotifyFilter.Value, DispatcherScheduler.Instance) 

正如你上面看到的,避免专用一个线程来调用这个函数的一种方法是使用持久化的UI线程(所以使用调度程序调度器)。 RegNotifyChangeKeyValue在异步模式下立即返回,因此不会阻塞UI。