Blog Post

Core Infrastructure and Security Blog
6 MIN READ

Exploring Configuration Manager Automation Fundamentals – PowerShell Cmdlets

ms-foxworks's avatar
ms-foxworks
Icon for Microsoft rankMicrosoft
Jun 28, 2023

Hello, everyone!

 

Welcome back to our blog series on automation 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 System Center Configuration Manager 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 scripts, 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.

 

 

 

 

  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.

 

 

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 (root\sms\site_xyz).

 

 

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.

 

 

 

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

 

 

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

 

 

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

 

ConvertTo-CMApplication

ConvertTo-CMConfigurationitem

ConvertTo-CMIResultObject

 

 

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

 

 

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

 

 

 

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

 

 

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.

 

 

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)

 

  <Property Name="Flags" Value1="" Value2="" Value3="4" />

  <Property Name="LEDBATEnabled" Value1="" Value2="" Value3="1" />

  <Property Name="DoincEnabled" Value1="" Value2="" Value3="1" />

  <Property Name="DistributeOnDemand" Value1="" Value2="" Value3="0" />

  <Property Name="LocalDriveDOINC" Value1="Automatic" Value2="" Value3="0" />

  <Property Name="DiskSpaceDOINC" Value1="GB" Value2="" Value3="90" />

  <Property Name="RetainDOINCCache" Value1="" Value2="" Value3="0" />

  <Property Name="AgreeDOINCLicense" Value1="" Value2="" Value3="1" />

  <Property Name="MaintenanceMode" Value2="Jul  6 2020  8:51AM" Value3="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

 

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 scripts are not supported under any Microsoft standard support program or service. The sample scripts 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.

Published Jun 28, 2023
Version 1.0
  • Hi DidiHai76

    I am glad to hear the Code-Example helped you and solved your problem. Well, if remember correctly there was some changes to this in the past. You can always sent a frown through the console, so the Software Engineering Team is aware. It will be reviewed and you will get an update, if this will be changed, confirmed or not.

  • DidiHai76's avatar
    DidiHai76
    Copper Contributor

    Thank you very much ms-foxworks! Your script works like a charm. I have had to modify the NewNALPath to ["Display=\\SITESERVER.DOMAIN.COM\D$\Microsoft Configuration Manager\"]MSWNET:["SMS_SITE=SITECODE"]\\SITESERVER.DOMAIN.COM\D$\Microsoft Configuration Manager\. And you are absolutely right when you say to comment out put() to verify the results. I compaired the NewNALPath with my LAB ConfigMgr installation a few times to find the right path. 

    Now the move to a new server with site recovery is 100% done and "clean". 

    However, I really think thats a bug and the ConfigMgr Team has to fix this. 

  • DidiHai76's avatar
    DidiHai76
    Copper Contributor

    Thank you very much for the very fast answer! This is exactly what i meant. I will give it a try and will comment my findings. This will make my day!

    Best regards,

    Dietmar

  • Hi DidiHai76 !

    I assume with Upgrade you mean you did an Disaster-Recovery and point the Installation to a new Directory. Yes, I had a few times such cases. Still my advice to open a case. So you have a similar situation like this:


    But to your question - a change for this would look like that - the CodeSnip is pretty old (6 years) - but it is still working:

    # Parameters
    $SiteServer = "PFECM001"
    $sitecode = "LAB"
    $scfNamespace = "root\SMS\site_$sitecode"
    $RoleName = "SMS Site Server"
    $OldNALPath = '["Display=\\PFECM001.LAB.LOCAL\E$\Roles\ConfigMgr\"]MSWNET:["SMS_SITE=LAB"]\\PFECM001.LAB.LOCAL\E$\Roles\ConfigMgr\'
    $NewNALPath = '["Display=\\PFECM001.LAB.LOCAL\D$\Roles\ConfigMgr\"]MSWNET:["SMS_SITE=LAB"]\\PFECM001.LAB.LOCAL\D$\Roles\ConfigMgr\'
     
     
    # Find the SMS Site Server Role - Check the PropList Value and Create an new SMS_EmbeddedPropertyList if match
    $resources = Get-WmiObject -namespace $scfNamespace -query "Select * From SMS_SCI_SysResUse Where SiteCode='$sitecode' and RoleName='$RoleName'"
    foreach ($res in $resources)
    {
        foreach ($Prop in $res.PropLists)
        {
        Write-host $Prop.PropertyListName
        Write-Host $Prop.Values
            If ($Prop.Values = $OldNALPath)
            {
            Write-Host "Match found"
            $embeddedpropertylist_class = [wmiclass]""
            $embeddedpropertylist_class.psbase.Path = "\\$SiteServer\root\sms\site_$($sitecode):SMS_EmbeddedPropertyList"
            $embeddedpropertylist = $embeddedpropertylist_class.createInstance()
            $embeddedpropertylist.PropertyListName=$Prop.PropertyListName
            $embeddedpropertylist.Values = $NewNALPath
            }
        }
    }
    $resources.PropLists = $embeddedpropertylist
    $resources
    $resources.Put()


    Nowadays you can create the Embedded-Objects also with a CmdLet. Take out or comment out the $resources.Put() then you can compare the result. 

    Hope this helps you further. 

  • DidiHai76's avatar
    DidiHai76
    Copper Contributor

    Hi! Thanks for the good work! A question about the site control file: During upgrade a customers ConfigMgr site server I moved the installation path of the component server role from C$ to D$. It's installed on \\siteserver.domain.com\D$\Microsoft Configuration Manager now. However, in the console the path doesn't change and it's marked red. On Twitter I got some tips to modify the path within the SCF. Now I know it's written in exactly one position in that file but I don't dare. 

    Can you explain how to modify the path in the correct way, please?  

    		<SYSTEM_RESOURCE_USE>
    			<Role>SMS Component Server</Role>
    			<NALResType>Windows NT Server</NALResType>
    			<NALPath>["Display=\\SITESERVER.DOMAIN.COM\"]MSWNET:["SMS_SITE=OOE"]\\SITESERVER.DOMAIN.COM\</NALPath>
    			<Properties>
    				<Property Name="Maximum Thread Yield Time In Milliseconds" Value1="" Value2="" Value3="5000"/>
    			</Properties>
    			<PropLists>
    				<PropList name="Objects Polled By Site Status">
    					<Value index="0">["Display=\\SITESERVER.DOMAIN.COM\D$\Microsoft Configuration Manager\"]MSWNET:["SMS_SITE=OOE"]\\SITESERVER.DOMAIN.COM\D$\Microsoft Configuration Manager\</Value>
    				</PropList>
    			</PropLists>
    		</SYSTEM_RESOURCE_USE>

     

    Thanks in advance! Dietmar