1

I just started working with powershell about 3 days ago and i've been trying to make a script that accesses the registry of a remote computer and looks for a certain key and puts the output into the file.

I have been able to get it to work but i noticed that if it fails to reach the registry it would take about 15 seconds to error out and continue with the script so i put this in:

$Server = "test.contesto.net"

$Job = Start-Job ScriptBlock{[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine",$Server)

Start-Sleep 2

If ($Job.State -EQ "Completed"){
write-host "made it"
}
Else {
write-host "failed"
}

and i will always get "made it". even when i know i can't reach that servers registry. The odd thing is, if i type all that in manually into a powershell prompt like this:

$Job = Start-Job ScriptBlock {[Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine","test.contesto.net") 

Then look at the state of that job

$Job.State

I get "Running" for the full 15 seconds that it takes to fail. i tried to add the Get-Variable in the ScriptBlock {} but that didn't work either. It still shows completed. So i'm thinking that it has to do with the job erroring out due to syntax or something so the job completes every time no matter what

alroc
  • 27,574
  • 6
  • 51
  • 97
Ivory
  • 35
  • 4
  • This doesn't need to be done as a job, at least the part that you're describing. So why add that layer of complexity? – alroc Jan 10 '15 at 13:57
  • The reason i wanted to add this layer of complexity is because i don't want to wait the default 15 seconds that it takes for the: [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine","test.contesto.net") command to finish. instead, i want to only wait less than a second or 1 second. i'm not sure of any other way to do this. I would love to get some other ideas if you have any on how to accomplish this. I'm going to be running this on a number of machines and i don't need 15 seconds to know that it's going to fail. – Ivory Jan 11 '15 at 21:09

1 Answers1

1

The issue is that you need to pass $server as an argument to your script block, then reference it via the automatic variable called $args:

$server = "test.contesto.net"
$Job = Start-Job -ScriptBlock {
    $server = $args[0]
    [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine",$server) 
} -ArgumentList @($server)

Background jobs run in a completely separate context from your current script, therefore the variables defined locally will not be seen.

So in your case, the job failed immediately because $server was equal to $null. By passing $server appropriately the job will try to retrieve the remote key, then time out.

Micky Balladelli
  • 9,781
  • 2
  • 33
  • 31
  • 1
    I think you can also use `$using:server` to resolve local variables used in script blocks like this. I can't say that works in Jobs, but I know it works in Invoke-command, workflows, and in DSC script resources. But you can avoid the -argument list this way and the code looks cleaner. – kevmar Jan 10 '15 at 18:32
  • Thanks! that is exactly what it was. I feel so stupid, such a simple answer. i figured it would be some syntax thing i was doing wrong. the "$using:server" is a great touch! i'll definitely use it. – Ivory Jan 11 '15 at 21:15
  • @kevmar I wanted to use $using:_variable_ with a scriptblock like `{& $using.mydir\echo.bat "a b c"}` but as soon as $job.State = Running is over Receive-Job fails with **"ObjectNotFound: The term '.mydir\echo.bat' is not recognized as a name of a ..."** -> It strongly seems that it wants to rebuild my command and if the job has completed the needed variables are not there. This happens also to $PSScriptRoot, not only $using.xyz. When I switched to `-ArgumentList` variant it worked. So in other words powershell forces you to use the not-so-readable way if you want to use all possibilities. – jifb Mar 23 '23 at 13:35
  • I mean $using:mydir, not $using.mydir -- anyway -ArgumentList does work better than $using – jifb Mar 23 '23 at 14:43