I need to run these 4 commands to boot a new image into a device:
bcdedit /copy {current} /d "Describe"
bcdedit /set {guid} osdevice vhd=somepath
bcdedit /set {guid} device vhd=somepath
bcdedit /default {$guid}
To automate my script, I want to extract the guid/identifier returned as output from the first command and pass it as a parameter to the other 3 commands. Right now, I'm doing it in this way:
$guid = Invoke-Command -ComputerName $comp -Credential $cred -ScriptBlock {cmd /c "bcdedit /copy {current} /d "Describe""}
#output
#$guid = This entry was successfully copied to {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}
$guid = $guid.Replace("This entry was successfully copied to {","")
$guid = $guid.Replace("}","")
$path1 = "xxx/xxxx/...."
#passing the guid and path as inputs
Invoke-Command -ComputerName $comp -Credential $cred -ScriptBlock {cmd /c "bcdedit /set {$guid} osdevice vhd=$path1"}
Invoke-Command -ComputerName $comp -Credential $cred -ScriptBlock {cmd /c "bcdedit /set {$guid} device vhd=$path1"}
Invoke-Command -ComputerName $comp -Credential $cred -ScriptBlock {cmd /c "bcdedit /default {$guid} "}
But, each time I get an error:
The element data type is not recognized, or does not apply to the specified entry. Run "bcdedit /?" for command line assistance. Element not found
This works fine when I manually copy and paste the path in the UI, but I'm not sure how I can automate it.
As explained in this answer to your prior question, there is no need to use cmd /c
in order to invoke bcdedit
- all that is needed is to quote literal arguments that contain {
and }
, because these characters, when used unquoted, have special meaning in PowerShell.
cmd /c
is not only inefficient (though in practice that will hardly matter), but can also introduce quoting headaches.[1]A script block passed to Invoke-Command -ComputerName ...
executes remotely and therefore has no access to the caller's variables; the simplest way to include variable values from the caller's scope is via the $using:
scope (see this answer).
Therefore:
$guid = Invoke-Command -ComputerName $comp -Credential $cred -ScriptBlock {
bcdedit /copy '{current}' /d "Describe"
}
# Extract the GUID from the success message, which has the form
# "This entry was successfully copied to {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}"
$guid = '{' + ($guid -split '[{}]')[1] + '}'
$path1 = "xxx/xxxx/...."
# Passing the guid and path as inputs, which must
# be done via the $using: scope.
Invoke-Command -ComputerName $comp -Credential $cred -ScriptBlock {
bcdedit /set $using:guid osdevice vhd=$using:path1
bcdedit /set $using:guid vhd=$using:path1
bcdedit /default $using:guid
}
[1] For instance, cmd /c "bcdedit /copy {current} /d "Describe""
doesn't work the way you think it does; it would have to be cmd /c "bcdedit /copy {current} /d `"Describe`""