Fractal Life

September 9, 2008

MMC 3.0 Concepts

Filed under: 64-bit — wordpress @ 15:10

I’ve been working on a MMC v3.0 snap-in for our Oak City Software project to manage configuration settings (licensing, etc) and was having some problems getting it to respond to the standard action verbs.

These are the items you see over in the Actions pane (select Customize View, then check the Action Pane checkbox) that represent standard things you can do with/to a snapin. Stuff like Refresh, Cut, Paste, Properties.

I was trying to implement the Refresh verb and it just wasn’t working.

What it turns out is that there is a disconnect in the object hierarchy between your class derived from ScopeNode and your class that derives from UserControl and implements IFormViewControl (if you’re doing a WinForm view like I was). At runtime, there is one instance of your ScopeNode, but there could be multiple instances of your FormViewControl class because the MMC environment is MDI, not SDI. So the node has no way of knowing which instance of your FormViewControl to call to tell to refresh itself. And since MMC is the one creating the instance (you tell it the Type, and it creates it for you), there’s no way for you to stick a reference to your control into the node, or other tricky ways.

What you have to do is implement the Observer pattern so that your FormViewControl subscribes to an event notificaton from the Node, and thus would know when it has to refresh itself (or cut, paste, show the properties, etc).

Here’s a code sample. First, your Node class:

 // Represents the license node in the MMC tree
public class OcsLicenseNode
         : ScopeNode
{
   // FormViewControl instances subscribe to this to know when to refresh themselves.
   public event EventHandler RefreshEvent;

   // Constructor
   public OcsLicenseNode()
   {
      EnabledStandardVerbs = StandardVerbs.Refresh;
      FormViewDescription rootView = new FormViewDescription(typeof(OcsRootNodeControl));
      rootView.DisplayName = "OCS License"; // TODO: get from resource file
      rootView.LanguageIndependentName = "OCS License";
      rootView.ViewType = typeof(OcsRootNodeFormView);
      rootView.ControlType = typeof(OcsLicenseNodeControl);
   }

   // Called when the user selects the Refresh action
   protected override void OnRefresh(AsyncStatus status)
   {
      base.OnRefresh(status);
      // Notify observers
      if (RefreshEvent != null)
         RefreshEvent(this, null);
   }
}

Now the FormViewControl implementation:

 // The usercontrol that is shown when the user selects the License node in the MMC tree
public partial class OcsLicenseNodeControl
   : UserControl, IFormViewControl
{
   private FormView _view;

   // Constructor
   public OcsLicenseNodeControl()
   {
      InitializeComponent();
   }

   // Forces the control to invalidate its client area and immediately redraw itself and any child controls.
   public override void Refresh()
   {
      base.Refresh();

      // See if they already have a license, and if so, display it.
      //
      // {snip}
      //
   }

   // Initializes the specified view.
   public void Initialize(FormView view)
   {
      Dock = DockStyle.Fill;
      _view = view;
   }
}

For production code, you’d use a try-catch block in the spot where we’re invoking the delegate — if one of the event implementations causes an exception to be thrown, then it would prevent any of the other observers in the delegate linked-list from being called.

Sidenote: posting code inside Wordpress is amazingly annoying. Enough so that I might need to consider changing my blog software after only using it for a few months. Getting just this little bit required me writing a VS.NET add-in to convert spaces to non-breaking space HTML entities, replace newlines with break tags, and several other unobvious tweaks. Not to mention Wordpress itself behaving erratically.

May 20, 2008

Implications of using Vista 64-bit when writing 32-bit code

Filed under: 64-bit — wordpress @ 19:48

I run Vista 64-bit Enterprise (under Bootcamp on my Mac Book Pro), and ran into an interesting side-effect yesterday.  At least it was interesting to me. :)

I want to store some values in the Windows Registry under the LocalMachine hive (a global setting, to get around a chicken-and-the-egg configuration problem I had).  My build target within Visual Studio 2008 was ‘Any CPU’, which means in effect, it creates a 32-bit executable.

The code worked fine - I could both write to and read from the registry.

But when I ran Regedit to go look at the values, I couldn’t find them.  I was looking at the right spot — HKEY_LOCAL_MACHINE\SOFTWARE\Oak City Software but my value wasn’t there!  I knew the write suceeded because I could read the value back again — it’s just that it wasn’t written where I thought it would go.  Walking off to get a refill on Diet Dr. Pepper while a global search in the registry ran, I returned to find that the values had been stored under HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Oak City Software

It turns out that when running 32-bit code on a 64-bit OS, Microsoft transparently redirects your registry calls to this special Wow6432 node in the registry.

OK, time for an experiment.  I changed the build target from ‘Any CPU’ to ‘x64′, thus creating a 64-bit executable.  Running this resulted in my values being written to the place I expected within the registry.

I’m tempted to call this a leaky abstraction, but on the other hand, it is transparent to my code, and any support burden would be internal — I don’t expect my endusers to be spelunking in the registry.  But at the same time I’m curious as to why this was done.  I suspect that the registry doesn’t store values with as strong a datatyping as we think — someone trying to read a 64-bit value when only 32-bits was actually written might be a problem.

Powered by WordPress