1

Related to Terminate part of powershell script and continue.
Partially related to Powershell Job Always Shows Complete.

My script runs locally and access the registry hive of a remote PC. I need the value of registry keys to be written into a $RegHive variable. And I want to monitor it as a job in case some PC freezes, I can terminate the command and move on to another PC.

My original code would be:

$global:RegHive = $null
$job = Start-Job -ScriptBlock {
    $RegHive = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("SomeKeyName", "SomePCName")
}

But no matter what I do, the variable $RegHive is empty.

If I do $RegHive = (Get-Job | Receive-Job) some value gets assigned to $RegHive that on one side looks exactly as if I would run it normally without a job/scriptblock, ie:

$RegHive = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("SomeKeyName", "SomePCName")

and even has the same $RegHive.SubKeyCount

But the "normal" one has $RegHive.GetSubKeyName() method and the one from job doesn't.

How do I escape assigning a variable with Receive-Job and do the assignment directly inside the scriptblock, which is run as a job?

In simple words:

$job = Start-Job -ScriptBlock {$a = 1 + 2}

How to get $a be equal to 3 without $a = (Get-job | Receive-job)?

Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328
  • 1
    Jobs executed in separate process. Live objects can not be passed thru process boundary. – user4003407 Apr 12 '18 at 08:26
  • @PetSerAl, so is it impossible then? No workaround? Like maybe passing pointers as parameters/global variables/calling functions that write into global variables(I tried the last 2, but couldn't make it work)? – snakePlantLeaf Apr 12 '18 at 11:58
  • Yes. Besides, I fail to see why you'd even want to pass back the hive object instead of finishing the work inside the job. – Ansgar Wiechers Apr 12 '18 at 19:45
  • @AnsgarWiechers The point is: i need the value of the key itself (call it `$RegHive`) to be used later. Otherwise I would have to add the entire script inside this job and deal with key value there. Idk if that makes sense... – snakePlantLeaf Apr 13 '18 at 09:09
  • The real question is, on such a quick operation as calling a registry value, why do you need to assign it a job at all? - nvm you stated you have issues with getsubkeyname() – Robert Cotterman Oct 06 '20 at 04:24
  • Why not just use the regular way, and use `select-object` to just remove getsubkeynames something like `select-object -ExcludeProperty GetSubKeyNames` – Robert Cotterman Oct 06 '20 at 04:32

1 Answers1

0

This might be helpful for you. The job is sort of like a variable What you can do is name the job and then call it by name with -Keep to maintain it's value stored - aka it will store all final output inside itself until you call it. (it can be kept but the default is to remove it once called)

$global:RegHive = $null
Start-Job -Name "RegHive" -ScriptBlock {
    [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("SomeKeyName", "SomePCName")
}
Receive-Job -Name "RegHive" -Keep

obviously calling the Receive-Job immediately after defeats the purpose of jobs, they add a lot of overhead, and are only efficient when needing to do multiple things at once. - if you call for 100s or thousands at once, you could do get-job | wait-job then when finished start using their outputs ---- wait-job also accepts job names or can wait on your entire list of jobs.

another option to set the variable is

$RegHive = "Receive-Job -Name "RegHive"

and finally, you can do this to use the value

get-<insert command> -value "$(Receive-Job -Name 'RegHive' -Keep)" -argument2 "YADA YADA"

remember keep will not delete the value and can be "Received" again later.

Robert Cotterman
  • 2,213
  • 2
  • 10
  • 19