Part 2 – First c# extension

Build your first extension -> device info

You might wonder why creating an extension on a C# assembly instead of writing a vbs, powershell ,…. Script ?

I see two advantages to do so:

  1. you can directly rely on the console’s connection information, no need to manage the connection on your own.
  2. The external executable solution only works if you select a single object in the console meaning you can’t run an action for several objects at once.

Here I will explain how to create an extension that will show in a MessageBox all the collections a device is a member of.

Edit: starting with SCCM CB 1906, this feature will be directly implemented in the console as a tab in the detail pane. This extension will then be useless but it’s still a good example of what can be achieved with custom extensions.

First download Visual studio IDE (Community edition is enough and freely distributed by Microsoft)

Start it and create a new “Class Library” project

And chose a simple name for it

The class automatically generated is always named Class1. Just change it for a more accurate one (right-click on “Class1” then select “rename”)

Don’t forget to also rename the file or you can quickly get lost ^^

The SCCM console is only 32bits so we need to limit compilation to X86 architecture.

Open the small menu showing “Any CPU” then select configuration manager

Open “Active solution platform” and choose “<New…>”

Select x86 in the first dropdown menu and click “OK”

Close the “configuration manager” window.

We require some references to SCCM console assemblies. In the left pane, in the solution explorer, right-click on “References” in your project then select “Add Reference…”

Click on the “Browse” at the bottom of the “Reference Manager” windows, then browse your drive to the bin directory of the console installation folder and select “Microsoft.ConfigurationManagement.exe”. Repeat the same operation for “Microsoft.ConfigurationManagement.ManagementProvider.dll” and “AdminUI.WqlQueryEngine.dll”

Now, create the function that we will call from the console:

public static void deviceCollections(object sender, ScopeNode scopenode, ActionDescription action, IResultObject result, PropertyDataUpdated dataUpdatedDelegate, Status status)
{
}

And add these line on top of the file:

using Microsoft.ConfigurationManagement.AdminConsole;
using Microsoft.ConfigurationManagement.AdminConsole.Schema;
using Microsoft.ConfigurationManagement.ManagementProvider;

That’s all!! you have an assembly that can be called from within the console. For now, it does nothing so let’s retrieve target object info and connection info.

The “result” variable contains info about selected object(s). These objects can provide information about active connection but it’s safer to rely on the “scopenode” object that will always provide this information even if no object is selected.

Add this at the beginning of your function

ConsoleParentNode consoleParentNode = scopenode as ConsoleParentNode;

ConnectionManagerBase connectionMgr = consoleParentNode.RootConnectionNode.GetConnectionManagerInstance("WQL");

Now we retrieve the device ResourceID and name with :

string deviceName = result.Properties["Name"].StringValue;

string resourceid = result.Properties["ResourceID"].StringValue;

The next task is to query SCCM for all collection that contains this device by submitting a WQL query to the active connection.

IResultObject collectionList = connectionMgr.QueryProcessor.ExecuteQuery("SELECT CollectionID FROM SMS_FullCollectionMembership where ResourceID = " + resourceid);

We will only retrieve collectionIDs. Getting the collection’s names in a single query is alittle bit trickier and will be covered later.

Now prepare a message and show it to end-users!

String msg = deviceName + " is presently member of collections with the following IDs:\r\n";

foreach (IResultObject collID in collectionList)
{
    msg += collID.Properties["CollectionID"].StringValue + "\r\n";
}

Finally, show our message in a messageBox. ( don’t forget to add “using System.Windows.Forms;” on top of your file and add the corresponding reference to your project)

The complete code should look like this:

using Microsoft.ConfigurationManagement.AdminConsole;
using Microsoft.ConfigurationManagement.AdminConsole.Schema;
using Microsoft.ConfigurationManagement.ManagementProvider;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MyFirstExtension
{
   public class DeviceTools
   {
      public static void deviceCollections(object sender, ScopeNode scopenode, ActionDescription action, IResultObject result, PropertyDataUpdated dataUpdatedDelegate, Status status)
      {
         ConsoleParentNode consoleParentNode = scopenode as ConsoleParentNode;
         ConnectionManagerBase connectionMgr = consoleParentNode.RootConnectionNode.GetConnectionManagerInstance("WQL");

         string deviceName = result.Properties["Name"].StringValue;
         string resourceid = result.Properties["ResourceID"].StringValue;

         IResultObject collectionList = connectionMgr.QueryProcessor.ExecuteQuery("SELECT CollectionID FROM SMS_FullCollectionMembership where ResourceID = " + resourceid);

         String msg = deviceName + " is presently member of collections with the following IDs:\r\n";

         foreach (IResultObject collID in collectionList)
         {
            msg += collID.Properties["CollectionID"].StringValue + "\r\n";
         }
         MessageBox.Show(msg, "message");
      }
   }
}

Switch to “Release”

and build the solution.

Browse your disk to your project folder

And copy your Dll to a more dedicated folder (i.e: C:\Program Files (x86)\myCompany\myextension)

It’s time to modify our XML file to link the console to our dll.

The Class of the ActionDescription becomes “AssemblyType” and the “Executable” section is replaced by a corresponding “ActionAssembly” section.

<ActionDescription Class="AssemblyType" DisplayName="show collections" MnemonicDisplayName="show collections" Description="Shows the list of collection IDs this device is member of">
   <ShowOn>
      <string>ContextMenu</string>
      <string>DefaultHomeTab</string>
   </ShowOn>
   <ActionAssembly>
      <Assembly>C:\Program Files (x86)\myCompany\myextension\MyFirstExtension.dll</Assembly>
      <Type>MyFirstExtension.DeviceTools</Type>
      <Method>deviceCollections</Method>
   </ActionAssembly>
</ActionDescription>

Note that the “Type” item is composed of our assembly namespace followed by the class name.

As usually, save this file and copy it in the dedicated folders.

As I wrote before, this is not a C# programming course so the code is not optimal (no exception or error management …). There are a lot of good tutorials on the internet for that. With a little bit of reading and the Configuration Manager SDK code samples, I’m sure you will be able to do what you need.

Leave a Reply

Your email address will not be published. Required fields are marked *