How-To Create a Snap-in That Uses WinForm View
Applies To: Windows 10, Windows 7, Windows 8, Windows 8.1, Windows Server 2008, Windows Server 2008 R2, Windows Server 2012, Windows Server 2012 R2, Windows Server Technical Preview, Windows Vista
A snap-in can use any Windows Forms form and host it in MMC in the results pane. It can extend the actions on Windows Forms selections and make use of MMC standard verbs. This sample demonstrates a simple snap-in that uses a Windows Forms view to create the same results pane UI as the MMC list view in the sample How-To Create a Snap-in That Uses MMCListView. It shows a list of users and their birthdays in the results pane. The form view allows you to multi-select a set of users. An action called Show Selection is available for the selection, which when invoked, shows the details of the selection.
Create SelectionFormViewSnapIn (file SelectionFormViewSnapIn.cs)
Similar to previous samples, create a snap-in class called SelectionFormViewSnapIn and create the standard RunInstaller and SnapInSettingsAttribute for it.
using System; using System.ComponentModel; using System.Security.Permissions; using Microsoft.ManagementConsole; [assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Unrestricted = true)] namespace Microsoft.ManagementConsole.Samples { /// <summary> /// Allows the .Net framework to install the assembly. /// </summary> [RunInstaller(true)] public class InstallUtilSupport : SnapInInstaller { } /// <summary> /// Provides the main entry point for the creation of a snap-in. /// </summary> [SnapInSettings("{9627F1F3-A6D2-4cf8-90A2-10F85A7A4EE7}", DisplayName = "- Selection (FormView) Sample", Description = "Shows FormView with multi-selection.")] public class SelectionFormViewSnapIn : SnapIn { /// <summary> /// Constructor. /// </summary> public SelectionFormViewSnapIn() { ... } } } //namespace
Add the following lines of code to the class constructor to create a root node and give it a display name. The subsequent lines of code create a form view description and attach the form view description to the root node.
// Create the root node. this.RootNode = new ScopeNode(); this.RootNode.DisplayName = "Selection (FormView) Sample"; // Create a form view for the root node. FormViewDescription fvd = new FormViewDescription(); fvd.DisplayName = "Users (FormView)"; fvd.ViewType = typeof(SelectionFormView); fvd.ControlType = typeof(SelectionControl); // Attach the view to the root node. this.RootNode.ViewDescriptions.Add(fvd); this.RootNode.ViewDescriptions.DefaultIndex = 0;
This creates the SelectionFormViewSnapIn class.
using System; using System.ComponentModel; using System.Security.Permissions; using Microsoft.ManagementConsole; [assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Unrestricted = true)] namespace Microsoft.ManagementConsole.Samples { /// <summary> /// Allows the .Net framework to install the assembly. /// </summary> [RunInstaller(true)] public class InstallUtilSupport : SnapInInstaller { } /// <summary> /// Provides the main entry point for the creation of a snap-in. /// </summary> [SnapInSettings("{9627F1F3-A6D2-4cf8-90A2-10F85A7A4EE7}", DisplayName = "- Selection (FormView) Sample", Description = "Shows FormView with multi-selection.")] public class SelectionFormViewSnapIn : SnapIn { /// <summary> /// Constructor. /// </summary> public SelectionFormViewSnapIn() { // Create the root node. this.RootNode = new ScopeNode(); this.RootNode.DisplayName = "Selection (FormView) Sample"; // Create a form view for the root node. FormViewDescription fvd = new FormViewDescription(); fvd.DisplayName = "Users (FormView)"; fvd.ViewType = typeof(SelectionFormView); fvd.ControlType = typeof(SelectionControl); // Attach the view to the root node. this.RootNode.ViewDescriptions.Add(fvd); this.RootNode.ViewDescriptions.DefaultIndex = 0; } } } //namespace
Create a Form View (file SelectionFormView.cs)
Create a selection form view class that has a private selection control.
using System; using System.Collections.Generic; using System.Text; namespace Microsoft.ManagementConsole.Samples { /// <summary> /// The form view to display the Winforms controls. /// </summary> public class SelectionFormView : FormView { private SelectionControl selectionControl = null; /// <summary> /// Constructor. /// </summary> public SelectionFormView() { } ... } // class } // namespace
Add the following methods to the selection form view, starting with the method that overrides OnInitialize to initialize the form view.
/// <summary> /// Initialize. /// </summary> /// <param name="status"></param> protected override void OnInitialize(AsyncStatus status) { // Call the parent method. base.OnInitialize(status); // Get a typed reference to the hosted control // that is set up by the form view description. selectionControl = (SelectionControl)this.Control; Refresh(); }
Define the Refresh method. We use the Refresh method to load fictitious data It creates a user and birthday list to be displayed in the results pane.
/// <summary> /// Load the data. /// </summary> protected void Refresh() { // Populate the lists with fictitious data. string[][] users = { new string[] {"Karen", "February 14th"}, new string[] {"Sue", "May 5th"}, new string[] {"Tina", "April 15th"}, new string[] {"Lisa", "March 27th"}, new string[] {"Tom", "December 25th"}, new string[] {"John", "January 1st"}, new string[] {"Harry", "October 31st"}, new string[] {"Bob", "July 4th"} }; selectionControl.RefreshData(users); }
Write a method to handle an action when an action is triggered.
/// <summary> /// Handle the selected action. /// </summary> /// <param name="action"></param> /// <param name="status"></param> protected override void OnSelectionAction(Action action, AsyncStatus status) { switch ((string)action.Tag) { case "ShowSelection": { selectionControl.ShowSelection(); break; } } }
This completes the form view definition.
using System; using System.Collections.Generic; using System.Text; namespace Microsoft.ManagementConsole.Samples { /// <summary> /// The form view to display the Winforms controls. /// </summary> public class SelectionFormView : FormView { private SelectionControl selectionControl = null; /// <summary> /// Constructor. /// </summary> public SelectionFormView() { } /// <summary> /// Initialize. /// </summary> /// <param name="status"></param> protected override void OnInitialize(AsyncStatus status) { // Call the parent method. base.OnInitialize(status); // Get a typed reference to the hosted control // that is set up by the form view description. selectionControl = (SelectionControl)this.Control; Refresh(); } /// <summary> /// Load the data. /// </summary> protected void Refresh() { // Populate the lists with fictitious data. string[][] users = { new string[] {"Karen", "February 14th"}, new string[] {"Sue", "May 5th"}, new string[] {"Tina", "April 15th"}, new string[] {"Lisa", "March 27th"}, new string[] {"Tom", "December 25th"}, new string[] {"John", "January 1st"}, new string[] {"Harry", "October 31st"}, new string[] {"Bob", "July 4th"} }; selectionControl.RefreshData(users); } /// <summary> /// Handle the selected action. /// </summary> /// <param name="action"></param> /// <param name="status"></param> protected override void OnSelectionAction(Action action, AsyncStatus status) { switch ((string)action.Tag) { case "ShowSelection": { selectionControl.ShowSelection(); break; } } } } // class } // namespace
Create a selection control (File SelectionControl.cs)
Create a class called SelectionControl that is a form view control, initialize it, and set up the list.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; namespace Microsoft.ManagementConsole.Samples { /// <summary> /// The selection control class. /// </summary> public partial class SelectionControl : UserControl, IFormViewControl { SelectionFormView selectionFormView = null; /// <summary> /// Constructor /// </summary> public SelectionControl() { // Initialize the control. InitializeComponent(); this.Dock = DockStyle.Fill; //Set up the list. UserListView.View = System.Windows.Forms.View.Details; ColumnHeader userColumnHeader = new ColumnHeader(); userColumnHeader.Text = "User"; userColumnHeader.Width = 200; UserListView.Columns.Add(userColumnHeader); ColumnHeader birthdayColumnHeader = new ColumnHeader(); birthdayColumnHeader.Text = "BirthDay"; birthdayColumnHeader.Width = 200; UserListView.Columns.Add(birthdayColumnHeader); } ... } // class } // namespace
Define the method that uses the associated Windows Forms view to initialize the control that implements the interface and adds the actions.
/// <summary> /// Initialize. /// </summary> /// <param name="parentSelectionFormView"></param> void IFormViewControl.Initialize(FormView parentSelectionFormView) { selectionFormView = (SelectionFormView)parentSelectionFormView; // Add the actions selectionFormView.SelectionData.ActionsPaneItems.Clear(); selectionFormView.SelectionData.ActionsPaneItems.Add(new Action("Show Selection", "Shows the Names of the selected Items in the FormView's ListView.", -1, "ShowSelection")); }
Define the method that populates the list with sample data.
/// <summary> /// Populate the list with the sample data. /// </summary> /// <param name="users"></param> public void RefreshData(string[][] users) { // Clear the list. UserListView.Items.Clear(); // Populate the list using the sample data. foreach (string[] user in users) { ListViewItem listViewItem = new ListViewItem(); listViewItem.Text = user[0]; listViewItem.SubItems.Add(user[1]); UserListView.Items.Add(listViewItem); } }
Add the method that shows the selected items that were stored in the selected data context of the form view when a user is selected.
/// <summary> /// Show the selected items. /// </summary> public void ShowSelection() { if (UserListView.SelectedItems == null) { MessageBox.Show("There are no items selected"); } else { MessageBox.Show("Selected Users: \n" + GetSelectedUsers()); } }
Define the method that updates the selected data context for the form view.
/// <summary> /// Update the context. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void UserListView_SelectedIndexChanged(object sender, EventArgs e) { if (UserListView.SelectedItems.Count == 0) { selectionFormView.SelectionData.Clear(); } else { // Update MMC with the current selection information selectionFormView.SelectionData.Update(GetSelectedUsers(), UserListView.SelectedItems.Count > 1, null, null); // Update the title of the selected data menu in the actions pane selectionFormView.SelectionData.DisplayName = ((UserListView.SelectedItems.Count == 1) ? UserListView.SelectedItems[0].Text : "Selected Objects"); } }
Build a string of selected users to create an object that qualifies as a unique selection object for selection data.
/// <summary> /// Build a string of selected users. /// </summary> /// <returns></returns> private string GetSelectedUsers() { StringBuilder selectedUsers = new StringBuilder(); foreach (ListViewItem listViewItem in UserListView.SelectedItems) { selectedUsers.Append(listViewItem.Text + "\n"); } return selectedUsers.ToString(); }
Define a method to handle mouse clicks and show the context menu if necessary.
/// <summary> /// Handle mouse clicks. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void UserListView_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { // Check selected items for a right-click. bool rightClickedOnSelection = false; ListViewItem rightClickedItem = UserListView.GetItemAt(e.X, e.Y); if (rightClickedItem == null || rightClickedItem.Selected == false) { rightClickedOnSelection = false; } else { rightClickedOnSelection = true; } // Show the context menu. selectionFormView.ShowContextMenu(PointToScreen(e.Location), rightClickedOnSelection); } }
This completes the code for the SelectionControl class.
using System; using System.Collections.Generic; using System.ComponentModel; using System.Drawing; using System.Data; using System.Text; using System.Windows.Forms; namespace Microsoft.ManagementConsole.Samples { /// <summary> /// The selection control class. /// </summary> public partial class SelectionControl : UserControl, IFormViewControl { SelectionFormView selectionFormView = null; /// <summary> /// Constructor /// </summary> public SelectionControl() { // Initialize the control. InitializeComponent(); this.Dock = DockStyle.Fill; //Set up the list. UserListView.View = System.Windows.Forms.View.Details; ColumnHeader userColumnHeader = new ColumnHeader(); userColumnHeader.Text = "User"; userColumnHeader.Width = 200; UserListView.Columns.Add(userColumnHeader); ColumnHeader birthdayColumnHeader = new ColumnHeader(); birthdayColumnHeader.Text = "BirthDay"; birthdayColumnHeader.Width = 200; UserListView.Columns.Add(birthdayColumnHeader); } /// <summary> /// Initialize. /// </summary> /// <param name="parentSelectionFormView"></param> void IFormViewControl.Initialize(FormView parentSelectionFormView) { selectionFormView = (SelectionFormView)parentSelectionFormView; // Add the actions selectionFormView.SelectionData.ActionsPaneItems.Clear(); selectionFormView.SelectionData.ActionsPaneItems.Add(new Action("Show Selection", "Shows the Names of the selected Items in the FormView's ListView.", -1, "ShowSelection")); } /// <summary> /// Populate the list with the sample data. /// </summary> /// <param name="users"></param> public void RefreshData(string[][] users) { // Clear the list. UserListView.Items.Clear(); // Populate the list using the sample data. foreach (string[] user in users) { ListViewItem listViewItem = new ListViewItem(); listViewItem.Text = user[0]; listViewItem.SubItems.Add(user[1]); UserListView.Items.Add(listViewItem); } } /// <summary> /// Show the selected items. /// </summary> public void ShowSelection() { if (UserListView.SelectedItems == null) { MessageBox.Show("There are no items selected"); } else { MessageBox.Show("Selected Users: \n" + GetSelectedUsers()); } } /// <summary> /// Update the context. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void UserListView_SelectedIndexChanged(object sender, EventArgs e) { if (UserListView.SelectedItems.Count == 0) { selectionFormView.SelectionData.Clear(); } else { // Update MMC with the current selection information selectionFormView.SelectionData.Update(GetSelectedUsers(), UserListView.SelectedItems.Count > 1, null, null); // Update the title of the selected data menu in the actions pane selectionFormView.SelectionData.DisplayName = ((UserListView.SelectedItems.Count == 1) ? UserListView.SelectedItems[0].Text : "Selected Objects"); } } /// <summary> /// Build a string of selected users. /// </summary> /// <returns></returns> private string GetSelectedUsers() { StringBuilder selectedUsers = new StringBuilder(); foreach (ListViewItem listViewItem in UserListView.SelectedItems) { selectedUsers.Append(listViewItem.Text + "\n"); } return selectedUsers.ToString(); } /// <summary> /// Handle mouse clicks. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void UserListView_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { // Check selected items for a right-click. bool rightClickedOnSelection = false; ListViewItem rightClickedItem = UserListView.GetItemAt(e.X, e.Y); if (rightClickedItem == null || rightClickedItem.Selected == false) { rightClickedOnSelection = false; } else { rightClickedOnSelection = true; } // Show the context menu. selectionFormView.ShowContextMenu(PointToScreen(e.Location), rightClickedOnSelection); } } } // class } // namespace
SelectionControl Designer (file SelectionControl.Designer.cs)
The following is part of the designer code for the selection control form. Be aware that the Component Designer generated code is excluded.
namespace Microsoft.ManagementConsole.Samples { /// <summary> /// Form container for a ListView control /// </summary> partial class SelectionControl { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing && (components != null)) { components.Dispose(); } base.Dispose(disposing); } ... private System.Windows.Forms.ListView UserListView; } }
All the code for this sample is available in the <MMC 3.0 Samples>\SelectionFormViewSample directory.
Steps to create, install, and run the snap-in
To install this snap-in, run the .NET Framework InstallUtil.exe program using the following command-line command: InstallUtil.exe SelectionFormViewSample.dll. Be aware that if the Microsoft.ManagementConsole dll is not in the GAC, the Microsoft.ManagementConsole.dll and the SelectionFormViewSample.dll must be in the same directory. To uninstall the snap-in later, run the previous InstallUtil.exe command with the /uninstall switch.
The InstallUtil.exe command attempts to install your snap-in using the SnapInSettingsAttribute. The utility creates a file called InstallUtil.InstallLog to show the success or failure of the install and all the actions taken.
InstallUtil.exe populates the registry entries for the given snap-in under the HKLM/Software/Microsoft/MMC/SnapIns key.
After the snap-in is installed, the snap-in is visible to MMC and can be added to the MMC Console using the Add/Remove Dialog. To test this snap-in, run MMC 3.0 (mmc.exe) and use the Add/Remove Snap-in menu. The Selection (Formview) Sample displays in the dialog and can be loaded in the MMC console.