I know I’m blabbering a lot about PowerShell.  I’m still poking a stick at it, which is a good thing.  I’ve always found that songs I take a liking to immediately, are the ones I end up hating most later on.  The ones that grow on me slowly are those I never tire of hearing.  People are like that.  Food is like that.  Movies, and TV shows.  And programming languages as well.

Also, it’s worth noting that I’m not a PowerShell expert.  I just have a blog and they don’t ask for a license when I start typing, so this is what happens.  Tragic, yes.

I also realize that what you’re reading right now, amounts to absolute nothing in the realm of tangible value.   I’ve only had two hours of sleep, so I need to pour this out of my brain bottle and crash for the night.

LISP was like that for me.  KiXtart as well, for a while.  VBScript was okay, but only because I had to use it.  PowerShell is different for me.

Playing with XML loading and parsing, and turning it into other things.  It’s like a Lego kit (can I say “Lego” without being sued?  Let’s see).

 <key name="ADK10" path="HKLM:SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{c09c49ab-d6a5-4543-bb31-639821977b42}" />
 <key name="MDT2013" path="HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{F172B6C7-45DD-4C22-A5BF-1B2C084CADEF}" />
 <key name="SCCM1511" path="HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\SMS Primary Site" />
 <key name="SQL2014" path="HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{5082A9F3-AEE5-4639-9BA7-C19661BA7331}" />
 <key name="CMToolkit" path="HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{4FFF7ECC-CCF7-4530-B938-E7812BB91186}" />
 <key name="CMPsCmdlet" path="HKLM:SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{7C91CE57-E49D-4F2D-A47D-0395A39C9C33}" />
 <key name="ADContainer" path="ad:CN=System Management,CN=System,DC=contoso,DC=com" />
 <key name="WDS" path="FEATURE:WDS" />
 <key name="WSUS" path="FEATURE:UpdateServices" />
 <pkg key="NULL" name="WDS Role" file="Install-WDS.ps1" />
 <pkg key="ADContainer" name="Create Container" file="Create-ADContainer.ps1" />
 <pkg key="NULL" name="Extend AD Schema" file="Extend-ADSchema.ps1" />
 <pkg key="ADK10" name="Windows 10 ADK" file="Install-ADK.ps1" />
 <pkg key="SQL2014" name="SQL Server 2014" file="Install-SQL2014.ps1" />
 <pkg key="WSUS" name="WSUS Role" file="Install-WSUS.ps1" />
 <pkg key="MDT2013" name="MDT 2013 Update 2" file="Install-MDT.ps1" />
 <pkg key="SCCM1511" name="ConfigMgr 1511" file="Install-SCCM1511.ps1" />
 <pkg key="CMToolkit" name="ConfigMgr Toolkit v2" file="Install-CMToolkit.ps1" />
 <pkg key="CMPsCmdlet" name="ConfigMgr Powershell Cmdlets" file="Install-CMPsCmdlets.ps1" />

So, what I’m doing is probably completely wrong and stupid, but it’s fun, so I do it.  Anyhow, I digress, but I want to read in the “sequence” data and perform some secondary associative queries from “detectionkeys”.  I’ll hum a few bars, but it goes something like this…

$ScriptPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
[xml]$configdata = Get-Content "$ScriptPath\config.xml"

function Get-DetectionPath {
  param (
    [parameter(Mandatory=$True)] [string] $KeyName
  $cfg.detectionkeys.GetElementsByTagName("key") | 
    Where {$_.name -eq $KeyName} |
      Select -ExpandProperty Path

function Detect-Key {
  param (
    [parameter(Mandatory=$True)] [string] $KeyPath
  if ($KeyPath.Substring(0,7) -eq "Feature") {
    $try = Get-WindowsFeature -Name $KeyPath.Substring(8)
    if ($try -ne $null) {
      $x = $try | select -ExpandProperty InstallState |
        Where {$_ -eq 'Installed'}
      $($x -ne $false)
  else {
    $(Test-Path $KeyPath)

$cfg = $configdata.settings

foreach ($pkg in $cfg.sequence.pkg) {
  write-host $pkg.name
  write-host $pkg.file
  write-host $pkg.key
  $detkey = Get-DetectionPath $pkg.key
  if ($pkg.key -ne "NULL") {
    if (Detect-Key $detkey) {
      Write-Host "installed"
    else {
      Write-Host "not installed"
  write-host "-------------------"

So, there you have it.  It’s a 1.0 thing, and like I said, I’m still learning.  The output looks like this…




2 thoughts on “PowerShell Meandering

  1. So first of all, by running the Get-WindowsFeature cmdlet, your assuming that the script is being executed on a Server OS – since that cmdlet only pertains to Servers (at least it fails on my Win10 Home edition system). You should add the following check to ensure that fact and if not report an error that server information is not available on a client OS and suggest that the script be run on a server.

    Server OS’s should include the word “Server” in their caption (I’m pretty sure they all do) and as such this check will return True for Server OS’s and False for clients.

    (Get-WmiObject -class Win32_OperatingSystem).Caption -contains “Server”

    Second, I think you should follow Don Jones article on creating custom objects for output rather than dumping it to text using Write-Host.


    Using custom objects gives you m,ore flexibility because you can sort the object, output to a table, xml file, html file, csv file, or grid. You could also pass this object on the pipeline as input to another cmdlet or script. 🙂

    Remove lines 32 and below in your script and replace with the following:

    foreach ($pkg in $cfg.sequence.pkg) {
    $package = New-Object –TypeName PSObject
    $package | Add-Member –MemberType NoteProperty –Name Name –Value $pkg.name
    $package | Add-Member –MemberType NoteProperty –Name File –Value $pkg.file
    $package | Add-Member –MemberType NoteProperty –Name Key –Value $pkg.key
    $detkey = Get-DetectionPath $pkg.key
    if ($pkg.key -ne “NULL”) {
    if (Detect-Key $detkey) {
    $package | Add-Member –MemberType NoteProperty –Name Installed –Value $True
    else {
    $package | Add-Member –MemberType NoteProperty –Name Installed –Value $False
    else {
    $package | Add-Member –MemberType NoteProperty –Name Installed –Value $False
    Write-Output $package

    1. It is being run on a server os, that is correct. It’s just a small piece of a bigger project, but one that I was playing around with to see if it added value to the overal effort. I like the New-Object approach. That’s sort of like making a hash table of data to perform secondary iteration.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s