1st ps1:
#$dll = 'C:\Some\Path\To\dll'
$dll = $PSScriptRoot+'\dll'
Write-Host $dll -foreground Green
$code = @"
Some code that works
"@
Add-Type -TypeDefinition $code -Language CSharp -ReferencedAssemblies $dll
[System.Reflection.Assembly]::LoadFrom($dll)
[HelloWorld.Program]::Main()
2nd ps1:
$job = Start-Job -FilePath "Myps1.ps1" -Name "aaa"
$dll = $PSScriptRoot+'\Mydll.dll'
Write-Host $dll -foreground Yellow
Start-Sleep 5
$JobStatus = $job.State
Write-Host $job.State -foreground Yellow
if ($JobStatus -like "Running")
{
Write-Host "Gresit" -foreground Red
}
else
{
Write-Host "Corect" -foreground Green
}
I am calling the first ps1 from the 2nd ps1. The problem arises because when calling the first ps1 from the 2nd, if I use
$dll = 'C:\Some\Path\To\dll'
then the program works. But if I use
$dll = $PSScriptRoot+'\dll'
then the program does nothing.
Needless to say that if I call the first ps1 it works with both versions of dll path.
So this is your problem...
$job = Start-Job -FilePath "Myps1.ps1" -Name "aaa"
If you look at the documentation for the -FilePath
parameter of Start-Job
it says:
When you use this parameter, PowerShell converts the contents of the specified script file to a script block and runs the script block as a background job.
So your code is sort-of equivalent to:
$src = Get-Content "Myps1.ps1"
$sb = [scriptblock]::Create($src)
$job = Start-Job -ScriptBlock $sb -Name "aaa"
And if we run a near-identical cut-n-pasteable example:
$src = @"
write-host "root = '$PSScriptRoot'"
"@
$sb = [scriptblock]::Create($src)
$job = Start-Job -ScriptBlock $sb -Name "aaa"
Wait-Job $job
Receive-Job $job
We see the following output:
root = ''
That is because $PSScriptRoot
is not defined when running inside a ScriptBlock
, only when running as a script:
Contains the full path of the executing script's parent directory.
In PowerShell 2.0, this variable is valid only in script modules (.psm1). Beginning in PowerShell 3.0, it's valid in all scripts.
A ScriptBlock
is an in-memory object, so it doesn't have a "parent directory", and creating a ScriptBlock from the contents of a file doesn't persist the file path into the ScriptBlock, so $PSScriptRoot
is undefined in both cases.
This answer gives some more details:
https://stackoverflow.com/a/72026978/3156906
And a suggested workaround there is to make the call to Start-Job a simple wrapper around the Call operator to invoke your script, because then your script executes as a script (not a scriptblock) and has access to the $PSScriptBlock
automatic variable:
$sb = { & ".\first.ps1" }
$job = Start-Job -ScriptBlock $sb -Name "aaa"
$result = Wait-Job $job
Receive-Job $job
So the script file runs as a script, not a scriptblock, and it has a $PSScriptRoot
automatic variable available as a result, which results in this output:
C:\src\so\root\dll