Watching Files & Registry keys from .Net (incl IronPython)
Registry watching
As I've noted before, the System.Management namespace has a lot of WMI-related goodies in it. In particular it includes analogues for the RegistryTreeChangeEvent, RegistryKeyChangeEvent and RegistryValueChangeEvent behaviours.
You can get at them as follows
- Create a suitable System.Management.ManagementScope object -- e.g. scope = new ManagementScope("root\\default");
- Create a new WqlEventQuery, call it q, and set the EventClass like q.EventClassName = "RegistryValueChangeEvent";
- Set the appropriate condition depending on the event class --
- For Tree change q.Condition = "Hive='HKEY_LOCAL_MACHINE' and RootPath='Software\\\\RavnaAndTines' ";
- For Key change q.Condition = "Hive='HKEY_LOCAL_MACHINE' and KeyPath='Software\\\\RavnaAndTines' ";
- For Value change q.Condition = "Hive='HKEY_LOCAL_MACHINE' and KeyPath='Software\\\\RavnaAndTines' and ValueName='my key'";
- Create a ManagementEventWatcher(scope, q) and add an appropriate EventArrivedEventHandler to the EventArrived property
- Start() the watcher (probably in its own thread, unless you can create it before the application main loop).
- As part of application termination, Stop() the watcher and Dispose() it.
Alternatively, the WqlEventQuery query string could be set manually, in which case it would be of form like
select * from RegistryTreeChangeEvent where Hive='HKEY_LOCAL_MACHINE' and RootPath='Software\\RavnaAndTines'
Presumably with more SQL-fu one could build a portmanteau query to look at multiple events, rather than creating one watcher per key or value.
The event handler looks like EventArrived(object sender, EventArrivedEventArgs e); the latter argument's NewEvent property is a name/value collection representing the WMI event, like
For Tree change
Hive = HKEY_LOCAL_MACHINE RootPath = Software\RavnaAndTines SECURITY_DESCRIPTOR = TIME_CREATED = 128351151930418266
For Key change
Hive = HKEY_LOCAL_MACHINE KeyPath = Software\RavnaAndTines SECURITY_DESCRIPTOR = TIME_CREATED = 128351153191840662
For Value change
Hive = HKEY_LOCAL_MACHINE KeyPath = Software\RavnaAndTines SECURITY_DESCRIPTOR = TIME_CREATED = 128351161584291834 ValueName = my key
and can obviously be common code for all watcher objects
Sample code
IronPython script used for rapid prototyping/validation
File System watching
This is much simpler, in that the behaviour is kept into one object (System.IO.FileSystemWatcher). there are complexities about multi-threading (if the object is being invoked in conjunction with UI objects); and for handling situations where there is a high frequency of changes expected (by configuring how much space to devote to buffering events).
The FileSystemWatcher is supplied with a directory path, a flag to say whether it should recurse through sub-directories, and a simple filter string to determine which files to watch. Event handlers are then added to the appropriate property (Changed, Created, Deleted, Renamed). The object is then enabled by setting its EnableRaisingEvents property.
The object is, like the ManagementEventWatcher, an IDisposable, but is stopped by clearing the EnableRaisingEvents property.
The event handler looks like EventArrived(object sender, FileSystemEventArgs e); this gives the type of event and the path and name of the file (the new name in the case of a rename, the object being sub-typed to also have an old name and old path property).
3 comments :
Great article. Did convert it into .Net (C#) without a problem. I've searced alot on this topic on the web but couldn't find anything working but your code. I am also pasting my code. Again Thank you.
private static void MonitorRegistryEvents()
{
string QueryStr = "Select * From RegistryKeyChangeEvent Where Hive='HKEY_LOCAL_MACHINE' And KeyPath='SOFTWARE\\\\Yahoo\\\\Companion'";
EventQuery Eq = new EventQuery(QueryStr);
ManagementScope Ms = new ManagementScope("ROOT\\DEFAULT");
ManagementEventWatcher Ew = new ManagementEventWatcher(Ms, Eq);
Ew.EventArrived += new EventArrivedEventHandler(Ew_EventArrived);
Ew.Start();
Console.ReadLine();
Ew.Stop();
}
static void Ew_EventArrived(object sender, EventArrivedEventArgs e)
{
foreach (PropertyData p in e.NewEvent.Properties)
{
Console.WriteLine("{0}, {1}", p.Name, p.Value);
}
}
Actually, the IronPython code was adapted from a sample somewhere in the MSDN documentation for System.Management, but the original might have been in VB.
I've said it before, but it needs saying often -- there is a lot of good stuff hidden in System.Management that up to now only admins with VB (and recently PowerShell) have known about, because they know of it as WMI (whereas most C# programmers know it as "LOL, WUT!?).
Superb
Post a Comment