Tag Archives: Desired State Configuration

Script Sharing – Determine the Node to GUID Mapping

If you’ve been following my recent posts, you know that the PowerShell Summit North America 2015 is only days away. I’ve used April to learn (as much as I can) about DSC. I wasn’t completely new to it — I’ve been following along for a bit — but there is still plenty I didn’t know, or at least haven’t experienced hands-on. Anyway, I’m doing whatever I can to absorb as much DSC knowledge as possible, before next week.

While I only have a single target node at this point, I stopped and wondered how obnoxious it may be to determine the GUID to node mapping, when I update a configuration script. I know I can get it from the target node, by using Get-DscLocalConfigurationManager, but what’s an easier way to get them all, at once? While I could query all the nodes, I figured I can also query my MOFs’ directory, providing we trust that source, and why shouldn’t we.

I wrote out a quick and dirty function that I’ve included below. Point this function at your MOFs’ directory on your DSC Pull Server and ta-da, it’ll create a PSCustomObject with your node names and matching GUIDs.

Disclaimer: I’m still learning DSC and may one day realize this function was a waste of time.

Function Get-TMDSCGuid {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory = $true)]
        [string]$Path
    )

    Begin {
        Write-Verbose -Message 'Collecting MOF files.'
        try {
            $Files = Get-ChildItem -Path $Path -Filter '*.mof' -ErrorAction Stop | Select-Object -Property *
        } catch [System.Management.Automation.ItemNotFoundException] {
            Write-Warning -Message "This path does not exist: $Path"
        }
    } # End Begin.

    Process {
        If ($Files) {
            Write-Verbose -Message 'Checking MOF files.'
            Write-Verbose -Message 'Writing ComputerName-GUID Mappings.'
            ForEach ($File in $Files) {
                $ComputerName = $null
                try {
                    $ComputerName = (Get-Content -Path $File.FullName |
                        Where-Object {$PSItem -like '@TargetNode*'}).Split('=')[-1].Trim("'")
                } catch {
                    $NoTargetNode += "$($File.Name);"
                } # End Try-Catch.

                If ($ComputerName) {
                    $Object = [pscustomobject]@{
                        ComputerName = $ComputerName
                        Guid = $File.BaseName
                    }
                    Write-Output -Verbose $Object
                } # End If.
            } # End ForEach.

            If ($NoTargetNode) {
                Write-Verbose -Message "---MOF Files without @TargetNode section---"
                $NoTargetNode = ($NoTargetNode.Trim(';')).Split(';')
                ForEach ($Node in $NoTargetNode) {
                    Write-Verbose -Message ($Node)
                } # End ForEach.
            } # End If.
        } Else {
            Write-Verbose -Message 'Cannot locate any MOF files.'
        }
    } # End Process.

    End {
        Write-Verbose -Message 'Function is done running.'
    } # End End.
} # End Function.

Below is an example of the output that will be displayed when we invoke the function against the directory that holds our <guid>.mof files for our DSC Pull Server.

ComputerName                                                       Guid
------------                                                       ----
serverX.mydomain.com                                               2766ffba-0c66-4358-8426-1a216c2b9d25
serverY.mydomain.com                                               7699bbcd-1a32-1429-9831-0f197d3a9b14
serverZ.mydomain.com                                               3224abda-2b41-4925-2948-4c317a1c0a54

 

Using OutVariable — Why Don’t I Do that More Often?

This week, Microsoft Virtual Academy had two live events about DSC (Desired State Configuration), hosted by Jeffery Snover and Jason Helmick. I watched as much as I was able, but there were some problems at work that demanded my attention, and so I was grudgingly pulled away from a good portion of both sessions. Luckily for me, and for you, if you missed them, is that the videos should be up in the next two to three weeks. That will allow anyone who is interested the ability to move through the modules (think sections, not PowerShell modules) around other ongoing tasks — like work.

I didn’t start this post to discuss DSC, but instead because of what I watched Jeffery Snover do several times. While I’ve always been aware of the existence of the -OutVariable common parameter, I’m not even sure if I’ve ever used it or not (although I’m certain I’ve used -ErrorVariable). This parameter is a great way to view your command’s results immediately, and write them to a variable at the same time.

In this example, we return the computers’ names from (all of) Active Directory (AD) that have the word ‘physical’ somewhere inside their description property. The problem here is that if we need to generate this list a second time, we’ll have to run the command again. This can be resource intensive, depending on the command, and not inline with best practice — at least, my best practice.

PS C:\> (Get-ADComputer -Filter {Description -like '*physical*'}).Name
DC01
DC02
DC03
WEB01
WEB02

In this example, we write our results to the variable $Physical. The difference here is that we don’t write the results to the screen automatically, but only when we echo the variable’s contents.

PS C:\> $Physical = (Get-ADComputer -Filter {Description -like '*physical*'}).Name
PS C:\> $Physical
DC01
DC02
DC03
WEB01
WEB02

In this example, we combine the best of both worlds: instant results written to the screen, with the “same” values stored in a variable. Notice that when I echo the variable, $P, it returns more than just the Name. This is because all the properties were written to the variable, before we displayed only the Name property. Note: I’ve concatenated the results after the first computer’s full results.

PS C:\> (Get-ADComputer -Filter {Description -like '*physical*'} -OutVariable P).Name
DC01
DC02
DC03
WEB01
WEB02
PS C:\> $P
DistinguishedName : CN=DC01,OU=Domain Controllers,DC=mydomain,DC=com
DNSHostName       : dc01.mydomain.com
Enabled           : True
Name              : DC01
ObjectClass       : computer
ObjectGUID        : ...
SamAccountName    : DC01$
SID               : ...
UserPrincipalName :
...

Here’s how we can return only the Name property, using this variable.

PS C:\> $P.Name
DC01
DC02
DC03
WEB01
WEB02

Hopefully I can remember to use this common parameter more often. We’ve been taught to store our results in a variable, so we aren’t continually performing resource intensive queries. This is a great way to do that, with the option to have the results of a command written to the screen immediately. Adios, friends.