Powershell DSC Syntax for Binary Registry Key

dscpowershellwindows-registry

What should be a simple registry DSC configuration has turned into a somewhat frustrating piece of guesswork. I'm trying to setting a binary registry key. I am finding it impossible to find the right format for the value data to get the key set correctly. I am trying to transform this registry file into DSC:

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\DefaultSecurity]
"SrvsvcShareAdminConnect"=hex:01,00,04,80,64,00,00,00,70,00,00,00,00,00,00,00,\
  14,00,00,00,02,00,50,00,03,00,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,\
  00,00,05,20,00,00,00,20,02,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,00,\
  00,05,20,00,00,00,25,02,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,00,00,\
  05,20,00,00,00,27,02,00,00,01,01,00,00,00,00,00,05,12,00,00,00,01,01,00,00,\
  00,00,00,05,12,00,00,00

I have tried this with both registry and xregistry resource and hit the same format error ( I really don’t mind which I use). I have tried providing the data as an a single string, an array of strings, an array of strings appended with 0x to show it is hex etc. Ihave tried the suggestion here as well.

The closest I got is with the configuration below, which seemed to work:

   Registry disableAdminShare {
            Ensure      = "Present"
            Key         = "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\lanmanserver\DefaultSecurity"
            Force       = $true
            ValueName   = "SrvsvcShareAdminConnect"
            ValueData   = @("010004806400000070000000000000001400000002005000030000000000180003000f00010200000000000520000000200200000000180003000f00010200000000000520000000250200000000180003000f0001020000000000052000000027020000010100000000000512000000010100000000000512000000")
            ValueType   = "Binary"
        }

But looking at the log when it is applied, it seems to be converting the value into Decimal, resulting in an invalid entry:

'HKLM:\SYSTEM\CurrentControlSet\Services\lanmanserver\DefaultSecurity\SrvsvcSha
reAdminConnect' to '(1, 0, 4, 128, 100, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0, 0, 20,
0, 0, 0, 2, 0, 80, 0, 3, 0, 0, 0, 0, 0, 24, 0, 3, 0, 15, 0, 1, 2, 0, 0, 0, 0,
0, 5, 32, 0, 0, 0, 32, 2, 0, 0, 0, 0, 24, 0, 3, 0, 15, 0, 1, 2, 0, 0, 0, 0, 0,
5, 32, 0, 0, 0, 37, 2, 0, 0, 0, 0, 24, 0, 3, 0, 15, 0, 1, 2, 0, 0, 0, 0, 0, 5,
32, 0, 0, 0, 39, 2, 0, 0, 1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 5, 18, 0, 0, 0)' of type 'Binary'
VERBOSE: [SCDEV-RD-02]: LCM:  [ End    Set      ]

I’m sure there is a simple answer to this, but I can’t locate anything in the documentation.

Best Answer

The format of the DSC MSFT_Registry Binary type ValueData is a string with contiguous pairs of byte values, with an optional leading "0x"

The trick is this bit of code from the resource in $env:windir\Windows\System32\WindowsPowerShell\v1.0\Modules\PSDesiredStateConfiguration\DSCResources\MSFT_Registry.psm1.

It parses the value with:

    $binaryVal = $null
    $val = $Data[0].TrimStart("0x")
    if ($val.Length % 2 -ne 0)
    {
        $val = $val.PadLeft($val.Length+1, "0")
    }

    try
    {
        $byteArray = [Byte[]]@()

        for ($i = 0 ; $i -lt ($val.Length-1) ; $i = $i+2)
        {
            $byteArray += [Byte]::Parse($val.Substring($i, 2), "HexNumber")                                    
        }

        $ReturnValue.Value = [Byte[]]$byteArray
    }

Example

Using a slight variation on your input data:

$reg = "01,00,04,80,64,00,00,00,70,00,00,00,00,00,00,00,
  14,00,00,00,02,00,50,00,03,00,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,
  00,00,05,20,00,00,00,20,02,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,00,
  00,05,20,00,00,00,25,02,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,00,00,
  05,20,00,00,00,27,02,00,00,01,01,00,00,00,00,00,05,12,00,00,00,01,01,00,00,
  00,00,00,05,12,00,00,00"

You can create a properly formatted string with this:

$val = [String]::Join("",$reg.Split(",").Trim())

In the MOF, you'll see this:

 ValueData = {
    "010004806400000070000000000000001400000002005000030000000000180003000f00010200000000000520000000200200000000180003000f00010200000000000520000000250200000000180003000f0001020000000000052000000027020000010100000000000512000000010100000000000512000000"
};

Here's an entire test sample to prove the point:

   $reg = "01,00,04,80,64,00,00,00,70,00,00,00,00,00,00,00,
  14,00,00,00,02,00,50,00,03,00,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,
  00,00,05,20,00,00,00,20,02,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,00,
  00,05,20,00,00,00,25,02,00,00,00,00,18,00,03,00,0f,00,01,02,00,00,00,00,00,
  05,20,00,00,00,27,02,00,00,01,01,00,00,00,00,00,05,12,00,00,00,01,01,00,00,
  00,00,00,05,12,00,00,00"

$val = [String]::Join("",$reg.Split(",").Trim())

Configuration RegistryTest
{
    param([string] $Path, [string] $Name, [string] $BinaryValue)

    Import-DscResource -ModuleName PSDesiredStateConfiguration    
    Registry test
    {
        Key = $Path
        ValueName = $Name
        ValueData = $val
        ValueType = "Binary"
    }
}

$args = @{ 
    Path = "HKLM:\SOFTWARE\StackOverflow"
    Name = "BinaryTest"
}

Remove-ItemProperty @args
Get-ItemProperty @args -ErrorAction Continue # Nothing up my sleeve!
$o = RegistryTest @args -BinaryValue $val -outputpath $env:temp
Start-DscConfiguration ($o | split-path) -Wait -Verbose -force
Get-ItemProperty @args

That results in the following output:

Get-ItemProperty : Property BinaryTest does not exist at path 
HKEY_LOCAL_MACHINE\SOFTWARE\StackOverflow.
At C:\scratch\test.ps1:30 char:1
+ Get-ItemProperty @args -ErrorAction Continue # Nothing up my sleeve!
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (BinaryTest:String) [Get-ItemProperty], PSArgu 
   mentException
    + FullyQualifiedErrorId : System.Management.Automation.PSArgumentException,Microsoft.Powe 
   rShell.Commands.GetItemPropertyCommand

VERBOSE: Perform operation 'Invoke CimMethod' with following parameters, ''methodName' = SendCo
nfigurationApply,'className' = MSFT_DSCLocalConfigurationManager,'namespaceName' = root/Microso
ft/Windows/DesiredStateConfiguration'.
VERBOSE: An LCM method call arrived from computer STACKOVERFLOW with user sid S-...
VERBOSE: [STACKOVERFLOW]: LCM:  [ Start  Set      ]
VERBOSE: [STACKOVERFLOW]: LCM:  [ Start  Resource ]  [[Registry]test]
VERBOSE: [STACKOVERFLOW]: LCM:  [ Start  Test     ]  [[Registry]test]
VERBOSE: [STACKOVERFLOW]:                            [[Registry]test] Registry key value 'HKLM:\SOFTW
ARE\StackOverflow\BinaryTest' does not exist
VERBOSE: [STACKOVERFLOW]: LCM:  [ End    Test     ]  [[Registry]test]  in 0.2130 seconds.
VERBOSE: [STACKOVERFLOW]: LCM:  [ Start  Set      ]  [[Registry]test]
VERBOSE: [STACKOVERFLOW]:                            [[Registry]test] (SET) Set registry key value 'H
KLM:\SOFTWARE\StackOverflow\BinaryTest' to '(1, 0, 4, 128, 100, 0, 0, 0, 112, 0, 0, 0, 0, 0, 0,
 0, 20, 0, 0, 0, 2, 0, 80, 0, 3, 0, 0, 0, 0, 0, 24, 0, 3, 0, 15, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32,
 0, 0, 0, 32, 2, 0, 0, 0, 0, 24, 0, 3, 0, 15, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 37, 2, 0,
 0, 0, 0, 24, 0, 3, 0, 15, 0, 1, 2, 0, 0, 0, 0, 0, 5, 32, 0, 0, 0, 39, 2, 0, 0, 1, 1, 0, 0, 0, 
0, 0, 5, 18, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 5, 18, 0, 0, 0)' of type 'Binary'
VERBOSE: [STACKOVERFLOW]: LCM:  [ End    Set      ]  [[Registry]test]  in 0.1390 seconds.
VERBOSE: [STACKOVERFLOW]: LCM:  [ End    Resource ]  [[Registry]test]
VERBOSE: [STACKOVERFLOW]: LCM:  [ End    Set      ]
VERBOSE: [STACKOVERFLOW]: LCM:  [ End    Set      ]    in  0.7010 seconds.
VERBOSE: Operation 'Invoke CimMethod' complete.
VERBOSE: Time taken for configuration job to complete is 0.799 seconds


BinaryTest   : {1, 0, 4, 128...}
PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE\StackOverflow
PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_LOCAL_MACHINE\SOFTWARE
PSChildName  : StackOverflow
PSDrive      : HKLM
PSProvider   : Microsoft.PowerShell.Core\Registry

Looking at both a Server 2016 and a Windows 10 machine where I ran this, the registry looks correct.

Registry binary value of demo