1

I have a main script that imports a module \path\to\functions.psm1, I call a function in the main script named: Run_Scans $ServerList, which is from functions.psm1, From Run_Scans I try and call two other functions (Scan1,Scan2) using Start-Job, but cannot get the servers variable to pass to the other functions. I've tried several different ways with either the job fails or completes but the server list does pass through. Any help would greatly be appreciated.

#This is from the main script#
Import-Module "path\to\Functions.psm1"
Run_Scans $ServerList

#This is from functions.psm1#
Function Run_Scans ($Servers){
#Start-Job -Name 'Scan1' -ScriptBlock {Run_Scan1 $using:Servers}
#Start-Job -Name 'Scan2' -ScriptBlock {Run_Scan2 $using:Servers}

$Scan = {
    param ($Servers)
    Run_Scan1 $Servers
    Run_Scan2 $Servers
}
Start-Job -ScriptBlock $Scan -ArgumentList $Servers
}

Function Run_Scan1 ($Servers){
    scan code
}
Function Run_Scan2 ($Servers){
    scan code
}

UPDATE:

I was able to do the following:

$ServerList = "Serv1","Serv2","Serv3"
Start-Job -InitializationScript $Initialization -ScriptBlock {param($servers) echo $servers} -args (,$servers)

Receive-Job 

Output:

Serv1

Serv2

Serv3

But when I try to incorporate calling the function:

$Initialization = [scriptblock]::Create("Import-Module -Name 'Pathto\Functions.psm1'")
Start-Job -InitializationScript $Initialization -ScriptBlock {param($servers) Run_Scan1 $servers} -args (,$servers)

I get the following errors:

The term 'Run_Scan1' is not recognized as the name of a cmdlet, function, script file, or operable program.

Cannot index into a null array.

FINAL Solution:

Start-Job -InitializationScript {Import-Module "Pathto\Functions.ps1"}  -ScriptBlock { param($Servers) Run_Scan1 $Servers } -ArgumentList (,$servers)
Chris
  • 17
  • 5
  • The background job runs in a session in an independent PowerShell _child process_ that knows nothing about the state of the caller, so the `Run_Scan1` and `Run_Scan2` functions won't be available there. Aside from that, if `$Servers` is an array, you'd have to pass it as `-ArgumentList (, $Servers)` as shown in js2010's answer. – mklement0 Apr 14 '20 at 22:40
  • If you Import-Module with -InitializationScript wouldn't that make the function available? – Chris Apr 15 '20 at 13:55
  • 1
    Yes, that should work; note that in PS 6- the background job runs in `$HOME\Documents`, not in the caller's current directory, so be sure to account for that in `Pathto\Functions.psm1` - see [this answer](https://stackoverflow.com/a/41054532/45375). – mklement0 Apr 15 '20 at 14:39
  • 1
    Thanks for the help – Chris Apr 15 '20 at 19:49

1 Answers1

0

For arrays, I recommend the using scope. Jobs don't handle array parameters well. Use start-threadjob if you have it.

$servers = echo server1 server2

start-job { param($servers) $servers } -args $servers | receive-job -wait -auto

server1


start-job { $using:servers } | receive-job -wait -auto          

server1
server2

Or there's this ridiculous (, ) workaround:

start-job { param($servers) $servers } -args (,$servers) | receive-job -wait -auto

server1
server2
js2010
  • 23,033
  • 6
  • 64
  • 66
  • 1
    Good catch (though the OP's bigger problem is the unavailability of the functions in the background job). Note, however, that the behavior - though surprising and requiring an obscure workaround - is by design, and applies to all cmdlets that accept pass-through arguments via an array-valued `-ArgumentList` parameter - see [this answer](https://stackoverflow.com/a/49307779/45375). – mklement0 Apr 15 '20 at 14:48
  • Perhaps you can add the other part of the solution to your answer as well, namely the need to import the module with the functions to call in the job; Chris has edited this into his question, but it's better to have it as part of the answer: `Start-Job -InitializationScript {Import-Module "Pathto\Functions.ps1"} -ScriptBlock { param($Servers) Run_Scan1 $Servers } -ArgumentList (,$servers)` – mklement0 Apr 15 '20 at 21:41