Exploring Configuration Manager Automation Fundamentals – PowerShell Cmdlets

Hello, everyone!

Welcome back to our blog series on and API capabilities within Microsoft Configuration Manager. In our previous post, we delved into the Windows Management Instrumentation, where we learned about namespaces, classes, properties, and methods. Now, let's shift our focus to the PowerShell cmdlets. As with our previous post, we will start with the essentials and dive deeper into this topic.

PowerShell Cmdlets – An Overview

Cmdlets were introduced in 2012 SP1 and have continued to evolve. With Microsoft Configuration Manager 2303, we now have over 1100 cmdlets at our disposal. These cmdlets allow us to automate and extend Configuration Manager using PowerShell , similar to other documented approaches such as WMI and C#.

Requirements for PowerShell Cmdlets

– .NET Framework 4.6.2 or later (starting with MECM 2103)

– Microsoft Configuration Manager Console installed on your system

Host Environment for PowerShell Cmdlets

All versions of Microsoft Configuration Manager support Windows PowerShell version 5.1. If you have PowerShell 7 installed, it can coexist with Windows PowerShell 5.1. Starting from version MECM 2010, the Configuration Manager PowerShell cmdlet library also supports PowerShell 7.

Interaction with Configuration Manager Cmdlets

There are two ways to interact with the Configuration Manager Cmdlets:

  1. Configuration Manager Console:

   – When you start PowerShell or the PowerShell ISE from the Configuration Manager console, it uses the AllSigned execution policy for the process scope.

msfoxworks_1-1686594271748.png

  1. Importing the ConfigurationManager.psd1 module from the console installation directory:

   – By importing this module, you gain access to the Configuration Manager cmdlets in your PowerShell session.

msfoxworks_2-1686594271750.png

Module Assemblies for PowerShell Cmdlets

When you import the ConfigurationManager.psd1 module, the following assemblies are referenced:

– AdminUI.PS.dll

– AdminUI.PS.psm1

– AdminUI.WqlQueryEngine.dll

– Microsoft.ConfigurationManagement.ManagementProvider.dll

PSDrive for PowerShell Cmdlets

Whenever you interact with the PowerShell cmdlets, a PSDrive is created at runtime. It establishes the connection to your site and SMS provider (rootsmssite_xyz).

msfoxworks_3-1686594271753.png

From a PowerShell perspective, you must handle the interaction with the PSDrive like a physical drive. The ConfigMgr PowerShell cmdlets can only be executed from this PSDrive.

msfoxworks_4-1686594271755.png

msfoxworks_5-1686594271756.png

It's important to note that you may need to change drives in your code. Always ensure that the location is set correctly.

Debug Logging for PowerShell Cmdlets

When you start a code project or code, it can be useful to have additional information about what the ConfigMgr cmdlet is doing. You can configure and activate debug logging by adding the following lines to the top of your code:

$Global:VerbosePreference = “Continue”

$Global:DebugPreference = “Continue”

$Global:CMPSDebugLogging = $true

By enabling debug logging, you will receive debug and verbose output from your ConfigMgr cmdlets.

msfoxworks_6-1686594271761.png

Serialization with PowerShell Cmdlets

While you can directly interact with WMI classes, instances, and properties most of the time, the PowerShell cmdlets also help with common tasks. As ConfigMgr evolves, new objects come into play that require interaction. One such example is interacting with objects that use the DCMObjectModel.dll (such as applications, configuration items, and configuration policies) in the Microsoft.ConfigurationManagement.DesiredConfigurationManagement namespace.

For Instance, when you work with Applications. The Application-Object is defined by two core components:

  • Metadata (Name, Description)
  • DeploymentType (Detection Method, Install Command, Requirements)

This Definition is stored in the SDMPackageXML.

msfoxworks_7-1686594271767.png

To work with these objects, you should use the ConvertTo-* cmdlets to handle the serialized object:

ConvertTo-CMApplication

ConvertTo-CMConfigurationitem

ConvertTo-CMIResultObject

msfoxworks_8-1686594271771.png

This allows you to modify, add, or remove aspects of an application. You can navigate the object using dot notation:

$App = Get-CMApplication -Name CMPivot
$AppObj = ConvertTo-CMApplication -InputObject $App

msfoxworks_9-1686594271775.png

In this example, we modify the reboot behavior of the application/deployment type. We notice that this property requires a specific type definition.

msfoxworks_10-1686594271784.png

msfoxworks_11-1686594271785.png

Once we have modified the object to our desired configuration, we need to write it back to the SMS provider using the ConvertFrom-* cmdlets:

$Behavior = [Microsoft.ConfigurationManagement.ApplicationManagement.PostExecutionBehavior]::NoAction
$App = Get-CMApplication -Name CMPivot
$AppObj = ConvertTo-CMApplication -InputObject $App
$AppObj.DeploymentTypes[0].Installer.PostInstallBehavior = $Behavior
$AppChange = ConvertFrom-CMApplication -InputObject $AppObj
$AppChange.Put()

msfoxworks_12-1686594271794.png

Site Control File (SCF) and Embedded Objects

Another area where information is stored in Configuration Manager is the Site Control File (SCF). In the past, this was a binary file located in the Site Server Inbox and defined general site properties. However, this information is now directly stored in the database.

To work with the Site Control File, you can query the ConfigMgr database or examine the views and tables related to the SCF. It's important to be cautious when working with embedded objects within the SCF, as there is no validation on the SMS provider for these objects. Using incorrect values could lead to crashes or other issues.

XML-Definition in the ConfigMgr-Database
Select SiteControl From vSMS_SC_SiteControlXML
— Views which are the base for the SiteControl
Select Name From sys.views Where Name like N'vSMS_SC_%'
— Get All Dependent Objects
exec sp_depends vSMS_SC_SiteControlXML

When you work with the Site Control File you will encounter SMS-Embedded objects which are a set of properties for a SCF item.

These Objects will have a name and then one or more of value (int), value1 (string), value2 (string) that define the property values.

There are also a concept of embedded property lists which are a generic collection of objects.

ATTENTION!!!:

Since there is no validation on the SMS Provider for these objects, make sure to use the correct values for the configuration. Getting this wrong could cause the console or site role to crash or worse.

For example, let's consider the Microsoft Connected Cache feature on the distribution point. This feature is controlled by the Site Control File, and there is no specific WMI method or cmdlet to set this option. By querying the appropriate tables/views in the database, you can examine and modify the properties related to this feature.

msfoxworks_13-1686594271801.png

Select Props from vSMS_SC_SysResUse_SDK Where RoleName = N'SMS Distribution Point' and ServerName = N'DP01.FOXWORKS.INTERNAL'

The Flags Property of Value3 defines if the DOINC Feature is activated (4) or disabled (0)

 

 

 

 

 

 

 

 

 

When you configure this Feature through the Console you will notice in the SMSProv.log that an Instance-Change occurred on the WMI-Class SMS_SC_SysResList.

You can also track such changes through the SQL-Table dbo.SCCM_Audit:

select top 1000 * from SCCM_Audit
where TableName = N'SC_SysResUse_Property'
and By_Component = N'SMS Provider'
order by changetime desc

msfoxworks_14-1686594271804.png

Working with embedded objects can be unintuitive as you're not directly working with the instance result. You need to retrieve the collection of values, manipulate it, and then set it back into the wrapped object.

As an example, following approach like this will not work and the changes are quietly discarded:

myIResultObject.EmbeddedProperties.Add(something)

or

myIResultObject.EmbeddedProperties[something][“Value”] = “something”

Instead, an approach like this is necessary:

myEP = myIResultObject.EmbeddedProperties

myEP.Add(something)

myEP[something][“Value”] = something

myIResultObject.EmbeddedProperties = myEP

Conclusion:

In this blog post, we have covered the important fundamentals of PowerShell cmdlets and explored specific aspects within the context of Microsoft Configuration Manager. We discussed serialization, debug logging, and working with embedded objects. In our next blog post, we will conclude this series and shift our attention to the Administration Service (REST API). Stay tuned for more insights!

Disclaimer
The sample are not supported under any Microsoft standard support program or service. The sample are provided AS IS without warranty of any kind. Microsoft further disclaims all implied warranties including, without limitation, any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the sample scripts and documentation remains with you. In no event shall Microsoft, its authors, or anyone else involved in the creation, production, or delivery of the scripts be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss) arising out of the use of or inability to use the sample scripts or documentation, even if Microsoft has been advised of the possibility of such damages.

 

This article was originally published by Microsoft's Core Infrastructure and Security Blog. You can find the original article here.