Archive for August, 2008

Can’t create an instance of a managed WMI provider

Thursday, August 28th, 2008

Current Status
Solved

Problem
Using the .NET WMI provider extensions 2.0, I cannot create an instance of my custom provider class.

Windows Management Interface (WMI) is a way to expose management and configuration components from your application to scripting and operations tools, like SMS and MOM. In the past, creating a WMI provider required the use of COM. The WMI provider extensions for .NET created the ability to expose read-only management objects. In .NET 3.5, this capability was enhanced to allow for writing properties and calling methods.

Using these extensions, I created a management class for my application. I am having trouble creating instances of this class from the WMI command line, or any of the other WMI tools that I've tried.

Here's the class:

using System.Management.Instrumentation;

namespace ConsoleDecoupled
{
    [ManagementEntity]
    public class Activity
    {
        private string _name;

        [ManagementBind]
        public Activity(string Name)
        {
            _name = Name;
        }

        [ManagementKey]
        public string Name
        {
            get { return _name; }
        }
    }
}


Here's the program that publishes the class to WMI:

using System;
using System.Management.Instrumentation;

namespace ConsoleDecoupled
{
    class Program
    {
        static void Main(string[] args)
        {
            //InstrumentationManager.RegisterType(typeof(Activity));

            Activity instance = new Activity("foo");
            InstrumentationManager.Publish(instance);

            Console.WriteLine("Press enter to exit");
            Console.ReadLine();

            InstrumentationManager.Revoke(instance);
            //InstrumentationManager.UnregisterType(typeof(Activity));
        }
    }
}


And here's what wmic does when I try to create an instance:

wmic:root\cli>path Activity create Name="fee"
Create instance of 'Activity' class (Y/N)?y
ERROR:
Code = 0x80041002
Description = Not found
Facility = WMI


I know that the class is found, because I can query for the instance that I created programmatically:

wmic:root\cli>path Activity where Name="foo"
Name
foo


My next plan of attack is to go through this article on Writing coupled WMI providers, and seeing if I run into similar problems.

No “new”s is good news

Friday, August 22nd, 2008

"New" is the new "goto". As mock object testing frameworks and inversion of control containers are becoming more commonplace, we are encouraged to avoid having objects directly create other objects.

Why is "new" a bad word?
When a line of code includes the "new" keyword, it must also include the name of a concrete class. This line of code will appear within a different class (unless you are writing a singleton, in which case you have even bigger problems). You have just created a compile-time dependency between two classes.

The dependency inversion principle states that we should depend upon abstractions (i.e. interfaces and abstract base classes), rather than concrete classes. The "new" keyword immediately violates this principle because it forces us to depend upon a concrete class. The name after the "new" cannot be an interface or abstract base class, but a concrete packet of implementation.

Without dependency inversion, it is difficult or impossible to change units of behavior. If a class uses "new" to get access to a service component, you must change that code to replace it with a different service. If the change is a design-time decision, then recompiling the code just means more testing is required. But if the change is a run-time decision, then recompiling the code is not an option.

Without dependency inversion, it is difficult or impossible to mock objects for testing. If the code that you are testing is invoking "new", then the mock framework cannot intercept that and replace it with a test harness. The dummy object is there to observe the calls that leak out of the object that you are testing, and make sure that they are the ones that the test expects to induce. If those calls go into a concrete class, then the scope of the test is bigger than intended, and visibility is lost.

Building blocks
I once had a manager who compared good software component design to Legos. A complete solution can be built from interchangeable pieces. If you are using "new", your components are more like a puzzle pieces than building blocks. You create a solution out of pieces, but those pieces fit together in only one way.

As a rule of thumb, critically examine every "new" in your software. See if you can find a way to push it up through dependency injection. If you can, push it all the way out of your code and into an IoC container. The fewer "new"s, the better.