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.



MDT – Check if the model is certified, with mail flow.

Hey Again! Long time no seen, just had an amazing vacation. How are you guys?
Now with some new pieces of stuff that I´ve been working on.

In our company, we have a lot of different models, and sometimes they deploy them without me knowing. And therefore I didn’t put in any drivers.


  • A pop-up box prompt while deploying a machine in MDT (this could work in SCCM also, not tested), So the installation doesn’t continue
  • A mail with the model name, computer name, and deployment share name, So i can put the correct model drivers into the MDT workbench.


I made a PowerShell script that solves this. You need to fill the parameters to make it work in your environment.

Like this2018-08-13 14_01_16-Administrator_ Windows PowerShell.png
.\ComputerNotCertfied.ps1 -SMTPServer -SMTPPort 25 -From -To

Little explanation of the parameters
-SMTPServer (To send an email without putting any credentials, I’m I using a SMTP relay)
-SMTPPort (And I need to specify the ports as well for the relay)
-From (From which address I want to specify )
-To (To which address I want to specify)

#    ComputerNotCertfied.ps1
#Make a step in MDT, and a popup will promt the user, that the "Computer is not certified, #a mail have been sent to the system administrator"
#Then the script is sending a email to the system-admins.
#And after that, Shuts down the computer.

#Created: 2018-08-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
#ComputerNotCertfied.ps1 -SMTPServer -SMTPPort 25 -From -to

[parameter(mandatory = $True, HelpMessage = "Name of the SMTP server?")]

[parameter(mandatory = $True, HelpMessage = "Name of the SMTP relay port?")]
[parameter(mandatory = $True, HelpMessage = "Which adress are you sending from?")]
[parameter(mandatory = $True, HelpMessage = "Which adress are you sending to?")]
$wshell = New-Object -ComObject Wscript.Shell
$wshell.Popup("Computer is not certified, a mail have been sent to the system administrator.", 0, "Error", 0x0 + 0x1000)

#Gather computer information
$log = get-content "C:\MININT\SMSOSD\OSDLOGS\BDD.log"
foreach ($line in $log) {
    if ($line -like "*DeployRoot is now =*") {
        $Deploymentshare = "Deploymentshare " + "$($line.split("=")[1].split(']')[0])"

$Model = wmic computersystem get model
$Make = wmic computersystem get manufacturer

#Send mail with gathered information
$Subject = "New Model to certify"
$Body = "$Model `n $Make `n $Computername `n $Deploymentshare"
Send-MailMessage -From $From -to $To -Subject $Subject -Body $Body -SmtpServer $SMTPServer -port $SMTPPort

#Shutting down computer


  1. Copy this script (  zip it up first 😉 ) into the script folder in your Deployment share.
  2. Make a new step in your MDT task sequence, Choose PowershellScript
    2018-08-13 14_39_30-Photos.png
  3. Put this script into an MDT Step, and specify the parameters you want to use.
    PowerShell script: ComputerNotCertified.ps1
    Parameters: -SMTPServer -SMTPPort 25 -From -To
    2018-08-13 14_41_04-sql.invidjkp.local - ASG-RemoteDesktop 2018 - invjkp-mdt01.png
  4.  Go to Options tab and click on Add button.
  5. Add then “If statement“, then choose “none
    2018-08-13 14_45_15-sql.invidjkp.local - ASG-RemoteDesktop 2018 - invjkp-mdt01.png
    2018-08-13 14_45_56-sql.invidjkp.local - ASG-RemoteDesktop 2018 - invjkp-mdt01.png
  6. Mark “if none of the conditions are true, then Add Query WMI2018-08-13 14_47_14-sql.invidjkp.local - ASG-RemoteDesktop 2018 - invjkp-mdt01.png
  7. Now we need to specify the models that are already certified.
    (Put in following text (in this example I put in the Virtual machine, in your case it could be “HP 820 G3”:
    SELECT * FROM Win32_ComputerSystem WHERE Model Like “Virtual Machine”
    2018-08-13 14_49_56-sql.invidjkp.local - ASG-RemoteDesktop 2018 - invjkp-mdt01.png
    2018-08-13 14_55_06-sql.invidjkp.local - ASG-RemoteDesktop 2018 - invjkp-mdt01.png
  8. Click Ok, then Apply, close the Task Sequence.
  9. Then “Update Deployment Share”
  10. Done

How does it looks like when we run a computer that is not certified?

When the computer run the “Check If the computer is certified” step.
This will pop-up

When you click “Ok“, the computer stops and shuts down.

Then you check your mail inbox.
2018-08-13 14_57_44-mdt - Inkorg - mdt - Outlook.png

Voila! Now you got an email that they tried to run a un-certified model.

Thanks for reading


Windows update Problem – Installing KB4284815 – Code 800F0831 – Store corruption, manifest missing for package: Package_2165_for_KB4103725

Hey! I discovered that some of my servers (Server 2012 R2) have some patching problems now in June.

When im trying to patch the KB4284815 – June 12, 2018—KB4284815 (Monthly Rollup)

Then im getting this Error.
Code 800F0831

I started to investigate the CBS.log in “C:\Windows\Logs\CBS\CBS.log”

And as I assumed, I got an Error Code
2018-06-25 09:25:48, Info CBS Store corruption, manifest missing for package: Package_2165_for_KB4103725~31bf3856ad364e35~amd64~~

2018-06-25 09:25:48, Error CBS Failed to resolve package ‘Package_2165_for_KB4103725~31bf3856ad364e35~amd64~~′ [HRESULT = 0x800f0831 – CBS_E_STORE_CORRUPTION]

Ok. It says something about KB4103725 – May 8, 2018—KB4103725 (Monthly Rollup)

To solve this we need to reinstall that patch again (last month patch), something happend with the Store Corruption.

And I´ve made a simple Powershell script to solve it.

Just follow these instructions:

#Created: 2018-06-25
#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.

# 1. Download the .MSU file from Microsoft.

# 2. Put it in the C:\Temp folder.
# 3. Locate the folder
Set-location C:\temp
# 4. Extract .msu file.
expand .\windows8.1-kb4103725-x64_cdf9b5a3be2fd4fc69bc23a617402e69004737d9.msu -f:* C:\TEMP

# 5. Install the update again,
DISM.exe /Online /Add-Package /PackagePath:C:\TEMP\

# 6. Your done. Try to install the new patch again.

If you have more servers with this kind of problems, you can just download the .msu file, put it in a sccm package. Then add this to the script.

#Make folder
New-item -Path .\Temp -ItemType Directory -Force
#Copy .msu file
Copy-Item -Path .\windows8.1-kb4103725-x64_cdf9b5a3be2fd4fc69bc23a617402e69004737d9.msu -Destination C:\temp

Good Luck


Is Windows Powershell Complete? What about Powershell Core?

Just looked at a very exciting video with Jeffrey Snover, and its about Powershell.

Gonna recap this video in a few pictures for you guys.

He explains that Windows Powershell is done, no more “New features” and so on. Just security patches etc.

So whats happens now? They building a New Tool, called Powershell Core

Taking the best of Windows Powershell, and its no need of .net framework.


They finnally go “Open source” and run on Anything, even your dishwasher 😉

To download this go to :

And you can remote “Windows powershell” from that tool. So dont be scared.

And like picture above, you can just
Import -module .\rModule.psm1 (Ofc you need to download that module first to your machine and its not available yet unfortunately)
Get-Command -Module rModule  (Ah Okay, we can write Get-rModule)
Get-rModule -ListAvailable -computername Localhost

Now its imported all the modules that are on the local machine. Then we take Applocker for an example.
So now
Import-rModule Applocker -computername Localhost
Get-Command -Module Applocker

And it Works.

Kinda cool huh?

Here’s the video if you wanna look at it: