Update CustomSettings.ini file remotely!

Got on a discussion this week with someone how to use PowerShell to update an MDT CustomSettings.ini file over the network. Well a *lot* of CS.ini files.. ūüôā

My manager is the Global Ops Manager and now he is asking me to find a way to run [update of customsettings.ini] on about 50 servers worldwide so the other MDT admins don’t have to log onto each server just to add one line.

The example given was to update the AdminPassword in CS.ini. I hope this company is following best practices, and disabling the local Administrator account and/or changing the Password once joined to the domain or connected to SCCM.

Anywho, INI files are a tad bit difficult to modify in Powershell because there are no native PowerShell or .NET functions to perform the action. So instead we need to do some ugly Pinvoke calls to the appropriate Win32 API.



New script – Import Machine Objects from Hyper-V into ConfigMgr

Quick Post, been doing a lot of ConfigMgr OSD Deployments lately, with a lot of Hyper-V test hosts.

For my test hosts, I’ve been creating Machine Objects in ConfigMgr by manually entering them in one at a time (yuck). So I was wondering what the process is for entering in Machine Objects via PowerShell.

Additionally, I was curious how to inject variables into the Machine Object that could be used later on in the deployment Process, in this case a Role.

Up next, how to extract this information from VMWare <meh>.

New Sample for MDT (Custom Actions)


MDT Litetouch Action Property Page Sample

Fancy Example


MDT has several pre-defined pages for common task sequence editing tasks. You’ve seen them in the MDT Litetouch Task Sequence Editor, under General, Disks, Images, Settings, and Roles.

They help abstract the ugly command line and scripting code behind the scenes for the user.

Recently I had an idea for a super-wiz-bang property page type for MDT Litetouch, and asked “are there any MDT LTI samples out there?”. I knew Config Mgr had a SDK Sample and I’ve been using it for a while now to create SCCM Task Sequence Actions pages.

The answer came back “There was an MDT Litetouch SDK, but not anymore.” (Long story for another day)

“Someone should create a sample!” I said!

“Cool Keith, when you figure it out, can you share the results? :)” For those of you who wonder, how does one become a Microsoft MVP? This, so here we go.

The Basics


MDT Task Sequence Action Pages are simply C# Windows Form Control Library, with some standard API interfaces so it can be called from the Litetouch Wizard Host. The MDT team designed the API to closely resemble the System Center Configuration Manager Action Page API.

  • There are entry points for when the control is initialized.
    • Use this opportunity to load the UI elements with the saved data from the PropertyManager (aka TS.xml)
  • There are entry points for when the “OK” and “Apply” buttons are pressed.
    • Use this opportunity to save the UI elements with to the PropertyManager

There are several dependent classes required by the sample, they are contained in the ‘c:\program files\Microsoft Deployment Toolkit\bin\Microsoft.BDD.Workbench.dll’ assembly, so you will need add this reference to your project.

Anything else you want to add in the control, can be done if you know the correct C# code to get the job done.


Once you have created the DLL Library, we will need to add it so MDT Litetouch console knows about it.

First off, copy the DLL to the ‘c:\program files\Microsoft Deployment Toolkit\bin’ folder.

Secondly, we’ll need to add an element to the actions.xml file.

	<Name>Install PowerShellGet Action</Name>
	<Action>powershell.exe -Command  Install-Package -Force -ForceBootStrap -Name (New-Object -COMObject Microsoft.SMS.TSEnvironment).Value('Package')</Action>
	<Property type="string" name="Package" />

For this sample, I included a PowerShell libary module with two functions, one to register the new control, the other to remove the control. Easy!

The Sample

The sample in this case is pretty small.

There is one TextBox (as shown above), that prompts the user for the name of a PowerShell Package.

The package name get’s added to the TS.XML, along with the command, in this case it calls PowerShell.exe with the cmdlet Install-Package. We use COM to connect to the SMS environment space to get the package name and go.

You can use the build.ps1 script to compile the sample, and create PowerShell library to install the control within MDT Litetouch.


Well I created this sample, because I have some ideas for some MDT LiteTouch (and SCCM) Action controls.

  • Fancy UI for installation of applications through Chocolatey
  • Run scripts and modules from PowerShellGallery.com
  • Other ideas, let me know (comments or e-mail)


New Tool: Get the Latest Windows 10 Cumulative Updates!

TL;DR – Programmatically get the latest Windows 10 Cumulative Updates!

Got a request from someone on an internal e-mail Distribution list recently, asking how to find out the latest Windows 10 (or Windows Server 2016) Cumulative Update.

Normally you can find these updates by going to this Microsoft KB article, then finding the right Operating System Version. Then you use the KB article number to go to Windows Update, and find the correct download link, then download the file.

I wanted to update this for another project, so I took it as a challenge to code in PowerShell.

New Tool

For this tool, I placed the source code up on GitHub.com, in a new gist. A gist is just a file that can be edited, version controlled, and shared out publicly on the GitHub.com site.

Given a Windows Version (build number), and a couple other search strings, will programmatically determine what the correct download links are for this Windows 10 (or Windows Server 2016).√ā

The output can also be piped into BITS so you can just download locally.


Get the links for the latest Windows 10 Version 1703 Updates:



Additionally we can also download the files using the BITS command Start-BITSTransfer







Hackers vs PowerShell!

OK, I have a couple of servers in my home lab. I suppose it has a lot to do with the fact that I work with ConfigMgr and other server tools.

Additionally, I like using Remote Desktop to connect and manage my machines, I suppose it has something to do with the fact that I once work as a Developer on the Terminal Services Client Team.

And yes, I have a couple of ports open to the Internet. <I am now reconsidering this :^(  >


Anyways, I was looking today at the performance on one of my machines, and noticed one of the remote desktop server processes was being accesses by someone in Germany. Germany?!!? What???


Something running on FastWebServer.de and Your-Server.de.

The network traffic was slow, not as fast as my active Remote Desktop session. What could it be? After some thought, I figured it could be someone attempting to log in using different credentials. Perhaps using a bot to try various credentials. Um… OK


PowerShell to the rescue.

I used the get-eventlog cmdlet to search for the right log (Security) and event entry (4625).

get-eventlog -log Security -InstanceId 4625 | Measure-Object

981 entries!! Youza!

Further analysis shows that entry #6 of the ReplacementStrings property shows the account that was used to logon. A frequency analysis should be in order:

PS E:\> get-eventlog Security -InstanceId 4625 | 
   %{$_.ReplacementStrings[5]} | group | 
   sort Count -Descending | select -first 10 Count,Name

Count Name
----- ----
  150 TEST
  150 ADMIN
  150 DEMO
  150 ROOT
    7 EDDIE
    7 CAFE
    7 BILL

The names appear to be random, nothing specific to me, needless to say I have disabled the local administrator account, and begun other security measures.

But I thought the powershell was fun! :).


Display WPF XAML code in PowerShell

Last week I went to the Minnesota Management Summit at the Mall of America #MMSMOA, and I got inspired to work on a few projects in my backlog.

One of the presentations I went to was with Ryan Ephgrave (@EphingPosh on Twitter.com), and his talk on “Better Know a PowerShell UI“.

Overall it was a great presentation, and I learned a lot. And got me thinking about some of the things I could do with a framework I started earlier in the year but never got around to finishing.


Without further adieu, I present Windows Presentation Framework for PowerShell (WPF4PS). It is also the first project I’ve released as source code on GitHub:



Most WPF + PowerShell examples are created with a lot of custom code to add in event handlers for the User Interface elements. The goal is to find all control elements on the page and if there is a pre-defined function created, then use it. Which means minimal code for overhead.


Here is a fully functional example:

  • Load the WPF4PS module
  • Import a XAML defined in Visual Studio
  • Create a scriptBlock to handle the button Click
  • Create a HashTable to pass data between our script that the XAML Window
  • Call the Show-XAMLWindow function
  • Get the value of the TextBox from the Hash


WPF4PS framework Examples

Simple Example

Copyright Keith Garner, All rights reserved.



import-module $PSScriptRoot\wpf4ps -force

$MyXAML = @"
<Window x:Class="WpfApplication1.MainWindow"
 Title="MainWindow" FontFamily="Segoe WP Semibold" Width="400" Height="300" Name="WindowMain" >
 <Label>Hello World</Label>
 <Button x:Name="Button1" Content="Big Red Button" Width="125" Height="25" Background="#FFDD0000" Margin="0,60,0,0"/>
 <TextBox x:Name="textBox1" Height="23" Width="200" />

$MyControl = [scriptBlock]{

    function global:button1_click()
        "Click the Big Red Button`n" + $TextBox1.TExt  | show-MessageBox 


$MyHash = [Hashtable]::Synchronized(@{ textBox1 = "Hello World" })

Show-XAMLWindow -XAML $MyXAML -ControlScripts $MyControl -SyncHash $MyHash

$MyHash.TextBox1 | Write-Host


My goal is to work out the kinks and eventually upload/share this on PowerShellGallery.com.

For example:

  • I created two Show-XAMLWindow() functions in the library, one inline and another Async. I still don’t know what the usage case of Async is.
  • Ryan Ephgrave did some XAML + Powershell examples in his “Better Know a PowerShell UI”¬†blog series with XAML “Binding” elements, something I have not used in the past, so I excluded them from this package.
  • I had to do some weirdness with the declaring the functions above as “global” to make them visible to the Module

If you have feedback on the layout or usage, please let me know.


Fix for Windows 1511 ADK bug

First off, yes, I have a new job working for 1e! I’m super excited, and I should have posted something about it, but I’ve been super busy. My first day on the job was at a customer site in Dallas, and I’ve been on the go ever since, working on this and that (stay tuned :^).

As many of you may have known, there has been a pretty big bug in the Windows 10 Version 1511 ADK, it’s caused all kinds of interop problems with Configuration Manager. Well Microsoft released a fix today! KB3143760. Yea!

Well I opened up KB3143760, and yikes! The instructions are a bit dry. Mount this, patch that, watch out for the data streams!

I needed to patch my local Windows 1511 ADK¬†installation because I’m working on a SCCM+MDT Refresh scenario, and I don’t want to uninstall the 1511 ADK. Perfect timing, if only there was a way to automate this..


Here is a link to a PowerShell script I wrote to auto-magically patch your WinPE files!


This script will:

  • Download the patch (no need to go through the E-Mail process)
  • Take care of all the stream issues (really I don’t use IE/Edge, so no security streams)
  • Auto extract the patch contents
  • Mount the wim file
  • Patch the appropriate dat files
  • Fix the permissions
  • Dismounts the WIM
  • Cleans up all left over files

So, for example, if you wanted to patch all of the WinPE Wim files in the ADK directory (before importing them into SCCM), you can run the following command:

get-childitem 'C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\*.wim' -recurse | .\Repair-1511ADK.ps1 -verbose

Lately, when programming in PowerShell, I have taken the “write-host considered harmful” rule to heart, so by default, there is *NO* std console output.¬†Instead, I redirect most¬†information output to “verbose”, so if you want to see what is happening in the background, use the -verbose switch.


Hopefully, moving forwards, this will be the *last* time I place a new script up on OneDrive, really I should be moving towards something more… modern… like GitHub.