Developing with Microsoft Management Console
This article provides a brief overview of Microsoft Management Console (MMC) and then illustrates how to create and install an MMC 3.0 snap-in using code from the DinnerNow.net sample application. For additional background information on MMC 3.0, see Windows Vista Management (Windows Vista Developer Story).
Overview
Microsoft Management Console
Microsoft Management Console (MMC) is a graphical user interface that hosts administration tools known as snap-ins. MMC provides a consistent user experience along with integrated error handling, event logging, and tracing. MMC 3.0 provides a managed API to create snap-ins and adds new features such as views based on Windows Forms and an actions pane.
The MMC console consists of a three-pane window, as shown in the following screenshot. The left pane, called the tree pane, is a hierarchy of nodes used for navigation. The middle pane, called the results pane, shows a view corresponding to the node selected in the tree pane or an action clicked in the actions pane. The right pane, called the actions pane, displays a list of commands that can be performed based on the selected node or view.
DinnerNow.net
DinnerNow.net is a sample application that revolves around a fictitious Web site where customers can search for and place a food order, split between multiple restaurants, for delivery to their home or office. In addition to the customer Web site, a kiosk is provided for restaurants to manage orders, and an MMC snap-in allows viewing of the Windows Communication Foundation (WCF) services and Windows Workflow Foundation (WF) workflows used in the application.
The DinnerNow MMC snap-in hosts Windows PowerShellâ„¢ to provide the data used to populate the snap-in views. Details of this process is described in the companion topic, Windows PowerShell in DinnerNow. For information on the DinnerNow WCF services displayed in the snap-in, see Developing Connected Systems.
The source code for the DinnerNow.net application can be downloaded from CodePlex/DinnerNow/Releases. The source code shown in this article is from the DinnerNow.Management.MMC project in the DinnerNow - Management solution.
Note: The included code examples, taken from DinnerNow's source code, are usually not complete and are modified for readability and succinctness.
Creating an MMC Snap-in
The following sections describe the process of creating the DinnerNow MMC snap-in. The discussion focuses on the Services child node of the MMC snap-in; however, the other nodes are created and populated in a similar fashion.
SnapIn class
Tree nodes
Services view
WCFServiceViewForm class
WCFServiceViewControl class
WCFServiceView class
Refresh action
SnapIn Class
A snap-in is represented by a type derived from the SnapIn class, which is in the Microsoft.ManagementConsole namespace. The SnapInSettingsAttribute attribute defines registration information for the snap-in and must be applied to the derived class. SnapInSettingsAttribute exposes the following properties, among others.
Property |
Description |
---|---|
Guid |
A Guid that uniquely identifies the snap-in. The snap-in is registered under the HKEY_LOCAL_MACHINE\Software\Microsoft\MMC\SnapIns key using this value. |
DisplayName |
A string that specifies the name of the snap-in as it appears in the Add or Remove Snap-ins dialog of the MMC console. |
Description |
A string that specifies the description of the snap-in as it appears in the Add or Remove Snap-ins dialog of the MMC console. |
The following code example, from DinnerNowSnapIn.cs, shows a basic snap-in declaration including the creation of the root node.
using Microsoft.ManagementConsole;
using System.Windows.Forms;
[SnapInSettings(
"{224308D4-2B1E-4073-B253-853BC3E60210}",
DisplayName = "DinnerNow Service Management",
Description = "Manage the DinnerNow Application")]
public class DinnerNowSnapIn : SnapIn
{
public DinnerNowSnapIn()
{
RootNode = new ScopeNode()
RootNode.DisplayName = "DinnerNow";
RootNode.EnabledStandardVerbs = StandardVerbs.Properties;
FormViewDescription fvd = new FormViewDescription();
// ...
RootNode.ViewDescriptions.Add(fvd);
WCFScopeNode wcfServicesNode = new WCFScopeNode();
wcfServicesNode.DisplayName = "Services";
// ...
RootNode.Children.Add(wcfServicesNode);
}
}
Tree Nodes
The nodes of the tree pane are represented by the ScopeNode class with the root node specified by the SnapIn.RootNode property. The ScopeNode class exposes the following properties, among others.
Property |
Description |
---|---|
DisplayName |
A string that specifies the name of the node as it appears in the tree pane. |
EnableStandardVerbs |
One or more members of the StandardVerbs enumeration that specify standard actions that can be performed on the node. When a verb is enabled, it is listed as an action in the actions pane. |
ViewDescriptions |
A ViewDescriptionCollection collection of ViewDescription types that represent the views that are available for display when the node is selected. The ViewDescriptionCollection.DefaultIndex property specifies the initial view that is displayed when a node is selected. |
Children |
A ScopeNodeCollection of ScopeNode instances that represent the child nodes of the given node. |
The following code example, from DinnerNowSnapIn.cs, shows the creation of the Services child node, wcfServicesNode. The EnabledStandardVerbs property is set to StandardVerbs.Refresh, which enables display of the Refresh action in the actions pane and is discussed in the Refresh Action section.
WCFScopeNode wcfServicesNode = new WCFScopeNode();
wcfServicesNode.DisplayName = "Services";
wcfServicesNode.EnabledStandardVerbs = StandardVerbs.Refresh;
FormViewDescription wcfSummaryView = new FormViewDescription();
wcfSummaryView.DisplayName = "WCF Services Summary";
wcfSummaryView.ViewType = typeof(WCFServiceViewForm);
wcfSummaryView.ControlType = typeof(WCFServiceViewControl);
wcfServicesNode.ViewDescriptions.Add(wcfSummaryView);
wcfServicesNode.ViewDescriptions.DefaultIndex=0;
RootNode.Children.Add(wcfServicesNode);
Services View
A ViewDescription type describes the view that is displayed in the results pane when a node is selected. There are four ViewDescription types, and each one has an associated View type. The four View types are described in the following table. The ViewDescription type has the same name as its associated View type suffixed with "Description". The ViewDescription.ViewType property specifies the view type, which is a class derived from the associated View type.
View type |
Description |
---|---|
FormView |
A Windows Forms control view. |
HtmlView |
A Web page view specified by a URL. |
MessageView |
A view similar to a Windows Forms MessageBox control. |
MmcListView |
A list of items. |
In the preceding example, wcfSummaryView is a FormViewDescription type with a display name of WCF Services Summary, and WCFServiceViewForm is a FormView type. A FormView type displays its results through the use of a Windows Forms control, which is specified by the FormViewDescription.ControlType property.
When the Services child node is selected, information about each WCF service used by the DinnerNow application is displayed. This information includes the status of the service, when it was started, the name and address of each endpoint, and the total calls on that endpoint.
The following classes are used to provide the WCF Services Summary view.
Class |
Description |
---|---|
WCFServiceViewForm |
A FormView type that contains the WCFServiceViewControl control. This class retrieves the display data from Windows PowerShell. |
WCFServiceViewControl |
A UserControl type that contains a TableLayoutPanel control, which is a container for multiple instances of the WCFServiceView control. |
WCFServiceView |
A UserControl type that displays information about a single DinnerNow service. |
WCFServiceViewForm Class
The WCFServiceViewForm class is a container for the WCFServiceViewControl control, which displays the service information. The WCFServiceViewForm.Refresh method is called on initialization, periodically in response to a timer, and whenever the Refresh action is clicked. The Refresh method calls into Windows PowerShell to retrieve the data to display and is discussed in the Refresh Action section. The following code example is from WCFServiceViewForm.cs.
using System.Collections.Generic;
using Microsoft.ManagementConsole;
using DinnerNow.Management.PS.Data;
public class WCFServiceViewForm : FormView
{
private WCFServiceViewControl control = null;
protected override void OnInitialize(AsyncStatus status)
{
base.OnInitialize(status);
control = (WCFServiceViewControl) this.Control;
Refresh();
}
protected override void OnRefresh(AsyncStatus status)
{
Refresh();
}
public void Refresh()
{
// See the Refresh Action section.
}
}
WCFServiceViewControl Class
The WCFServiceViewControl class is a UserControl type that consists of an instance of the TableLayoutPanel class named RepeaterPanel. RepeaterPanel is a container for multiple instances of the custom WCFServiceView class, each of which represents one DinnerNow service. The following code example is from WCFServiceViewControl.cs.
using System.Collections.Generic;
using System.Windows.Forms;
using DinnerNow.Management.PS.Data;
public partial class WCFServiceViewControl : UserControl
{
// From the corresponding designer generated partial class.
private TableLayoutPanel RepeaterPanel;
internal void AddService(DinnerNowService _service,
IList<WCFEndpoint> endPoints)
{
WCFServiceView view = new WCFServiceView();
view.Service = _service;
view.EndPoints = endPoints;
RepeaterPanel.Controls.Add(view);
}
}
WCFServiceView Class
The WCFServiceView class is a composite control that represents information about a single DinnerNow WCF service using the DinnerNowService and WCFEndpoint data classes. The following code example is from WCFServiceView.cs.
using System.Collections.Generic;
using System.Windows.Forms;
using DinnerNow.Management.PS.Data;
public partial class WCFServiceView : UserControl
{
// From the corresponding designer generated partial class.
private Label lblServiceName;
private Label lblStartTime;
private Label lblRunning;
private ListView lvEndPoints;
public DinnerNowService Service
{
set
{
lblServiceName.Text = value.Name;
lblStartTime.Text = value.StartTime.ToString();
lblRunning.Text = value.Status;
// ...
}
}
public IList<WCFEndpoint> EndPoints
{
set
{
foreach (WCFEndpoint endPoint in value)
{
lvEndPoints.Items.Add(new ListViewItem(
new string[] { endPoint.Name, endPoint.Address,
endPoint.Totalcalls.ToString() }));
}
}
}
}
Refresh Action
The view description, wcfSummaryView, for the Services node enables the standard verb Refresh, which causes the Refresh action to appear in the actions pane. When the Refresh action is clicked, the WCFServiceViewForm.OnRefresh method is called, which in turn calls the WCFServiceViewForm.Refresh method.
The Refresh method uses Windows PowerShell (through the PSHelper.GetDNServices and PSHelper.GetEndpoints methods) to retrieve the WCF service information, which is passed to the WCFServiceViewControl.AddService method, as shown in the following example from WCFServiceViewForm.cs. For details on how the service information is retrieved using Windows PowerShell, see Windows PowerShell in DinnerNow.
public void Refresh()
{
IList<DinnerNowService> _services = PSHelper.GetDNServices();
control.ClearService();
foreach (DinnerNowService _service in _services)
{
control.AddService(_service, PSHelper.GetEndpoints(_service.Name));
}
}
Installing the Snap-in
A snap-in must be installed before it can be added to an MMC console. The following steps are required to install a snap-in.
Create an installer class.
Derive a class from the SnapInInstaller class (an Installer type) and apply the RunInstallerAttribute attribute set to true. The following code is from DinnerNowMMCInstaller.cs.
using Microsoft.ManagementConsole; using System.ComponentModel; [RunInstaller(true)] public class DinnerNowMMCInstaller : SnapInInstaller {}
Build the snap-in and installer assembly.
The snap-in and installer classes must be built into the same assembly.
Run the Installer tool (Installutil.exe) on the assembly.
Installutil DinnerNow.Management.MMC.dll
Installutil uses reflection to find an Installer type in the assembly that is decorated with the RunInstallerAttribute attribute set to true and then installs the type. When a SnapInInstaller type is installed, reflection is used to find a SnapIn type decorated with SnapInSettingsAttribute. The SnapIn type is then registered under the HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MMC\SnapIns key using the GUID specified in SnapInSettingsAttribute.
Note: Use the Installer tool only in a development environment. For deployment, create an installer using a tool such as Microsoft Windows Installer (MSI). For more information, see Developer Story Windows Installer and Windows Installer.
Once installed, the snap-in appears in the Add or Remove Snap-ins dialog of the MMC console.
See Also
Concepts
Design Highly Manageable Applications
Developing with Windows PowerShell
Windows PowerShell in DinnerNow
Other Resources
Microsoft Management Console 3.0
Developing for Microsoft Management Console (MMC 3.0)