views:

2698

answers:

4

I'm a newbie to WMI and I need to implement RegistryValueChangeEvent in a C# service.

I need an event handler that gets triggered each time any one of a set of registry values is changed. I want behavior similar to the FileSystemWatcher class's Changed event, but for registry values.

If there's some other technique I could use to accomplish the same task, I'd appreciate that as well. My minimum requirement is that it be a better solution than what I have now: polling every 20 seconds and comparing the registry value with the last result.

Please provide example code in your answer. If I can get an example for watching just one registry value, that would be fine.

I need a solution in .Net 2.0

Thanks.

A: 

You'll need to utilize WMI for it. See http://msdn.microsoft.com/en-us/library/aa393035.aspx

marcc
Ha... I know. That's the part I need help with.
Andrew
I've changed the wording of my question to reflect what I really need. Any additional help?
Andrew
+4  A: 

Are you limited to WMI? If not you can use RegNotifyChangeKeyValue wrappers like RegistryMonitor

felixg
No I am not limited to WMI, that's just the only method I knew of at the time of posting. Thanks for the links. They are helpful. Could you provide some example code though?
Andrew
Are you really that lazy that you cannot click the RegistryMonitor link and download the zip file from CodeProject??
Dave Ganger
Hey, did you offer 350 bounty points for this question? For 350 points, I get example code. mmmmkay.
Andrew
Let's not be rude, guys. The question asked for example code; also, one must bear in mind that some links become stale and example code will be archived here for the foreseeable future. :)
Ed Altorfer
@Dave short answer, and what no one else has said - yes, he is that lazy. that's not a bad thing.
TheSoftwareJedi
@TheSoftwareJedi: Read my comment on a similar answer below. The source code and examples given on that project page DO NOT meet the requirements of my question. Registry Monitor only watches for changes to _KEYS_. Any change to any subkeys or values will fire the event handler. I need an event handler for when a registry _VALUE_ changes. Before anyone calls me lazy, they should take the time to actually read the question. /rant
Andrew
+8  A: 

WMI can sometimes be interesting to work with...I think I understand your question, so take a look at the code snippet below and let me know if it's what you're looking for.

// --------------------------------------------------------------------------------------------------------------------- 
// <copyright file="Program.cs" company="">
//   
// </copyright>
// <summary>
//   Defines the WmiChangeEventTester type.
// </summary>
// ---------------------------------------------------------------------------------------------------------------------
namespace WmiExample
{
    using System;
    using System.Management;

    /// <summary>
    /// </summary>
    public class WmiChangeEventTester
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="WmiChangeEventTester"/> class.
        /// </summary>
        public WmiChangeEventTester()
        {
            try
            {
                // Your query goes below; "KeyPath" is the key in the registry that you
                // want to monitor for changes. Make sure you escape the \ character.
                WqlEventQuery query = new WqlEventQuery(
                     "SELECT * FROM RegistryValueChangeEvent WHERE " +
                     "Hive = 'HKEY_LOCAL_MACHINE'" +
                     @"AND KeyPath = 'SOFTWARE\\Microsoft\\.NETFramework' AND ValueName='InstallRoot'");

                ManagementEventWatcher watcher = new ManagementEventWatcher(query);
                Console.WriteLine("Waiting for an event...");

                // Set up the delegate that will handle the change event.
                watcher.EventArrived += new EventArrivedEventHandler(HandleEvent);

                // Start listening for events.
                watcher.Start();

                // Do something while waiting for events. In your application,
                // this would just be continuing business as usual.
                System.Threading.Thread.Sleep(100000000);

                // Stop listening for events.
                watcher.Stop();
            }
            catch (ManagementException managementException)
            {
                Console.WriteLine("An error occurred: " + managementException.Message);
            }
        }

        /// <summary>
        /// </summary>
        /// <param name="sender">
        /// The sender.
        /// </param>
        /// <param name="e">
        /// The e.
        /// </param>
        private void HandleEvent(object sender, EventArrivedEventArgs e)
        {
            Console.WriteLine("Received an event.");
            // RegistryKeyChangeEvent occurs here; do something.
        }

        /// <summary>
        /// </summary>
        public static void Main()
        {
            // Just calls the class above to check for events...
            WmiChangeEventTester receiveEvent = new WmiChangeEventTester();
        }
    }
}
Ed Altorfer
That's exactly what I'm looking for. I'll try it out and let you know how it works.
Andrew
Great, Andrew. Let me know if you have any trouble re-purposing it for your own use. You can ping me on AIM if you want--e4lt0rf3R (replace the numbers with letters). I will be happy to help you resolve any additional questions you have and then post a summary of them here.
Ed Altorfer
+1  A: 

You really don't need WMI, as others have pointed out. I too have used RegistryMonitor with no problems.

If you need an example, there's already example code for the RegistryMonitor on the page itself. Did you scroll down to this bit on the code project:

public class MonitorSample
{
    static void Main() 
    {
        RegistryMonitor monitor = new 
          RegistryMonitor(RegistryHive.CurrentUser, "Environment");
        monitor.RegChanged += new EventHandler(OnRegChanged);
        monitor.Start();

        while(true);

        monitor.Stop();
    }

    private void OnRegChanged(object sender, EventArgs e)
    {
        Console.WriteLine("registry key has changed");
    }
}
Dan
Yes I did, but... it doesn't meet the requirements of my question. I need example code for an event that gets fired when a specific registry _VALUE_ is changed; not a key. I understand I can get that from RegistryMonitor, but if someone wants to save my time, they have a lot to gain.
Andrew