Virtual Developer Workshop: Containerized Development with Docker

Creating a Simple MMC Snap-In with 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


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).

Creating a Simple MMC Snap-In with ATL

(Tools used: Microsoft. Platform SDK for Whistler Beta 1 and VC++ 6.0(SP4) under Windows 2000)

    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.


    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:

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 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 our CSimpleComponent 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 static Node.
  • 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 has a 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 are somewhat confusing. I always mix up which one inherits from IComponentData and which one provides implementation for IDataObject. IComponentData (MSDN) Initializing CComponentData and Displaying the Snap-in Root Node (MSDN)

IComponent 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

IDataObject 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 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 class for 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 the base class.  All we have to do is call the appropriate virtual function for each message and the right function for our nodes will be called. So now any new Scope Node or Result Item will inherit from CBaseNodeItem.

Adding the Items

Any new Scope Node or Result Item will 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.
  • Create a member of your new class in 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)

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)

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. Just implement the GetResultViewType and provide the CLSID_MessageView.  During the OnShow use QueryResultView to get access to the IMessageView interface and manipulate it.

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.

(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.
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 All  Tasks, 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 Directly on the MSDN.


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)

Adding Persistence

Implement the IPersistStreamInit for IComponentImpl and/or IComponentDataImpl if needed. You can save nodes and items, computer names 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.

Adding ActiveX control

Adding ActiveX isn't hard either.  Derive another CBaseNodeItem 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.  After GetResultViewType 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.

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 is much 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:

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 at Using 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


Download demo - 32 Kb


  • Help please. Link problem caused by MMCPropPageCallback()

    Posted by Legacy on 02/21/2004 08:00am

    Originally posted by: De Tran

    Whenever I use MMCPropPageCallback() with MFC (either static or dynamic), I get a link error as follow. Any suggestion for me? Thank.

    mmc.lib(apimfc.obj) : error LNK2005: "public: __thiscall AFX_MAINTAIN_STATE2::~AFX_MAINTAIN_STATE2(void)" (??1AFX_MAINTAIN_STATE2@@QAE@XZ) already defined in mfc42d.lib(MFC42D.DLL)
    mmc.lib(apimfc.obj) : warning LNK4006: "public: __thiscall AFX_MAINTAIN_STATE2::~AFX_MAINTAIN_STATE2(void)" (??1AFX_MAINTAIN_STATE2@@QAE@XZ) already defined in mfc42d.lib(MFC42D.DLL); second definition ignored


      Posted by landonb on 09/20/2006 11:37pm

      I had a similar problem with MMC.lib, but at runtime. If you see any thing like this: (adc.57c): Unknown exception - code c015000f (first chance) [Where c015000f <==> STATUS_SXS_EARLY_DEACTIVATION] You'll want to check the include of MMC.lib. I had to pull some stuff out of AFX.h and include it before MMC.lib, i.e., "mfc80d.lib mfcs80d.lib msvcrtd.lib MMC.LIB" The library was causing activation context pollution whenever a thread exited, and also when making some SetupDi calls, like SetupDiCallClassInstaller.


      Posted by klevgard on 07/11/2006 01:29am

      ///////// MMC.LIB UAFXCWD.LIB UAFXCW.LIB ///////////// I believe you need to force VC8.0 to load UAFXCWD.LIB before MMC.LIB. You ca n do this via the project property settings: Linker | Input | Additional Dep endencies. It worked for me. Paul 7/10/06

    • Similar problem

      Posted by simwall on 06/12/2006 02:47pm

      I have a similar problem building with VS2005 and unicode:
      uafxcwd.lib(afxinl2.obj) : error LNK2005: "public: __thiscall AFX_MAINTAIN_STATE2::~AFX_MAINTAIN_STATE2(void)" (??1AFX_MAINTAIN_STATE2@@QAE@XZ) already defined in mmc.lib(apimfc.obj)
      Did you manage to solve your problem?

  • This is nice, but I am getting m_spConsole NULL when going to invoke menu item

    Posted by Legacy on 06/30/2003 07:00am

    Originally posted by: Delta Gh

    This sample is nice. But I am facing some problem to invoke an wizard.
    I have created an extension snpins (extending IExtendContextMenuImpl for 'Active directory users and compuetrs') and added a menu item 'Invoke' under 'NEW'. I followup the coding as described in this sample, but I am getting m_spConsole as NULL while invoking this menu and as result I am unable to invoke wizard successfully. How I can proceed? Have any idea?

    thanx in advance

  • Other COM object

    Posted by Legacy on 05/18/2003 07:00am

    Originally posted by: Geni

    How can I create other object on remote computer in MMC snap-in. I need do authentification. I can`t call "CoCreateInitializeSecurity". It`s possible do Kerberos authentification and how?
    Thank you.


  • How does one pass custom data from the primary to the extension snapin?

    Posted by Legacy on 04/27/2003 07:00am

    Originally posted by: Sen Lin-Liu

    Nice article and helpful source code. I'm now running some small test programs successfully with stand alone and extensions. However I have not found a way to pass custom data from the primary to the extension. For example, after the extention is loaded, I need to pass some dynamically-ccreated data (by the primary) to initialize the extension. I would greatly appreciate it if someone can point the way or even share some code.

  • How are you supposed to reorder MMC scope nodes?

    Posted by Legacy on 01/21/2003 08:00am

    Originally posted by: RyanG

    Good article and source code. I learnt a great deal about building MMC snap-ins.

    I have a question that I hope someone can answer. I have just implemented renaming of MMC a node in the scope pane and want to reorder the nodes alphabetically. Unfortunately, the ability to position nodes using SDI_PREVIOUS, SDI_PARENT...etc is only available when inserting new nodes. How then do you reorder existing nodes? Obviously you could remove the old node and create a new node with the new name, except that MMC crashes if you do it while handling the MMCN_RENAME notification. Any ideas?


  • Bug (casching problems with Help) ?

    Posted by Legacy on 09/09/2002 07:00am

    Originally posted by: Igor Jovanovski


    I am experimenting with a snapin for mmc and I have problems with the help.
    I tryed setting the pat for the help file (.chm) to another directory where I have my file. The help didnt work (only shows mmc help). When I returned to the old pat it didnt work again. I am always inserting the snapin newly in a console file but it is the same. I tryed different types of recompiling but all I could manage is to have the web pages being displayed when I invoke a help for certain node but my help itself is not shown under the help of mmc. Is the path being cashed somewhere because the recompiling (which also does the registration) does not helps. I tryed the same stuf on your code and I got the same problems.
    That is:


    HRESULT STDMETHODCALLTYPE CSCSnapIn::GetHelpTopic(/* [out] */ LPOLESTR __RPC_FAR *lpCompiledHelpFile)
    if ( !lpCompiledHelpFile)
    return E_POINTER; // invalid argument
    *lpCompiledHelpFile = (LPOLESTR) CoTaskMemAlloc( MAX_PATH * sizeof(WCHAR) );
    if ( !lpCompiledHelpFile )
    return E_OUTOFMEMORY;

    #pragma chMSG(Change the help path to valid path)
    // ocscpy(*lpCompiledHelpFile, T2OLE("Help\\simpsnap.chm"));
    ocscpy(*lpCompiledHelpFile, T2OLE("help2\\HTMLCustom1.chm"));
    return S_OK;

    Could you plase explain me how does all of that works?
    I am using VC++6.0 with Windows XP and ATL for the development of the snapin. The HTMLCustom1.chm was developed with RoboHelp HTML.

    Thank you very much.

    Best regards,

  • Note about Data Items and the MSDN FAQ

    Posted by Legacy on 07/09/2002 07:00am

    Originally posted by: Eric E. Evans

    In the MSDN FAQ Article on adding custom item type it has you cut and past your existing IComponentData derived class static members and replace the name with the new item name.

    Referencing Article in MSDN :

    'How Do I Add Custom Item Types to the Snap-In Object?'

    Can be found here:


    One line needs to have the SnapIn CLSID remain set to the Parent Snap-In Node CLSID providing your just creating nodes in your snap-in that are not exposed via the IDL.

    This line is copied:

    const CLSID* CProjNameData::m_SNAPIN_CLASSID = &CLSID_sdfdsf;

    It says to replace with this:

    const CLSID* CMyCustomSnapIn::m_SNAPIN_CLASSID = &CLSID_MyCustomSnapIn

    If you don't have CLSID_MyCustomSnapIn defined you get the expected compiler error.

    It should be this with the implementation conditions stated above:

    const CLSID* CMyCustomSnapIn::m_SNAPIN_CLASSID = &CLSID_sdfdsf



  • Where is MMC snap-in in VC7?

    Posted by Legacy on 07/05/2002 07:00am

    Originally posted by: Vladimir

    Hi! Does anybody know how to develop an MMC snap-in using VC7?

  • Muiltiselection with MMC 2.0

    Posted by Legacy on 06/12/2002 07:00am

    Originally posted by: Kenia Alvarez

    I implemented multiselect in my snapin and it works fine in Windows 2000 - MMC 1.2. but on Windows XP - MMC 2.0 i have a little problem, i don't see any context menu to select an option, only the standard toolbar is active.
    Any Info about changes in MMC version 2.0 related with multiselection?
    Thanks, Kenia

  • MMC Snap-in extension dll

    Posted by Legacy on 06/05/2002 07:00am

    Originally posted by: Shilpi Baijal

    Does anybody know how to develop an mmc extension dll?


  • Loading, Please Wait ...

  • You must have javascript enabled in order to post comments.

Leave a Comment
  • Your email address will not be published. All fields are required.

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date