Build and Import your perfect WIM file to SCCM with powershell

There are literally so many ways to inject patches to your WIM file nowadays, I’ve been done a little research and I find this way the most appropriate.
This guide is based on this blog:
but with a final touch on how to do almost everything with PowerShell, even import it to SCCM. Ok, lets go!

  1. Make a folder on the Site server example: “C:\WIM-Servicing”

  2. Download and unzip this file, WIM-Servicing (Includes two scripts

  3. Copy these two scripts to the ServerCapture.PNG
  4. Now its time to Mount the .ISO file to this server

  5. Copy the “D:\sources\install.wim” to this folder “C:\WIM-Servicing”
    D: is the mounted .ISO

  6. Now we need to download the .MSU files to your server, this step need some manually, unfortunately.

    In my enviorment, I want to patch the 1803 version with Cumulative, Stack update and Adobe Flash
    1. November 2018 – KB4467702 Cumulative Update for Windows 10 Version 1803 for x64-based Systems
    2. November 13, 2018 – KB4465663  Servicing stack update for Windows 10, version 1803
    3. November – KB4462930 Update for Adobe Flash Player for Windows 10  Version 1803
    To find these patches you go to

  7. After you download them, make another folder in that WIM-Servicing folder, and name it to the month with first 3 letters.

  8. One important thing is to rename the stack update with a “1-” in the name. like this
    Because if the Cumulative patch injects before the stack update, it could cause problems. So make sure you change this. So the stack comes first!
  9. Now we have everything settle to start the progress, Open up the Service_WIM_Proper_Way.ps1, right-click and Edit.
  10. Change variables to match your wishes.
  11. Run the script.
  12. What’s happening now is
    * Injection of patches
    * Moving the .wim file to your location
    * Importing the operating system image to sccm

  13. So now you can distribute your .wim file, and ready to Test.

Good luck!

Create CM Collections from OU

Hey, Working on a script lately, to create CM collections from OU structure, also with a query that looks into the OU to collect the machines.

So let say you have a OU structure like above,

So you want collections in CM like “SBS Computers” and “SBSServers” collections will be created and gathering all the computers into that. And if you put this script on a schedule task, if the Active directory people doing new OU, they will pop up in CM automatically


the script looking like this.)

#Created: 2018-11-13
#Version: 1.0

#Author : Pontus Wendt
#Twitter: @pontuswendt
#Blog :

#Disclaimer: This script is provided "AS IS" with no warranties, confers no rights and
#is not supported by the author.

#Import Modules
Import-Module ConfigurationManager
Import-Module ActiveDirectory

#The logpath of your script
$Logpath = "C:\Logging\Log.log"
$Domain = ""
#Domain in ADSI
$DomainADSI ="DC=test,DC=pontus,DC=com"
#Gather the OU folders, that will be created, every folder you search for will be created.
$GADOU = Get-ADOrganizationalUnit -LDAPFilter '(name=*)' -SearchBase $DomainADSI -SearchScope OneLevel -Properties CanonicalName | Select Name
#SCCM Query
$query="select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.SystemOUName like '$domain/Computers%'"
#Specify the sitecode of your SCCM
$SiteCode = "X01:"
#SCCM folder you want to move your collections to (you need to create this folder before you run)
$CMFolderPath = "$SiteCode\DeviceCollection\Computers from OU"
#You need to mofidy one more step is under the Add collection function

#Change Location to primary site
CD $SiteCode

#WriteLog function
Function WriteLog ($message)
    $TZbias = (Get-WmiObject -Query “Select Bias from Win32_TimeZone”).bias
    $Time = Get-Date -Format “HH:mm:ss.fff”
    $Date = Get-Date -Format “MM-dd-yyyy”
    $Output = "<time>"
    Out-File -InputObject $Output -Append -Encoding Default –FilePath "$Logpath"

#AddCollection function
Function AddCollection
#Check if name already exists
if ((Get-CMDeviceCollection -Name "$Collectionname") -ne $null)
WriteLog "$Collectionname exists. Skipping."

#Check if OU structure have XX
if ($Collectionname -eq "XX")
WriteLog "$Collectionname have equals name as XX. Skipping."

WriteLog "Adding $Collectionname"

$Schedule = New-CMSchedule -RecurInterval Hours -RecurCount 1
WriteLog "Created Schedule: $Schedule"

WriteLog "Creating collection $Collectionname"
$newcollection=New-CMDeviceCollection -Name "$Collectionname" -LimitingCollectionName "All systems" -RefreshSchedule $Schedule

$query="select SMS_R_SYSTEM.ResourceID,SMS_R_SYSTEM.ResourceType,SMS_R_SYSTEM.Name,SMS_R_SYSTEM.SMSUniqueIdentifier,SMS_R_SYSTEM.ResourceDomainORWorkgroup,SMS_R_SYSTEM.Client from SMS_R_System where SMS_R_System.SystemOUName like '$domain/$names/Clients/XX/%'"

WriteLog "Creating $Collectionname with query $query"
Add-CMDeviceCollectionQueryMembershipRule -CollectionName "$Collectionname" -QueryExpression $query -RuleName "$Collectionname"
WriteLog "Moving $Collectionname"

$CollID = Get-CMDeviceCollection -Name $Collectionname
Move-CMObject -FolderPath $CMFolderPath -ObjectId $CollID.CollectionID

#Wait a bit
Start-Sleep 10

Write-Host "Failed to create collection $($_.Exception.Message) $($_.Exception.ItemName)"

#OU from csv foreach in foreach
foreach ($Collectionname in $GADOU.Name) {

WriteLog "Adding $Collectionname"

Get-ADOrganizationalUnit -Identity "OU=$Collectionname,$DomainADSI"
AddCollection $Collectionname
WriteLog "Done with the script"

Have the script here also, if you want to download it. CreateCollectionsfromAD


KB4343900 – Failed to resolve package [HRESULT = 0x80070490 – ERROR_NOT_FOUND]

Hey! Just got a problem in the service window this Sunday, I’m just in need to share this with everyone.

The platform that has the problem.
Server 2008 SP1

The real problem
KB4343900 just not installing, Error code: 0x80070490

When I’m digging the C:\Windows\Logs\CBS\CBS.log, find some interesting stuffs.

Exec: Package: Package_533_for_KB4343900~31bf3856ad364e35~amd64~~ is already in the correct state, current: Installed, targeted: Installed
2018-08-23 14:58:44, Info CBS Exec: Skipping Package: Package_533_for_KB4343900~31bf3856ad364e35~amd64~~, Update: 4343900-1784_neutral_LDR because it is already in the correct state.
2018-08-23 14:58:44, Error CBS Failed to resolve package ‘Package_424_for_KB4103718~31bf3856ad364e35~amd64~~′ [HRESULT = 0x80070490 – ERROR_NOT_FOUND]

And Solution was to Install this patch
KB4103718 –

Look in this post if you want a script to run this on more computers than just one –

If you have another KB but still have ERROR_NOT_FOUND line, you´ll just install that patch instead.



How to uninstall or remove SCCM client

Hey! I work with a company, that the customers, come and go pretty much. So sometimes they gonna install the CM-agent and sometimes some customers leaves. Then we need to uninstall the CM-Agent remotely of course! God forbidden manually!

You need
* Server 2008 R2 or above
* Windows 7 With PowerShell 3.0 installed or above
* CM2012

1. Create a Collection.

2. Create a Configuration item

2.1 Then the “Setting step”, Modify like below

2.2 Choose Script like this:
2017-12-19 16_38_23-sql.invidjkp.local - ASG-RemoteDesktop 2017 - SCCM02.png
2.3 Edit “Discovery Script”: Then you post in this:

function Get-ccmexec-service
    param ()

    Try {
    Get-Service -Name CcmExec |
        ForEach-Object {
            If($_.Name -eq "none") {
                $State = 0 }
            ElseIf($_.Name -eq "ccmexec") {
                $State = 1}

   catch {
   # Error handling



2017-12-19 16_42_42-sql.invidjkp.local - ASG-RemoteDesktop 2017 - SCCM02.png
2.4 Then “Remediation Script” you post in this:
C:\Windows\ccmsetup\ccmsetup.exe /uninstall
2017-12-19 16_43_04-sql.invidjkp.local - ASG-RemoteDesktop 2017 - SCCM02.png
2.5 Then in the Compliance Rules tab, Add this:
2017-12-19 16_44_14-sql.invidjkp.local - ASG-RemoteDesktop 2017 - SCCM02.png
2.4. The Finish the Configuration Item Wizard.

3. Create a Baseline to this, And put the deployment to your Collection.

4. And you are Done

Good Luck


CI – Get-ServicePackMajorVersion

Recently I got and a mission to inventory the ServicepackMajorversion on our servers. So ive made a script that you can use in a CI if you want.

Discovery Script

function Get-ServicePackMajorVersion
    param ()

    Try {

# Get Operating System Info
$sOS =Get-WmiObject -class Win32_OperatingSystem -computername Localhost

foreach($sProperty in $sOS)
        ForEach-Object {
            If($sProperty.ServicePackMajorVersion -match "0") {
                $State = 0}
            ElseIf($sProperty.ServicePackMajorVersion -match "1") {
                $State = 1}
   catch {
   # Error hantering


Compliance Rule
Equals 1 ( which is “a Service pack is installed”)

Good luck!


CI – Cleanup CCMcache

When I was at the MMS this year, I asked the Microsoft product team if the CCMCache is OK to clean up, because a lot of files is in the folder, and there is no built-in to do so.

This is a standard Configuration Item, pretty easy when you get into it.

Let say, we want to delete all content in C:\Windows\ccmcache if its 60 days or older.

Discovery script:

$MinDays = 60
$UIResourceMgr = New-Object -ComObject UIResource.UIResourceMgr
$Cache = $UIResourceMgr.GetCacheInfo()
($Cache.GetCacheElements() |
where-object {[datetime]$_.LastReferenceTime -lt (get-date).adddays(-$mindays)} |

Like this:
2017-09-18 13_44_52-sql.invidjkp.local - ASG-RemoteDesktop 2017 - invjkp-sccm03.png

If i just test this on a machine. It gonna look like this
2017-09-18 13_40_59-sql.invidjkp.local - ASG-RemoteDesktop 2017 - SCCM02.png

The result is the number of files that are older than 60 days.

Remediation script:

$MinDays = 60
$UIResourceMgr = New-Object -ComObject UIResource.UIResourceMgr
$Cache = $UIResourceMgr.GetCacheInfo()
$Cache.GetCacheElements() |
where-object {[datetime]$_.LastReferenceTime -lt (get-date).adddays(-$mindays)} |
foreach {

Like this:
2017-09-18 13_50_55-sql.invidjkp.local - ASG-RemoteDesktop 2017 - invjkp-sccm03.png

Compliance rule:
2017-09-18 13_52_42-sql.invidjkp.local - ASG-RemoteDesktop 2017 - invjkp-sccm03.png

Deploy this to some machines that you want to clean up, And you are good to go.


CI – Check for a registry value.

Hey! Sooner or late some upper management come to you and ask if you can check your machines if they are infected of a registry key (often a virus). They also ask if you can post a nice report of this. So how do you do? Well, in my opinion, This is the best way. Configuration Item (In this case I’m looking for “HKLM:\Software\Classes\MJ” exist or not)

1. First, Go to your console -> Assets and Compliance -> Configuration Item
2017-09-04 10_55_37-Invid - ASG-RemoteDesktop 2017 - invjkp-sccm03 (Work Resources).png

2. Right click “Create Configuration Item”
2017-09-04 10_56_20-Namnlös - Paint.png
3. Pick a good name for your CI
2017-09-04 09_27_45-Invid - ASG-RemoteDesktop 2017 - invjkp-sccm03 (Work Resources).png

4. Go With Default settings, Next, Next, Summary, Close.
2017-09-04 09_29_19-Invid - ASG-RemoteDesktop 2017 - invjkp-sccm03 (Work Resources).png

5. Right click on the CI, go to Properties> Settings and New
2017-09-04 10_03_32-Invid - ASG-RemoteDesktop 2017 - invjkp-sccm03 (Work Resources).png

6. Do the settings like this
6.1 Name it to ” Check for a Registry Value”
6.2 Change Setting type to Script
6.3 Change Data type to String
2017-09-04 10_08_24-Invid - ASG-RemoteDesktop 2017 - invjkp-sccm03 (Work Resources).png
6.4 Click on Discovery script
6.5 Script language to Windows Powershell, then copy this

function Get-Registrykey
    param ()

    Try {
    $Result = Test-Path "HKLM:\Software\Classes\MJ"

    ForEach-Object {
            If($Result -match "True") {
                $State = 1}
            ElseIf($Result -match "False") {
                $State = 0}
   catch {
   # Error hantering



2017-09-04 10_10_13-Invid - ASG-RemoteDesktop 2017 - invjkp-sccm03 (Work Resources).png

6.6 Click on Ok
7. Go to the Compliance Rule Tab
2017-09-04 10_11_41-Invid - ASG-RemoteDesktop 2017 - invjkp-sccm03 (Work Resources).png

8. Click on New
9. Then change the Following value to 1, and Check the box “Report noncompliance if this setting instance is not found. Then click on OK
2017-09-04 10_13_40-Invid - ASG-RemoteDesktop 2017 - invjkp-sccm03 (Work Resources).png

10. Apply, Apply, Ok.
11. Go to Configuration Baselines, Create Configuration Baseline
2017-09-04 10_15_59-Namnlös - Paint.png

12. Name it to ” Check for a Registry Value
13. Click on Add, Configuration Item
14. Ok.
2017-09-04 10_18_27-Invid - ASG-RemoteDesktop 2017 - invjkp-sccm03 (Work Resources).png

15. Right click on the baseline, then Deploy
2017-09-04 10_19_22-Namnlös - Paint.png

16. Do the settings like this,
16.1 “Check Remediate noncompliant rules when supported”
16.2 “Check Allow remediation outside the maintenance window”
16.3 Select a Collection that you want to run the script on.
16.4 Simple Schedule, 1 Time each day.
2017-09-04 10_20_05-Invid - ASG-RemoteDesktop 2017 - invjkp-sccm03 (Work Resources).png
16.5 Ok.
17. Now we are done, The clients will report back if the registry exists or not.

Also shared the Files here, if you just want to import the CI
CI – Check for a Registrykey

Thanks for reading.