0

I can't pass $dir variable to scripts in the background "Script2" and "Script3".

What an I doing wrong?

All code is pretty simple, I'm just testing how to run background processes and get results from them.

Script1

# Ask the user for the directory to check
$dir = Read-Host "Enter the directory path to check for files"

# Start the second script in the background
Start-Job -ScriptBlock { & "C:\Scripts\Script2.ps1" -dir $dir } -Arg $dir

# Start the third script in the background
Start-Job -ScriptBlock { & "C:\Scripts\Script3.ps1" -dir $dir } -Arg $dir

# Wait for the second and third scripts to complete
Wait-Job -State Completed

# Get the results of the second and third scripts
$result1 = Receive-Job -Id 1
$result2 = Receive-Job -Id 2

# Output the results
Write-Output "Script 2 completed with result: $result1"
Write-Output "Script 3 completed with result: $result2"

Here I trying to get $dir variable from Script1

Script2

param(
   [string]$dir
)

# Check if the directory exists
if (Test-Path $dir) {
   # Get all files in the directory
   $files = Get-ChildItem $dir

   # Check if the directory is empty
   if ($files.Count -eq 0) {
      Write-Output "The directory is empty"
   } else {
      # Calculate the total size of the files in the directory
      $size = ($files | Measure-Object -Property Length -Sum).Sum
      Write-Output "The total size of the files in the directory is $size bytes"
   }
} else {
   Write-Output "The directory does not exist"
}

Script3

param(
   [string]$dir
)

# Check if the directory exists
if (Test-Path $dir) {
   # Get all files in the directory
   $files = Get-ChildItem $dir

   # Check if the directory is empty
   if ($files.Count -eq 0) {
      Write-Output "The directory is empty"
   } else {
      Write-Output "The filenames in the directory are:"
      # List the filenames in the directory
      $files | ForEach-Object { Write-Output $_.Name }
   }
} else {
   Write-Output "The directory does not exist"
}

I get the following error:

Cannot bind argument to parameter 'Path' because it is an empty string.
    + CategoryInfo          : InvalidData: (:) [Test-Path], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.Test
   PathCommand
    + PSComputerName        : localhost
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
Boom
  • 27
  • 6
  • In short: Because the script block executes _in a different runspace_ (in a child process, in the case of `Start-Job`), it knows nothing about the caller's _local_ variables. The simplest way to reference the caller's variable values is with the `$using:` scope; alternatively, pass values via `-ArgumentList`. See the linked duplicate for details. – mklement0 Jan 02 '23 at 14:16
  • I changed from "Start-Job -ScriptBlock { & "C:\Scripts\Script2.ps1" -dir $dir } | Out-Null" to "Start-Job -ScriptBlock { & "C:\Scripts\Script2.ps1" -dir $dir } -Arg $dir" and still getting error "Cannot bind argument to parameter 'Path' because it is an empty string." – Boom Jan 02 '23 at 15:32
  • 1
    EITHER use `$using:dir` _alone_ in the script block OR `-Args $dir` _combined with referring to it as `$args[0]` in the script block_, using the [automatic `$args` variable](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Automatic_Variables#args). – mklement0 Jan 02 '23 at 16:09

0 Answers0