windowspowershellregistryshare

Change drive in multiple shares inside windows registry


I need to change the drive of the shares inside the registry in the branch: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Shares

The word is a REG_MULTI_SZ, and I need to modify only the sub-word PATH. The code I have is:

$prueba="individu"
$error.clear()
$compartidos=$null
$compartidos=[system.collections.arraylist]@()
$rama="HKLM:\SYSTEM\CurrenteControlSet\Services\LanmanServer\Shares"
try{
    $compartidos+=get-itemproperty -path $rama -name $prueba
}
catch{
    $error|select-string equal
}
foreach($listado in $compartidos){
    $listado=$listado.$prueba -replace 'D:\\','O:\'
    $separado=$listado.$prueba
    $newWord=$separado|foreach{
        $_ -replace 'PATH=D:\\','PATH=O\'
    }
    $newReg=[Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SYSTEM\CurrentControlSet\Services\LanmanServer\Shares",$true)
    $newReg.SetValue($prueba,$newWord,[Microsoft.Win32.RegistryValueKind]::Multistring)
    $newReg.Close()
}

And the output I get is the following:

error message output

As you can see, when I expand the word I can change the drive from D: to O:, but when I try to modify the registry entry it fails.

The way I got to add the modification to the registry I got it from queries online an GPT. And in both case it suggest the same, and it doesn't word.

It's like I need to recreate the REG_MULTI_SZ word, but I don't know how and how to replace it in the registry word.

Can someone give me a hand pleaseee???


Solution

  • The answer was already provided in comments, to give it closure, the issue is that the RegistryKey.SetValue API is unable to convert the $newWord type to what is expected for a RegistryValueKind.MultiString:

    An array of null-terminated strings...

    To fix the issue, you can cast string[] to $newWord in order to convert it from object[]:

    $newReg.SetValue($prueba, [string[]] $newWord, [Microsoft.Win32.RegistryValueKind]::Multistring)
    

    As for why $newWord is an object[] to begin with, an assignment from a PowerShell expression that outputs 2 or more items will always be of this type, PowerShell won't try to infer the type of array it should use (there would be a performance penalty if it did) not counting the output from PowerShell expressions are dynamic, can be any type even mixed types. However, PowerShell offers several ways you can use so that the result is of the type you'd expect, for example by type constraining. See also about_Type_Conversion for more details as well as other conversion techniques.

    [string[]] $newWord = $separado | ForEach-Object {
        $_ -replace 'PATH=D:\\', 'PATH=O\'
    }