Create ConfigMgr Powershell Configuration Items using Powershell

As part of a presentation for the 2019 Midwest Management Summit in Minneapolis, one of the sessions I'm presenting with Jeff Bolduan is Configuration Items.  As part of that session, we'll be demoing using a PowerShell Script to create PowerShell-based Configuration Item.
If you want to see how that works (at least it works in my lab) --> Here <-- is the script for creating a Configuration Item with multiple tests inside, where the CIs are posh-based detection, applicability, and remediation scripts.  For demo purposes, I grabbed the scripts from the blog --> about WSUS Administration/WSUSPool <-- settings enforcement via Configuration Items, and got them all working to be made into 1 Configuration Item, with multiple rules.
Hopefully for those of you who are looking to create your own re-producible PowerShell code for creating posh-based CIs, the attached example posh will give you an idea of how you might want to get that done.

CMCB, PowerShell

  • Created on .

ConfigMgr Truncate History Tables

Thanks very much to Umair Khan, Twitter @TheFrankUK, for the assist!  One of the hiccups recently was making sure to exclude "globaldata" type HIST tables, so that DRS replication doesn't want to go into MAINTENANCE_MODE and re-initialize global data.

Read more ...ConfigMgr Truncate History Tables

  • Created on .

Inventory Per User Installed Applications, For Example, Click-Once

This routine has only had a limited life in a lab environment with only 3 clients.  Use at your own risk, etc. etc.  No promises or guarantees, and it might be the Worst Thing Ever.  Test, test, and test some more. 

What this routine would be for, is a custom powershell script, which tries to read what per-user installed things are installed, for the currently logged in user.  I tried in the lab to run it as a Baseline/Compliance Item... but one of the problems with it is that although running as 'SYSTEM', it wants to look at whatever user is currenly logged in.  As a Baseline, it won't 'wait for a user to logon' to run.  So depending upon when it runs, it might run and make an empty custom class with nothing to say, simply because the user is currently not logged on--even though they are logged on 8 hours a day, it just happened to run within the other 16 hours of that day.

So you, Super CM Admin that you are, you might want to forget about doing this as a baseline.  Instead make the powershell script as the only thing in the source folder for a package.  And then, make a old school/traditional Package, and program.  the program would run the script, "only when a user is logged on", but "with system rights".  and deploy the program to a collection.  If it were me... I'd set the advertisement to run on a schedule, like every 4 days or something.  Note I didn't test this at all in my lab.  I'm just offering this out there into the ether for (hopefully) someone else to take this and make it awesome and bulletproof. 

What the script does is create, and populate, a custom class. 

In the --> attached <-- is also a mof file.  You'd want to go to your console, Administration, Client Settings, Default Cient Settings, Hardware Inventory, set classes, and Import that mof file.  Once that is done, clients will be able to start reporting back on this information.



  • Created on .

Use CM Console scripts node to gather log files from CM Clients

To assist in answering a question in this forum post:

I'm blogging on behalf of Srikant Yadav; he gave me permission to do so.  Thanks Srikant! 

How to make this work..

Step 1:
Make a location on a server you manage/control--which has lots of space.

create a folder called (for example):

Share that out as ClientLogs$
At a minimum, you need these permissions (if you have multiple domains, or support non-domain joined computers, you'll have to figure out what other permissions might be necessary).

 For share permissions, because who will be 'copying' the logs to that share is a computer, add the group:
  <your domain where your computers live>\Domain Computers, with Change, Read.
 On that folder of E:\ClientLogs, for NTFS permissions, add Modify, Read & Execute, List folder contents, read, Write (aka, everything but full control) to
  <that same group you just did for share permissions, aka, \Domain Computers

Step 2:
In the --> attached <-- is a script.  Modify the parameter within that script which is currently...
$Destination = "\\<DummyShare>\ClientLogs$"

To be  \\YourServer\ClientLogs$

Save that modified script as <some location you'll remember>\ImportThisIntoCM.ps1

Step 3:
In your CM Console, go to software library, scripts, create script
ScriptName = Retrieve Client Logs
Script Language = Powershell
Import... and go to <some location you just said you'd never forget> and import that ImportThisIntoCM.ps1 script.
Review the Script Parameters.  You can, if you wish, modify the defaults of the parameters here.  For example, maybe you ALWAYS want to get any ccmsetuplogs, or you know you only want log files that will be within the last 5 days and nothing older.
double-check the Destination is the right servername and sharename
Next, Next, Close.

Step 4:
Approve the script in the Scripts Node.  You may need a peer to do the approval.  In smaller environments, if you are the only admin, you can self approve scripts in the Scripts node if you've configured that in Site Configuration, Site, Hierarchy Settings, uncheck "do not allow script authors to approve their own scripts".  This is a safety feature, that you SHOULD leave checked--because scripts can be powerful.  Some disgruntled admin COULD make a "format c:" type of script, self approve it, and send it as they walk out the door.  Just saying... you might not want to do this.  peer review of scripts is GOOD.

Step 5:
Use it!
As an example, in Assets and Compliance, Devices, pick on a Online device (obviously this only works if the target is online/available), right-click, Run Script.  Pick "Retrieve Client Logs".  At this point, you can change parameters as needed.  Next/next.  You'll see a progress bar. 

When it's done, in the \\yourserver\ClientLogs$ will be Subfolders; CMClientLogs$ for cmclientlogs, WindowsUpdateLogs$ for WindowsUpdateLogs, etc.  Inside those subfolders will be the zipped-up log files, named for the device name targeted.

Step 6:
Have a Cleanup Routine.  The \\YourServer\ClientLogs$ doesn't have any automatic cleanup routine around it.  If say... you were to gather log files all the time, wherever that location exists might fill up the drive.  You want to remember to clear that out either manually occasionally, or setup some kind of maintenance routine on that server to "delete xx when older than yy days" or something.

Possible updates...If you read through the script, you'll see that you can make this extensible yourself.  Perhaps you have a <App Specific to our type of business> which has log files that are always stored in c:\programdata\Widgets\Logs.  You can easily add a new section to the script, with another parameter to grab those log files as needed, if needed.

CMCB, PowerShell

  • Created on .

Politely Schedule restarts of CCMExec Service

Over the years of troubleshooting the SCCM Client, even with the built-in CCMEval task to attempt to watch and remediate client health of the SCCM Client, experience has shown to those of us in the trenches that sometimes, despite everything else, simply restarting the SMS Agent Host (aka, ccmexec service) will clear previously inexplicable issues.  A service restart is often less disruptive to the end user than saying "have you tried a reboot yet".

If that scenario is something you've encountered in your environment, or you just want to be proactive (like some other companies) one way to accomplish an 'SMS Agent Host' restart is to ask the ccmeval task to do that for you.  Kent Agerlund very kindly shared with me the edits they've done for their customers; and by doing so on their customers it was determined that overall, issues were reduced with the sccm client.

I've taken his edits, and created a couple of Configuration Items.  It's the ccmeval.xml which indicates what tests should be run by the ccmeval scheduled task.  Two tasks are added to ccmeval.xml:
- Restart CCMExec.exe-Stop
- Restart CCMExec.exe-Start

There are two --> attached <-- Configuration items.  One is to modify the ccmeval.xml to add the stop/start actions.  The other is to return the ccmeval.xml back to the original values (as of version Current Branch 1806 clients, but the ccmeval.xml hasn't changed in years, so it is anticipated it won't change in future version... but nothing is certain). 

What you would do to test:

  • Create a Baseline, let's call it "CCMEval Add Action to Restart CCMEXEC".  Add ONLY the 1 Configuration Item, 'ccmeval.xml Add Service Restart', make it optional (not required).
  • Deploy that baseline to a collection of TEST computers; to run daily, make sure you check the box for Remediation (not just monitor).
  • On the client
    • after the baseline of "CCMEval Add Action to Restart CCMEXEC" has run, go look at ccmeval.xml (it's usually in %windir%\ccm folder); and you should see the new actions have been added.
    • if you are patient--wait overnight.  The next day check in %windir%\ccm, for ccmevalreport.xml  Open up that file and look for the actions of "Restart CCMExec.exe-Stop." and "Restart CCMExec.exe-Start."  and they should have resultcodes of 0 (success).  You might also want to take note of the time that ccmevalreport.xml was created.  and then go look at %windir%\ccm\logs, for example, ccmexec.log or clientidmanagerstartup.log for entries around that time--you should notice that the logs indicated a service restart.
    • if you are NOT patient... from cmd-prompt-as-admin, you can run ccmeval.exe from %windir%\ccm, and then look at the files and results as indicated above.


  • Remove the Deployment of the baseline "CCMEval Add Action to Restart CCMEXEC" to your test collection.
  • Create a Baseline called... "CCMEval Return to original", and add just and only 'ccmeval.xml Return to Original', make it optional (not required).
  • Deploy the baseline to your collection of Test Computers, to run daily, make sure you check the box for Remediation (not just monitor)
  • Confirm the ccmeval.xml gets set back to no longer have to 2 additional tasks
  • Manually run ccmeval.exe after the xml is changed back, and/or wait overnight, to confirm that ccmeval runs, and no longer restarts the ccmexec service.
  • Remove the Deployment of the Baseline "CCMEval Return to Original" (hopefully you'll never need this again... but...)
  • Once you've satisfied yourself that you can not only modify the ccmeval.xml, but also return it to a pre-changed condition, then you will be confident (hopefully) to move forward.

Your next step (if you choose to go forward) is to deploy the "CCMEval Add Action to Restart CCMEXEC" to a collection of targets.

One thought...I personally would not deploy the xml change to any Server OS, and definitely not any of my SCCM Servers--because the Management Point processes use ccmexec.  Restarting ccmexec on a Management Point role server might be fine... only you can say what makes sense in your infrastructure.  If you restart SMS Agent Host on your Management Point Role servers outside of a reboot, what does that impact for you?  anything?  if no impacts, then sure.  But YOU need to test, test, test. 

You may be asking yourself why this blog article was titled 'politely' ... that's because the ccmeval scheduled task is designed to only run when the client isn't doing other important things, and the system is quiet.  By design ccmeval tries to be quiet and discreet about when it runs, and randomized.

CMCB, ConfigMgr

  • Created on .
Copyright © 2022 - The Twin Cities Systems Management User Group