jamesdeluk
jamesdeluk

Reputation: 324

REG EXPORT single value to .reg file

I want to export a single registry value to a file using PowerShell (eventually scripting to backup a bunch of registry values).

I can view the file with QUERY:

REG QUERY "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa" /v LimitBlankPasswordUse
>>
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa
    LimitBlankPasswordUse    REG_DWORD    0x1

However, I can't export the single value.

REQ EXPORT has no /v flag, so:

REG EXPORT "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa" \v "LimitBlankPasswordUse" LBPU.reg
ERROR: Invalid syntax.

Doesn't work.

If I try to export the value I get:

REG EXPORT "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\LimitBlankPasswordUse" LBPU.reg
ERROR: The system was unable to find the specified registry key or value.

And if I simply do the folder:

REG EXPORT "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\" Lsa.reg
The operation completed successfully.

I get a .reg file which includes the correct value:key pair "LimitBlankPasswordUse"=dword:00000001 - but also all the others. Which is no use. I want one pair, not hundreds.

How do I export a single value to a .reg file?

Upvotes: 3

Views: 13847

Answers (2)

mklement0
mklement0

Reputation: 437090

There is no direct way of achieving what you want, and given that you want a .reg file as output, using PowerShell's cmdlets (such as Get-Item, Get-ItemProperty, and Get-ItemPropertyValue) is not an option - unless you're prepared to emulate the .reg file format in all aspects, which is nontrivial both in terms of effort and complexity.[1]

The best approach in your case is to first export the whole key, with reg.exe export, to a temporary file, and then extract and export only the header lines and the data-value pair of interest.

Given that a single data-value pair can span multiple lines, this isn't straightforward, but the following should work robustly (you could wrap it in a function for convenience and reuse):

# Determine the key path and the name of the value to export...
$keyPath = 'HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa'
$valueName = 'LimitBlankPasswordUse'
# ... and the output file path.
$outFile = 'LBPU.reg'

# Create a temporary file and export the whole key to it.
$tempFile = New-TemporaryFile
$null = reg.exe export $keyPath $tempFile /y

# Extract the header lines and the key's *immediate* value children.
# Note: reg.exe export invariably exports *recursively*, so that any 
#       descendant keys are exported as well, which we want to exclude.
$null = (Get-Content -Raw $tempFile) -match '(?s)^(.+?\])\r\n(.+?)\r\n(?:\r\n|\z)'
Remove-Item $tempFile

# Extract the header lines (format identifier and key path)...
$headerLinesBlock = $Matches[1]
# ... and the key's immediate children as value-data pairs
$valueLinesBlock = $Matches[2]

# Extract the specific value-data pair of interest.
# Note: Such a pair can span *multiple* lines, if "\" is used as the
#       line-continuation character at the end of a line, as is common
#       with hex. data.
#       Continuation lines always start with a *space*, so a data-value pair
#       ends either with a new line whose first char. is a non-whitespace char. 
#       or with the end of the input string.
if ($valueLinesBlock -notmatch "(?sm)^`"$valueName`"=.+?(?=(\r\n\S|\z))") {
  throw "Value name not found: $valueName"
}
$valueDataPair = $Matches[0]

# Save the header lines and the data-value pair line(s) to the result file.
# Note that .reg files are "Unicode" (UTF-16LE) files.
$headerLinesBlock, $valueDataPair | Set-Content -Encoding Unicode $outFile

$outFile receives the following content:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa]
"LimitBlankPasswordUse"=dword:00000001

[1] To name a few challenges: REG_DWORD and REG_QWORD values must be represented as hex values, REG_EXPAND_SZ values, when queried with Get-ItemProperty are invariably expanded, so you wouldn't preserve the actual value as stored in the registry; furthermore, REG_EXPAND_SZ and REG_MULTI_SZ values must be represented as types hex(2) and hex(7) in the form of hex byte arrays, respectively.

Upvotes: 4

Mark Elvers
Mark Elvers

Reputation: 647

You haven't used PowerShell at all here. As zett42 said, this is a Get-ItemProperty problem. If you must have a .reg file as the output then you could easily create one providing you have simple case such as this where the output is a single dword. The approach will struggle if you have numerous items and more complex datatypes.

$lsa = Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Lsa" -Name LimitBlankPasswordUse
$path = $lsa.PSPath.Split('::')
Set-Content foo.reg "Windows Registry Editor Version 5.00`r`n`r`n[$($path[2])]`r`n`"LimitBlankPasswordUse`"=dword:$($lsa.LimitBlankPasswordUse)"

You can hard code or script as much as you need depending upon your overall objective. Probably export to CSV and then apply then at the target with Set-ItemProperty.

Upvotes: 3

Related Questions