Search code examples
powershellregistry

How to store text variable to file and retrieve it in PowerShell?


Following line reads registry value into variable

$renames = (Get-ItemProperty "HKLM:\System\CurrentControlSet\Control\Session Manager").PendingFileRenameOperations

If I use the variable directly to create new registry entry, it works well, new value is identical to previous one.

Set-ItemProperty "HKLM:\System\CurrentControlSet\Control\Session Manager" -name PendingFileRenameOperationsNew -value $renames -type MultiString

I need to store the variable to file and use it from other script. I tried to use this way

$renames | Out-File C:\temp\renames.txt
$renamesFromFile = Get-Content C:\temp\renames.txt -Raw
Set-ItemProperty "HKLM:\System\CurrentControlSet\Control\Session Manager" -name PendingFileRenameOperationsThroughFile -value $renamesFromFile -type MultiString

Unfortunately this leads into few extra bytes at the end of each line of the registry value. How to store and restore the registry value correctly?

(I need the code in PowerShell version 5.1 (default in Windows today))


Solution

  • Dereferencing a multi-string registry value with more than 1 value set will, perhaps unsurprisingly, give you multiple string values - so $renames likely contains an array of strings after the first operation.

    Out-File then writes each of these values to a separate line in the target file.

    Reading it back from disk with Get-Content -Raw causes PowerShell to treat the entire file as one big multi-line string....

    Unfortunately this leads into few extra bytes at the end of each line of the registry value.

    Those extra bytes are likely literal carriage returns (ASCII 0xA) as read from the (raw) underlying filestream.

    If you remove the -Raw switch parameter, Get-Content will instead read 1 line at a time, stripped of any trailing newlines - just like the original values in $renames:

    PS ~> $renamesFromFile = Get-Content C:\temp\renames.txt -Raw
    PS ~> $renamesFromFile.GetType()   # it's a single [string] value, not an array
    PS ~> $renamesFromFile = Get-Content C:\temp\renames.txt
    PS ~> $renamesFromFile.GetType()   # now it's an array type (eg. [object[]])