Click here to Skip to main content
15,867,308 members
Articles / Desktop Programming / ATL
Article

Developing MMC Snap-Ins using ATL

Rate me:
Please Sign up or sign in to vote.
5.00/5 (11 votes)
4 Jun 2001CPOL12 min read 287.6K   1.8K   69   60
Describes how to add various Microsoft Management Console UI items using ATL

Adding About Information
Adding the Items
Adding Help
Adding MessageView
Adding Property pages
Adding Menu
Adding Wizard
Adding Toolbar
Adding Persistence
Adding Connect to Server dialog
Adding ActiveX control
Adding Taskpads
Adding WebPage

Introduction

This article tries to show how to implement basic MMC Snap-in features using ATL and gives you a starting point. The MMC Snap-in is a COM in-process server DLL. MMC stands for Microsoft Management Console and is designed to simplify and unify the different tasks and GUI elements for the end user. Some of the examples that use MMC as a hosting environment include Event Viewer, NT Services configuration GUI, Indexing Service, Win2k Disk Defragmenter, Device Manager, and many others. You can view the list on your machine by running mmc.exe and choosing menu Console | Add/Remove Snap-in | Add. The MMC framework provides no management by itself, but only unified graphical interface for hosting snap-ins. MMC is not a solution for everything. It's just another option that you have. It's up to you to see the applicability of MMC to your particular needs. This article only describes Primary Snap-Ins (Non Extension).

MMC GUI has several elements to it.

  • Scope Panes - Console Tree which is normally on the left pane. Starts with a Static node which can have children.
  • Result Panes - List View, Taskpad View, ActiveX control, and Web Page normally on the right pane. Usually appears when user selects a node from Console tree.
  • Context menus - Popup menu when user right clicks Scope Pane or Result Pane.
  • Toolbars and menus
  • Property Sheets - When user chooses Properties for scope or result pane items, MMC allows developer to add property pages.
  • Wizards
  • Taskpads

Key Required Interfaces:

Note: The following links point to MSDN pages that have UML diagrams and explain in details the communication between MMC and your Snap-In. Even though it's based on the C++ samples that they provide, it can still be followed easily.

The only help I found on the subject at the time was MSDN. I strongly suggest learning MMC Snap-Ins framework through the various C++ Samples and Diagrams at Sample Snap-ins Discussion (MSDN).

ATL Implementation

Create a new ATL COM AppWizard project for in-process COM server. Insert New ATL Object | MMC Snap-in. For the name put Simple. For MMC Snap-in property page leave the defaults and choose IExtendContextMenu, IExtendPropertySheet, and

IExtendControlBar
.

All Snap-ins get installed under HKEY_LOCAL_MACHINE\Software\Microsoft\MMC\SnapIns reg key. The following values are valid under this key:

  • NameString - Displayed during Add/Remove Snap-in Dialog. If not specified, Snap-in appears without name.
  • About - CLSID of the about object. Used during Add/Remove Snap-in to provide the version and copyright info as well as the Snap-in icon. If not specified, no about information will be available to end user and default icon for the Snap-in will be used, which is generic folder icon.
  • StandAlone - The key indicates that this is a Primary Snap-in; that is, it can be used stand alone and doesn't extend any other Snap-ins.
  • NodeTypes - Contains values that represent Snap-ins nodes. You should list your nodes here only if you want them to be extended by other Extension Snap-ins. The wizard adds our static node here, it assumes that we will allow Extension Snap-ins to be written for it.

ISnapInAbout

Let's start with the simple part of MMC, the ISnapinAbout interface. This interface is responsible for providing the copyright and version info, etc. to the user. The info is only visible when the Snap-in is being inserted through Add/Remove Snap-ins dialog:

Image 1

It is implemented in a separate COM class for efficiency since it's role as you can see is very minimal. It has very trivial methods. Adding About Information (MSDN)

IComponentData

This is implemented by IComponentDataImpl in ATL. The

IComponentData
is associated with the Scope pane (left pane/the tree nodes). MMC calls the IComponentDataImpl::CreateComponent, which will create an instance of IComponentImpl or more specifically ATL will create ourCSimpleComponent class, which was passed as 2nd template argument to
IComponentDataImpl
.MMC will associate it with this
IComponentData
.The IComponentDataImpl::Initialize method, which is called by MMC, caches the private IConsole(2) and it you can also cache the IConsoleNamespace(2). The constructor of CSimple creates a new main staticNode.

  • CSimple - IComponentData. (Scope Pane/Left pane/The tree nodes/The folders)
  • CSimpleComponent- IComponent. (Result Pane/Right pane/Listview..etc)
  • CSimpleData - It's base class CSnapInItemImpl hasa method CSnapInItemImpl::GetDataObject to provide the IDataObject pointer. It creates an instance of CSnapInDataObjectImpl, which inherits from IDataObject.MMC uses IDataObject as means of transferring data between MMC and Snap-in. It uses predefined clipboard formats for that.

The names used by ATL wizard aresomewhat confusing. I always mix up which one inherits fromIComponentData and which oneprovides implementation for IDataObject. IComponentData (MSDN) Initializing CComponentData and Displaying the Snap-in Root Node (MSDN)

IComponent

This is implemented by IComponentImpl in ATL. The IComponentImpl is associated with the Result Pane (right pane). It also has Initialize method and gets passed its own private IConsole pointer by MMC, which is also cached by IComponentImpl. It also sets the header, but the docs say that "The IConsole2::SetHeader method is obsolete in MMC version 1.2 and later." IComponent (MSDN)
Creating CComponent and Expanding the Snap-in Root Node
(MSDN)

IDataObject

This is implemented by CSnapInDataObjectImpl in ATL. We don't come in contact with it directly.ATL handles it. It gets created when MMC calls QueryDataObject, which calls GetDataObject.. etc
Data Objects and MMC (MSDN)

IPersistStreamInit

This can be used by

IComponentData
and IComponent derived classes to provide persistence support. You can for example save the computer name, IP address, folder names, services, etc...

IExtendContextMenu, IExtendPropertySheet(2), and IExtendControlbar can be used to extend the popup menu, property pages, and add control bars for Snap-ins.
ISnapinHelp(2) is used to inform MMC that we support help. Snap-ins are strongly encouraged to provide help
IDisplayHelp can be used to support context sensitive help by responding to MMCN_CONTEXTHELP messages from MMC.

The best thing to do is to rename the CSimpleData to CStaticNode. I think it makes it clearer, but I left it as is. To simplify our life a little we need to create a base classfor the nodes. This class will provide all the default initialization and functions that don't need to be repeated in all our node classes. I've added a CBaseNodeItem, which inherits from

CSnapInItemImpl
and provides simple initialization. If you look at
CBaseNodeItem
class you'll see that it does some pretty generic stuff in the constructor, GetScopePaneInfo, GetResultPaneInfo, and Notify that are shared among most items. The Notify method is the method responsible for handling various MMC messages and is the primary way of getting notifications from MMC. The obvious advantage of course is for Notify method to be in thebase class. All we have to do is call the appropriate virtual function for each message and the rightfunction for our nodes will be called. So nowany new Scope Node or Result Itemwill inherit from CBaseNodeItem.

Adding the Items

Any new Scope Node or Result Itemwill inherit from CBaseNodeItem. The items in MMC are represented by the SCOPEDATAITEM and RESULTDATAITEM structures.

To add the items to the Result Pane:

  • Derive another CBaseNodeItem which will represent result items. Define the clipboard vars. I set the GUID to GUID_NULL.
  • MMCN_SHOW - respond to this message from MMC in Notify. We simply call virtual OnShow function. Insert the columns/items.
  • GetResultViewType - set the params depending on what you need. Listview, Taskpad or ActiveX ctrl.
  • GetResultPaneInfo - calls virtual GetResultPaneColInfo to get the list item.

To add items to the Scope Pane:

  • Derive another class from CBaseNode which will represent scope items. Define the clipboard vars.
  • Createa member of your new classin parent node class.
  • MMCN_EXPAND - handle this message from MMC. We simply call our virtual OnExpand.
  • Define the clipboard format values (m_NODETYPE, m_SZNODETYPE, m_SZDISPLAY_NAME, m_SNAPIN_CLASSID, CSomeNodeGUID_NODETYPE)

Image 2

Adding Help

Create a simple html help project with HTML help wizard. Handle the MMCN_CONTEXTHELP. This will enable the F1 context sensitive help. Inherit the

IComponentData
derived class from ISnapinHelp2. Provide implementation for
GetHelpTopic
(tell it the directory of your help file). Look at the help on ShowTopic for the format on how to specify help topics. Now each Node in the Scope Pane and each item in the Result Pane can have it's own help file entry. The help file will be merged with MMC's help file. So you can add your own headings and stuff. Implementing Help (MSDN)
Image 3

Adding MessageView

MMC 1.2 has MessageView OCX control that can be used to provide some useful info to the user.
You create it similar to creating ActiveX. Justimplement the GetResultViewType and provide the CLSID_MessageView. During the OnShow use QueryResultView to get access to the IMessageView interface and manipulate it.

Image 4

Using the MMC Message OCX Control (MSDN)

Adding Property pages

To provide the property page:

  • derive a class from CSnapInPropertyPageImpl
  • Implement QueryPagesFor for your Scope Pane or Result Pane Item
  • Implement CreatePropertyPages for your Scope Pane or Result Pane Item
  • Enable the MMC_VERB_PROPERTIES verb. I did it in OnSelect
  • Save a pointer to parent class to exchange the data if needed
  • You can use the PropertyChangeNotify function of your property page class which will translate to MMCN_PROPERTY_CHANGE.
    You have to override the Notify function of IComponentDataImpl derived class and provide the implementation for lpDataObject == NULL case and handle the
    MMCN_PROPERTY_CHANGE
    
    event.

Image 5 Image 6

(Side Note: There are different predefined MMC verbs that can be used such as MMC_VERB_RENAME, MMC_VERB_DELETE, MMC_VERB_PROPERTIES, etc... Enabling MMC Standard Verbs (MSDN))

If you want to display Property Page and not use the MMC's Properties menu, you have to do so using the IPropertySheetProvider. Look under the Adding Wizard section later for details. Adding Property Pages (MSDN)

Adding Menu

Adding menu is easy with ATL. Just add a menu resource with 4 popup menus. Image 7
Each popup menu on the menu represent specific place on the MMC popup menu. Adding menu entry under Top will create a top level menu, Task - under AllTasks, New - under New, and View - under View. To add the menu all you actually do is use the SNAPINMENUID ATL macro for each node or result item that you want to have menu commands. You handle messages using BEGIN_SNAPINCOMMAND_MAP/END_SNAPINCOMMAND_MAP. What you get is the pointer to CSnapInObjectRootBase. You cast it to the IComponent or IComponentData derived class by looking at the m_nType (Scope or Result). Adding Context Menu Items (MSDN)

Adding Wizard

Add a menu entry under All Tasks for invoking the wizard. Then Add a function such as InvokeWizzard so it is accessible to you when you need it. It can be used for Result and Scope items based on the m_nType. All we get with the menu command is CSnapInObjectRoot, Notice that ATL uses the m_nType variable in CSnapInObjectRoot. So we know that

IComponentDataImpl
derived class has type 1 and IComponentImpl has type 2.To display wizards we have to directly use the IPropertySheetProvider. Look under the Using IPropertySheetProvider Directlyon the MSDN.

Image 8Image 9

Adding Property Pages and Wizard Pages (MSDN)

Adding Toolbar

Add a toolbar resource with 16x16 buttons. Add the entry inside the BEGIN_SNAPINTOOLBARID_MAP/END_SNAPINTOOLBARID_MAP block. Handle the commands from toolbar under BEGIN_SNAPINCOMMAND_MAP/END_SNAPINCOMMAND_MAP. You can manipulate the toolbar. Notice that CSnapInObjectRootBase has

CSimpleMap
m_toolbarMap. Call the lookup method on it passing the toolbar id as key. It will return IToolbar pointer. Now call SetButtonState on it. You can also use the GetToolbarInfo function to get the CSnapInToolbarInfo and then iterate through all toolbars of the class if needed. More details at Adding Toolbars (MSDN)

Image 10

Adding Persistence

Implement the IPersistStreamInit for IComponentImpl and/or IComponentDataImpl if needed.You can save nodes and items, computernames and reload it next time. Snap-in Persistence Model (MSDN)

Adding Connect to Server dialog when the Snap-in is Added

The main static node has to respond to QueryPagesFor and check the type to be CCT_SNAPIN_MANAGER. Implement the CreatePropertyPages. So now when MMC adds your Snap-in, you'll bee able to present a choose computer dialog. The dialog layout is basically standard for most components.
Image 11

Adding ActiveX control

Adding ActiveX isn't hard either. Derive anotherCBaseNodeItem class and implement the GetResultViewType. MMC will call this function. One of the params is ppViewType, which should be set to the CLSID of the control you want to display. You can cache or recreate the control each time the item is selected through the pViewOptions param. You can use MMC_VIEW_OPTIONS_CREATENEW/MMC_VIEW_OPTIONS_NONE. AfterGetResultViewType returns MMC will send a MMCN_INITOCX notify to the Snap-in. One of the params will be the pointer to IUnknown. You can also obtain the pointer through IConsole2::QueryResultView when you receive the

MMCN_SHOW
notification from MMC. You can set up your sink to receive events if needed. The control most likely has to support IDispatch, but I'm not sure and didn't test it.
Image 12

Using Custom OCX Controls: Implementation Details (MSDN)

Adding Taskpads

There are two different taskpads. Snap-in taskpad and Console taskpad. The latter one is available with version 1.2 and ismuch easier because MMC takes care of managing and creating the taskpad. To add the Console taskpad do the following select and then right click the node. Choose New Taskpad View:
Image 13Image 14
You can play with different options to change how taskpad looks, etc...
If you want to do it manually (Snap-in taskpad)or have to support 1.1 then read this:Using Taskpads (MSDN) and Using Taskpads: Implementation Details. Of course you'll have much more control over the taskpad if you choose to use the Snap-in taskpad.

Adding WebPage

Look atUsing Custom Web Pages(MSDN)

Some Useful links

BUG: Breakpoints Not Hit in ATL MMC Snap-in (MSDN)
Microsoft Management Console (MSDN)
MMC C++ Sample Snap-ins (MSDN)
Distributing Saved Console Files (MSDN)
MMC: Designing TView, a System Information Viewer MMC Snap-in
Visual C++ Developer: January 1999 - Writing MMC Snapins is a Snap with ATL 3.0
Simple MMC SnapIn

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionWhich IDE used for this example? Pin
Andy Luis Hernandez Romero27-Mar-17 9:37
professionalAndy Luis Hernandez Romero27-Mar-17 9:37 
Questionin the snapindata ,how can i get h_wnd to create a dialog? Pin
numega@163.com10-Dec-09 20:49
numega@163.com10-Dec-09 20:49 
GeneralTaskPad Pin
Member 44424206-Apr-09 0:05
Member 44424206-Apr-09 0:05 
GeneralProblem compiling this sample Pin
khaydarin23-Jan-08 8:32
khaydarin23-Jan-08 8:32 
GeneralDid not show helpTopic Pin
E_Qawasmi21-Jan-08 4:10
E_Qawasmi21-Jan-08 4:10 
QuestionA problem about adding ContextMenu Pin
Penny Chiu14-Dec-06 19:09
Penny Chiu14-Dec-06 19:09 
GeneralImages Pin
mo_nica88124-Nov-06 0:20
mo_nica88124-Nov-06 0:20 
GeneralContext Menu Pin
mo_nica88124-Nov-06 0:11
mo_nica88124-Nov-06 0:11 
QuestionProcessing changes in PropertyPage Pin
igor shmukler9-Jul-06 6:31
igor shmukler9-Jul-06 6:31 
Hi,

I have implemented a Snap-In that displays PropertySheet/Page as a reaction to some specific action, and needs to process data entered in the dialog.

I implemented OnApply() in the class derived from CSnapInPropertyPageImpl and it gets called whenever user clicks on [OK]. So far so good.

From within OnApply() I do input validation and depending on success, I either do nothing [return FALSE] or call PropertyChangeNotify().

The latter is taken from the article -

HRESULT PropertyChangeNotify(long param)
{
return MMCPropertyChangeNotify(m_lNotifyHandle, param);
}

I understand that it should send a notification with a "user-defined" value param somewhere (I am no longer sure whether it would be node the had the property sheet created or perhaps IComponent class with lpDataObject == 0). I don't think in my case anyone receives the notofication.

Either way, I tried to dig into what's happening with a debugger and I don't see this event being processed.

I am however sure that MMCPropertyChange is being called. I just cannot figure out what happens from that point on.

Any ideas?
AnswerRe: Processing changes in PropertyPage Pin
Matthew J. Bobowski7-Aug-18 14:34
Matthew J. Bobowski7-Aug-18 14:34 
GeneralAccess to "Properties" Pin
gustave_moriss5-Apr-06 23:55
gustave_moriss5-Apr-06 23:55 
GeneralRe: Access to "Properties" Pin
gustave_moriss10-May-06 6:18
gustave_moriss10-May-06 6:18 
GeneralMultiselect Pin
Anonymous16-Oct-05 15:31
Anonymous16-Oct-05 15:31 
QuestionHow i can display a PropertyPage when Doubleclick? Pin
zhenxiuf15-Jun-05 16:49
zhenxiuf15-Jun-05 16:49 
GeneralCompiler error Pin
Martin Gillmann3-Jun-05 4:41
Martin Gillmann3-Jun-05 4:41 
GeneralRe: Compiler error Pin
Anonymous3-Jun-05 13:37
Anonymous3-Jun-05 13:37 
GeneralCalling OnApply from MMC property sheet Pin
Dave Tyldesley26-Jan-05 1:46
Dave Tyldesley26-Jan-05 1:46 
GeneralPlease Help Pin
Member 150293311-Nov-04 6:14
Member 150293311-Nov-04 6:14 
GeneralRe: Please Help Pin
Anonymous11-Nov-04 14:53
Anonymous11-Nov-04 14:53 
GeneralRe: Please Help Pin
nikomsj30-Jan-06 20:35
nikomsj30-Jan-06 20:35 
GeneralCannot compile and build the sample Pin
Member 15029338-Nov-04 7:30
Member 15029338-Nov-04 7:30 
GeneralThank you Pin
SharpKnife24-Aug-04 16:08
SharpKnife24-Aug-04 16:08 
GeneralMMC SnapIn View Problem Pin
Member 24734716-May-04 22:31
Member 24734716-May-04 22:31 
Generalattaching HTML help in snap-in Pin
Anshul Solanki31-Mar-04 2:03
Anshul Solanki31-Mar-04 2:03 
GeneralRe: attaching HTML help in snap-in Pin
Leon Finker31-Mar-04 14:44
Leon Finker31-Mar-04 14:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.