1

I have a script that grabs a series of information from SQL. It then parses the information and passes it to a series of arrays. I want to then pass each array to a separate script.

I've seen Start-job should be able to do this but form my testing it didn't seem to work. This is what I have tried. Each Script individually works, and I am currently just using CVS's to pass the information.

Once the information is in the script I need to be able to call specific properties from each object. I did get it to just print the array as a string, but I couldn't call anything specific.

Invoke-Sqlcmd -Query $Q1 -ServerInstance $I -Database $DB | Export-Csv "$Files\Employees.csv"

$emps = Import-Csv "$Files\Employees.csv"
$newaccounts = @()
$deacaccounts = @()
$changedusers = @()
if(Test-Path -Path "$Files\Employees.csv"){
    foreach ($emp in $emps) {
        if ($emp.emp_num.trim() -ne $emp.EmpNum) {
           $newaccounts += $emp 
        }
        if ($emp.emp_num.trim() -eq $emp.EmpNum) {
            if ($emp.fname -ne $emp.GivenName -and $emp.lname -ne $emp.SurName) {
                $deacaccounts += $emp
                $newaccounts += $emp
            }
            else ($emp.dept -ne $emp.DepartmentNumber -or $emp.job_title -ne $emp.JobTitle) {
                $changedusers += $emp
            }
        }
    }
}

Start-job -path "script" -argumentlist (,$deacaccounts)
Start-job -path "script" -argumentlist (,$changedusers)
Start-job -path "script" -argumentlist (,$newaccounts )

EDIT: The Information passed to the scripts would be multiple lines of employee data. I need to be able to grab that info in the "Sub" scripts and perform actions based on them.

EX: Deacaccounts =

fname Lname empnum
ted kaz 1234
sam cart 245
AndeCase
  • 11
  • 2
  • 1
    It being a background job doesn't matter to me. The "parent" script will be running automatically, so it will all be in the background. I just need to be able to pass the information. if a different command will work better then that is fine. – AndeCase Aug 20 '21 at 19:22

1 Answers1

0

If you really need background jobs - it turns out that you don't - note that Start-Job doesn't have a -Path parameter; you'd have use -ScriptBlock { & "$script" } instead.

To simply invoke the script in the foreground, in sequence, use the following (script representing your .ps1 file path(s)):

& "script" $deacaccounts
& "script" $changedusers
& "script" $newaccounts

Note: &, the call operator, is only needed if the script / executable path is quoted and/or contains variable references (or subexpresions); e.g., a script with path c:\foo\bar.ps1 may be invoked without &; e.g.
c:\foo\bar.ps1 $deacaccounts

Note that your script(s) will receive a single argument each, containing an array of values.

If instead, you wanted to pass the array elements as individual (positional) arguments, you'd have to use splatting, where you use sigil @ instead of $ to pass your variable (e.g.,
& "script" @deaccounts).

If you need to enumerate the arrays and pass each object individually as a parameter, use the following:

foreach ($obj in $deaccounts)   { & "script" $obj }
foreach ($obj in $changedusers) { & "script" $obj }
foreach ($obj in $newaccounts)  { & "script" $obj }

If each object should be splatted positionally based on its property values:

foreach ($obj in $deaccounts) { 
  $vals = $obj.psobject.Properties.Value
  & "script" @vals 
}
# ... ditto for $changeduser and $newaccounts

If each object should be splatted by property names, based on both property names and values, you need to convert each object to a hashtable first:

foreach ($obj in $deaccounts) { 
  $params = @{}
  foreach ($prop in $obj.psobject.Properties) {
    $params[$prop.Name] = $prop.Value
  } 
  & "script" @params
}
# ... ditto for $changeduser and $newaccounts

As an aside: Incrementally extending arrays in a loop with += is inefficient, because a new array must be created behind the scenes in every iteration, because arrays are of fixed size.

In general, a much more efficient approach is to use a foreach loop as an expression and let PowerShell itself collect the outputs in an array: [array] $outputs = foreach (...) { ... } - see this answer.

In case you need to create arrays manually, e.g to create multiple ones, such as in your case, use an efficiently extensible list type, such as [System.Collections.Generic.List[object]] - see this answer.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Either I'm struggling to fully understand the concepts put forth, or there is a misunderstanding cause it doesn't seem to be working how I think it does. The goal of these script is account creation, update, and deactivation. So each of them will get a line of data with multiple values (first name, lastname, title, number, etc) and potentially multiple lines. I would like to be able to gather all of the information for each and then run the script that does what is needed, Without running the script multiple times, or creating a CSV every time. I have edited some more info into main question. – AndeCase Aug 25 '21 at 20:26
  • @AndeCase, I'm afraid neither your comment nor your edit make your intent clearer to me. Perhaps if you show the parameter declaration of your script and a sample invocation with literal data it will become clearer. In the meantime, this answer provides some general pointers regarding parameter passing and splatting. – mklement0 Aug 25 '21 at 21:03
  • @AndeCase, I've added more information on splatting; perhaps that helps. – mklement0 Aug 25 '21 at 21:22