Developing for Microsoft Management Console (MMC 3.0)

Developing for Microsoft Windows Management Console (MMC 3.0)

Introduction

Microsoft Management Console (MMC) is a framework that hosts administrative tools, called snap-ins, on Windows operating systems. Windows Vista®, Windows® XP, Windows Server® 2003, and Windows 2000 use MMC, which displays snap-ins as consoles. The snap-ins are used to administer networks, computers, services, and other system components. As the basic component of MMC, a snap-in provides the actual management of the program.

Snap-in programs are designed to perform a specific set of tasks on a specific type of application or object. A snap-in can be loaded as needed into an MMC console to create a customized management environment. With the new Add/Remove capability provided in MMC 3.0, it is possible to create specific consoles that match the skill level and job description of the administrator who is the intended operator of the console.

MMC version 3.0, the Management Console provided in Windows Vista, is designed to:

  • Reduce the cost of snap-in development by providing managed code framework

  • Improve reliability by offering heap isolation, Event Tracing for Windows (ETW), and application domain isolation and threading (managed code)

  • Provide consistent user experience for administrators by providing a new Actions Pane, a new Add/Remove dialog, and new user interface guidelines

The managed framework for MMC 3.0 provides a richer snap-in development experience than MMC 2.0 offers. It presents a quick start for developing snap-ins and facilitates incremental improvements of snap-in implementations.

This article offers information and code examples to help developers programming in the .NET Framework programming model create snap-ins or extension snap-ins using a Common Language Specification (CLS)-compliant language (for example, Microsoft Visual C# .NET, Microsoft Visual Basic .NET, or managed C++) and the MMC 3.0 managed code framework. For detailed reference information about the managed code framework, see "Microsoft.ManagementConsole Namespace" in the MSDN Library at https://msdn.microsoft.com/library.

MMC Improvements

MMC 3.0 radically simplifies the task of creating snap-ins by offering a managed layer that calls the MMC core that MMC version 2.0 exposes. In MMC 2.0 (which ships with Windows XP and Windows 2003), a snap-in is implemented as a Component Object Model (COM) in-process server. The compiled code is linked to create a DLL. MMC 2.0 interacts with snap-ins using several defined programming interfaces.

Using MMC 3.0, a snap-in developer does not need to write code to access the MMC internals, therefore can focus development time on programming management tasks. The MMC API can be used successfully to implement those user interfaces that best expose management functionality.

MMC 3.0 managed interfaces support the following features:

  • Managed/unmanaged snap-in extensibility (Namespace and Property Page)

  • Actions Pane Support, allowing developers to program actions once to offer consistent surfacing through Actions Pane and Context menus

  • Integrated Windows Forms controls (replaces OCX controls)

  • Multiple Views per node

  • Status Management

Although the MMC 3.0 managed interfaces provide parity with existing MMC 2.0 snap-ins, some exceptions exist. The exceptions are:

  • Context Menu extensions are not supported.

  • Virtual Lists are not supported in MMC ListView. Use standard list controls on Windows Forms Views instead.

  • Toolbar support is removed. Use the Actions Pane, which provides better and more consistent surfacing of actions.

Platform Support

MMC 3.0 is fully backward-compatible and supports all existing snap-ins: snap-ins written for earlier versions of MMC (1.0, 1.2, and 2.0) are also available in Windows Vista, Windows Server 2008, Windows Server 2003 R2, Windows Server 2003 (SP1), and Windows XP (SP2).

Developer Benefits

Easier and Faster Snap-in Development

It takes less time to get a snap-in up and running on Windows Vista. MMC 3.0 is easier to debug because actions are now logged, and MMC provides integrated trace support.

Visual Studio Support

MMC 3.0 provides the ability to design, develop, and debug using Visual Studio. It also is fully integrated with Windows Forms (unlike the OCX controls in MMC 2.0).

Design Guidelines and Best Practices

MMC 3.0 provides prescriptive guidance on standardized layout, behaviors, and discussions on common MMC design issues.

These guidelines include:

  • Consistency of user experience

  • Guidance on layout—layout of views, use of controls, and system themes (fonts, colors)

  • Guidance on structure—simplified navigation using a tree

  • Protection of investments in existing managed snap-ins

Developer Experience

MMC 3.0 is designed to provide many benefits to software developers:

  • Offers shorter ramp-up time to get a basic snap-in working and presents consistently shorter development times.

    • Provides several-fold improvements in productivity. (It's common to notice a tenfold increase in productivity.)

    • Fewer lines of code.

    • Powerful extensibility features.

  • Provides a rapid application development model and provides full support for WinForms for the development snap-ins.

  • Abstracts core concepts in simpler to understand .NET primitives.

  • Supports a drag-and-drop feature, which has gone from being a nearly impossible development task to an almost trivial task.

  • Improves reliability—MMC 3.0 fully supports asynchronous UI and now checks operations performed by snap-ins for common bug classes, such as potential heap corruption.

With all these new benefits, it is possible for developers with no MMC experience to be productive within a day. Creating snap-ins in Widows Vista is so easy, it's almost trivial.

Creating a Snap-in

Developers can create the following types of snap-ins using MMC 3.0.

Basic Developer Scenarios

  • Snap-ins that use MMC list view

  • Snap-ins that use MMC Actions Pane

  • Snap-ins that use property pages

  • Snap-ins that use an initialization wizard

  • Snap-ins that use a WinForm view

To find samples that address the MMC features used in the basic snap-in development scenarios, see How-To Develop Snap-ins Using MMC.

Advanced Developer Scenarios

  • Multi-threaded snap-ins

  • Snap-ins with multiple views on a node

  • Extension snap-ins

  • Extensible primary snap-ins

How to Create a Snap-in

This section provides code examples that demonstrate how to create snap-ins using the managed code API for MMC 3.0.

Important

It is important for software developers to be familiar with MMC programming elements before starting to create snap-ins for MMC 3.0.

For more information about MMC programming elements, see "MMC Programming Elements" in the MSDN Library.

Steps

The following summarizes the steps required to create a snap-in.

To create a snap-in

  1. Declare and register the snap-in.

  2. Create nodes in the scope tree.

  3. Create and use actions and standard verbs.

  4. Create a results view.

Code Examples

Note

Although code examples provided in the Windows Vista Developer Story are mostly for unmanaged code developers, code examples in this article are provided as managed code.

Software developers are encouraged to develop MMC 3.0 snap-ins as managed snap-ins because the power and advantage of MMC 3.0 become evident when developing managed snap-ins. In addition, developers will benefit from much fewer lines of code, quicker development time and more uniform interfaces.

The code examples that were distributed for MMC 2.0 documentation are adequate for MMC 3.0 unmanaged development. For detailed information, see "MMC 2.0 Programmer's Guide" in the MSDN Library.

The following code examples demonstrate how to create snap-ins that use MMC action list view and how to create multi-threaded snap-ins.

This C# code example shows the various places in a snap-in where custom actions can be added; they are: ScopeNodes, Views, ViewModes, and ResultNode Selections. This example loads a list of users into an MmcListView and adds actions. The ScopeNode snap-in has Add Child Node and Add to Root Node actions. The MmcListView snap-in has Refresh and SortByName actions. The node of the MmcListView has View as Large Icons, View As List, View As Small Icons, and View as Report actions. The SelectionData of result nodes has ShowSelection action.

//====================================================================;
//  This source code is only intended as a supplement to existing  
//  Microsoft documentation. 
//
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
//  ANY KIND, EITHER EXPRESSED OR IMPLIED — INCLUDING BUT NOT LIMITED  
//  TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
//  PARTICULAR PURPOSE.
//
//  Copyright (C) Microsoft Corporation.  All Rights Reserved.
//
//====================================================================;
using System;
using System.ComponentModel;
using System.Security.Permissions;
using Microsoft.ManagementConsole;

[assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Unrestricted = true)]
    
namespace Microsoft.ManagementConsole.Samples
{
    /// <summary>
    /// RunInstaller attribute - Allows the .NET Framework 
    /// InstallUtil.exe to install the assembly.
    /// SnapInInstaller class - Installs snap-in for MMC.
    /// </summary>
    [RunInstaller(true)]
    public class InstallUtilSupport : SnapInInstaller
    {
    }
    
    /// <summary>
    /// SnapInSettings attribute - Used to set the registration    
    /// information for the snap-in.
    /// SnapIn class - Provides the main entry point for the creation 
    /// of a snap-in.
    /// ActionsSnapIn - Snap-in for this example to show off Actions
    /// </summary>
    [SnapInSettings(  "{3DCE9B26-01F8-42f1-A5EA-2CBD5A48EB68}",
       DisplayName = "- Actions Sample", 
       Description = "Shows MmcListView with Actions at scope, list,  
                      view mode and selection level.")]
public class ActionsSnapIn : SnapIn
{
        /// <summary>
        /// Constructor for snapin
        /// </summary>
        public ActionsSnapIn()
  {
            // Create the root node
            this.RootNode = new ActionScopeNode();
            this.RootNode.DisplayName = "Actions Sample";

            // Create a message view for the root node.
            MmcListViewDescription lvd = new MmcListViewDescription();
            lvd.DisplayName = "Users (MmcListView)";
            lvd.ViewType = typeof(ActionListView);
            lvd.Options = MmcListViewOptions.ExcludeScopeNodes |     
                      MmcListViewOptions.AllowUserInitiatedModeChanges;

            // Attach the view to the root node
            this.RootNode.ViewDescriptions.Add(lvd);
            this.RootNode.ViewDescriptions.DefaultIndex = 0;
        }

        /// <summary>
        /// ScopeNode - Basic name and icon for the ScopeTree
        /// ActionScopeNode - Version of ScopeNode that has built in 
        /// actions
        /// </summary>
        public class ActionScopeNode : ScopeNode
        {
            /// <summary>
            /// Constructor for node
            /// </summary>
            public ActionScopeNode()
            {
                // add actions
                this.ActionsPaneItems.Add(new Action("Add Child", "Adds   
                a new scope node under this node", -1, "AddChild"));
                this.ActionsPaneItems.Add(new Action("Add to Root", 
                "Adds a new scope node to the root", -1, "AddToRoot"));
            }

            /// <summary>
            /// Handle node actions
            /// </summary>
            /// <param name="action">action that was triggered</param>
            /// <param name="status">asynchronous status for updating  
            /// the console</param>
            protected override void OnAction(Action action, AsyncStatus  
                                             status)
            {
                switch ((string)action.Tag)
                {
                    case "AddChild":
                        {
                            ActionScopeNode actionScopeNode = new  
                            ActionScopeNode();
                            actionScopeNode.DisplayName = "Added " + 
                            System.DateTime.Now.ToLongTimeString();
                            this.Children.Add(actionScopeNode);
                            break;
                        }

                    case "AddToRoot":
                        {
                            ActionScopeNode actionScopeNode = new 
                            ActionScopeNode();
                            actionScopeNode.DisplayName = "Added " + 
                            System.DateTime.Now.ToLongTimeString(); 
                            ((ActionsSnapIn)this.SnapIn).RootNode.
                            Children.Add(actionScopeNode);
                            break;
                        }
                }
            }        
        }

} // class
} //namespace

The following C# code example demonstrates how to use a separate thread to expand nodes and update the status and progress bar. The code defines a new type of ScopeNode that adds ten children to itself by firing a new thread for the adding process. The adding routine uses the SnapIn.Invoke method to have a delegate add the node.

//====================================================================
//
//  This source code is only intended as a supplement to existing 
//  Microsoft documentation. 
//
//  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
//  ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO 
//  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A 
//  PARTICULAR PURPOSE.
//
//  Copyright (C) Microsoft Corporation.  All Rights Reserved.
//
//====================================================================
using System;
using System.Configuration.Install;
using System.ComponentModel;
using System.Security.Permissions;
using System.Threading;
using Microsoft.ManagementConsole;

[assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Unrestricted = true)]
namespace Microsoft.ManagementConsole.Samples
{
    /// <summary>
    /// RunInstaller attribute - Allows the .NET Framework 
    /// InstallUtil.exe to install the assembly.
    /// SnapInInstaller class - Installs snap-in for MMC.
    /// </summary>
    [RunInstaller(true)]
    public class InstallUtilSupport : SnapInInstaller
    {
    }

    /// <summary>
    /// SnapInSettings attribute - Used to set the registration 
    /// information for the snap-in.
    /// SnapIn class - Provides the main entry point for the creation 
    /// of a snap-in. 
    /// AsyncExpandSnapIn class - snapin with nodes that expand on 
    /// separate threads.
    /// </summary>
    [SnapInSettings("{BC2A078C-27DF-405b-BEF0-A5A87B83A557}",
        DisplayName = "- Threading Sample",
        Description = "Shows asynchronous expanding with progress.")]
    public class AsyncExpandSnapIn : SnapIn
    {
        /// <summary>
        /// Constructor
        /// </summary>
        public AsyncExpandSnapIn()
        {
            this.RootNode = new AsyncExpandNode();
            this.RootNode.DisplayName = "Threading Sample - 
            Asynchronous expansion on separate thread";
        }
    }

    /// <summary>
    /// ScopeNode class - basic icon and name for item in scope pane
    /// AsyncExpandNode class - node which handles its expansion on a 
    /// separate thread.
    /// </summary>
    public class AsyncExpandNode : ScopeNode
    {
        private AsyncStatus expandStatus = null;

        /// <summary>
        /// Constructor
        /// </summary>
        public AsyncExpandNode()
        {
        }

        /// <summary>
        /// Launch new thread to handle expand tasks
        /// </summary>
        /// <param name="status">asynchronous status for updating the    
        /// console</param>
        protected override void OnExpand(AsyncStatus status)
        {
            // hang onto status
            expandStatus = status;

            // mark as 
            expandStatus.EnableManualCompletion();

            Thread thread = new Thread(new ThreadStart(Expand));
            thread.Start();
        }

        /// <summary>
        /// Add child nodes during expansion 
        /// </summary>
        private void Expand()
        {
            int foundChildren = 10;

            // report progress
            expandStatus.ReportProgress(0, foundChildren, "Loading 
                                        Sample children...");

            // find results
            for (int child = 1; child < foundChildren; child++)
            {
                // The Thread.Sleep statement below is for demo 
                // purposes only. When doing your development you  
                // should not block your snap-in thread to service an 
                // async request like OnExpand unless you only use the 
                // scope tree and list view and never show any WinForms     
                // views or WinForms property pages.  
                // The reason is that your WinForms views and property  
                // pages will be blocked, and in certain cases that can 
                // also block MMC.  

                // sleep for a second
                Thread.Sleep(1000);

                // New scope nodes must be created on the snapin's 
                // thread.
                DelegateWithNode delegateWithNode = new 
                DelegateWithNode(AddChildNode);
                this.SnapIn.BeginInvoke(delegateWithNode, new object[] 
                                        {this});

                // update the progress
                expandStatus.ReportProgress(child, foundChildren,  
                "Loading Sample children...");
            }

            // update progress
            expandStatus.Complete("Loading Sample complete.", true);
        }

        private delegate void DelegateWithNode(AsyncExpandNode 
                                               parentNode);

        /// <summary>
        /// Adding node on the snap-in thread although the Expand is in 
        /// its own thread.
        /// </summary>
        /// <param name="parentNode">node to add under</param>
        private void AddChildNode(AsyncExpandNode parentNode)
        {
            // add the child 
            ScopeNode childNode = new AsyncExpandNode();
            childNode.DisplayName = "Added " + 
            System.DateTime.Now.ToLongTimeString();
            this.Children.Add(childNode);
        }

    }
} // namespace

For additional code examples, see "How-To Develop Snap-ins Using MMC" in the MSDN Library.

See Also

Concepts

Windows Vista Management

Microsoft Management Console (MMC)