Create Desired State Configuration (DSC) “snippets”-like resources

In the following help file…

Get-help about_DesiredStateConfiguration

… there’s a cool tip to show the syntax of the DSC resources keywords

DSC provides the following set of built-in resources that you can use in a configuration script: Registry, Script, Archive, File, WindowsFeature, Package, Environment, Group, User, Log, Service, and WindowsProcess. The example above demonstrates how to use the File and WindowsFeature resources. To see all the properties that you can use with a given resource, place the cursor on the resource keyword (for example, File) within your configuration script in the Windows PowerShell ISE, hold down CTRL, and press the SPACEBAR.

If I press CTRL+spacebar, I’ve the following:

That’s cool, but it doesn’t tell me which one is mandatory… 😦

Here’s what I did to generate “snippet”-like DSC resources:

[System.Management.Automation.Language.DynamicKeyword]::GetKeyword() | ? { $_.Keyword -in @(
    'File',
    'Registry',
    'Service',
    'Archive',
    'Script',
    'WindowsFeature',
    'Package',
    'Environment',
    'Group',
    'User',
    'Log',
    'WindowsProcess'
) } | ForEach-Object -Begin {
    'Configuration TestDSCConfig {'
} -Process { 
    "`t{0} Test{0} " -f ($_.Keyword)
    "`t{"
    $_.Properties.Values | ForEach-Object -Process { 
        if ($_.Mandatory) {
            "`t`t{0} = {2} # {1} ; Manadatory" -f $_.Name,$_.TypeConstraint,$($_.Values -join "|")
        } else {
            "`t`t{0} = {2} # {1}" -f $_.Name,$_.TypeConstraint,$($_.Values -join "|")
        }
    } -End {
        "`t}"
    }
} -End {
    "}"
}

Now, all I need to do is to remove properties I don’t need, fill-in mandatory properties… 😀

Advertisements

WSUS 2012: viewing superseded and superseding updates

I’ve shown over the last few months how Powershell can help manage a WSUS built-in a Windows Server 2012:

  • Problem

Now that Office 2010 SP2 has been released and that the catalog of my WSUS has been updated, I cannot filter anymore superseded Office 2010 updates with the following code:

# View superseded updates that were previously approved            
(Get-WsusServer).SearchUpdates("2010") | Where {            
 ($_.IsSuperseded) -and            
 ($_.isApproved)             
} |             
ft Title,SecurityBulletins,IsApproved,IsSuperseded -AutoSize 

If I run this, I got more than I expected:

I was just expecting bulletin MS12-34 being supersed by MS13-054 😦

It appears that the ‘IsSupersed’ property isn’t precise enough and that I need more information like the ones provided by the “Updates superseding this update” and the “Updates superseded by this update” properties that you can see in the above snapshot of the WSUS console.

  • Solution

The above search returns a collection of Microsoft.UpdateServices.Internal.BaseApi.Update objects.

Each object has many properties by default but not the aboves juicy ones (“Updates superseding this update”) I’m looking for.

That said, each object has also many methods that could help.

To get a collection of “Updates superseding this update”, the GetRelatedUpdates needs to be used according the following MSDN page on How to Get Update Details

How should I implement and use this method?

I can enumerate UpdateRelationship values and their meaning with this code:

[System.Enum]::GetValues([Microsoft.UpdateServices.Administration.UpdateRelationship]) | ForEach-Object -Process {
    '{0} -> {1}' -f ([Microsoft.UpdateServices.Administration.UpdateRelationship]::$_.Value__),$_
}

This step will just allow me to save some typing below…

Now the idea is to add on the fly a ‘UpdatesThatSupersedeThisUpdate’ property to each Microsoft.UpdateServices.Internal.BaseApi.Update object returned by the search.
This property should be filled-in with the collection of Titles returned by the GetRelatedUpdates method.
Let’s have a look at the changes I made to achieve this:

# View superseded updates that were previously approved            
(Get-WsusServer).SearchUpdates("2010") | Where {            
 ($_.IsSuperseded) -and            
 ($_.isApproved)             
} | ForEach-Object -Process {
    $_ | Add-Member -MemberType ScriptProperty -Name UpdatesThatSupersedeThisUpdate -Value {
    ($this.GetRelatedUpdates(5)).Title
    } -Force -PassThru
} | ? UpdatesThatSupersedeThisUpdate -notmatch "Service\sPack\s2" |
 fl Title,SecurityBulletins,IsApproved,UpdatesThatSupersedeThisUpdate 

I’ve added a foreach loop that processes each update object and adds a collection of titles of updates that superseded this update by first calling the GetRelatedUpdates method and then using an implicit foreach to return only the title property. The Add-Member cmdlet allows me to create this script property on the fly.

As this new scriptproperty is a multiline string, the match operator can be used to filter it.

I got only MS12-034 as a result, perfect that’s exactly what I was looking for 😎
MS12-034 is superseded by SP2 but SP2 isn’t the only update that supersedes MS12-034.

Note also that I’m actually using a feature of the match comparison operator. When used on multilines, it doesn’t return true or false.

This is what you can read with

Get-help about_Comparison_Operators

If the input is a collection, the -Match and -NotMatch operators return
the matching members of that collection, but the operator does not
populate the $Matches variable.

Did I already say that Powershell rocks!? 😀