I have an app that is using the PowerShell SDK to execute PowerShell code in the background.
However, that code depends on Start-Job
, and the PowerShell script is throwing an exception when I run it in my app:
_powerShellInstance.AddScript("DoSomethingWithStartJob").Invoke();
The pwsh executable cannot be found at "C:\Users\ben\Projects\Foo\Foo (Package)\bin\x64\Debug\AppX\Foo\runtimes\win\lib\net8.0\pwsh.exe". Note that 'Start-Job' is not supported by design in scenarios where PowerShell is being hosted in other applications. Instead, usage of the 'ThreadJob' module is recommended in such scenarios.
I want to port to use Start-ThreadJob
like the error says, but I don't know how! How can I get my C# app to install the ThreadJob module into my PowerShell SDK installation?
This should work for any PS module available in PSGallery. To support ThreadJob
specifically:
ThreadJob
's PSGallery nuget package to our feedThreadJob
module contents to our output dir.In your nuget.config
(example nuget.config):
<packageSources>
<clear />
<!-- ... -->
<add key="PSGallery" value="https://www.powershellgallery.com/api/v2/" />
</packageSources>
In your csproj
(example csproj; in our case, we were deploying a WinUI project so we edited the package wapproj
instead):
<ItemGroup>
<!-- ... -->
<PackageReference Include="ThreadJob" Version="2.0.3">
<!-- Necessary for the next step: -->
<GeneratePathProperty>True</GeneratePathProperty>
</PackageReference>
</ItemGroup>
This adds the pacakge to your project.
In our case, we had a custom NuGet feed in ADO, so we just added ThreadJob
to its cache.
In the same csproj
/wapproj
that references the ThreadJob
package:
<Target Name="CopyThreadJob" AfterTargets="AfterBuild">
<Message Text="ThreadJob module files: @(ThreadJobFiles)" Importance="high"></Message>
<Message Text="Deploying ThreadJob module to: $(OutDir)AppX\Foo\runtimes\win\lib\net8.0\Modules\Microsoft.PowerShell.ThreadJob\" Importance="high"></Message>
<!-- If you want other targets, like UNIX, you'll need to copy to those Modules\ directories, too -->
<!-- Remember, the subdir in Modules needs to exactly match the name of the .psd1 -->
<Copy SourceFiles="@(ThreadJobFiles)" DestinationFolder="$(OutDir)\AppX\Foo\runtimes\win\lib\net8.0\Modules\Microsoft.PowerShell.ThreadJob\" SkipUnchangedFiles="true" />
</Target>
Now your code can invoke Start-ThredJob
!
_powerShellInstance.AddScript("Start-ThreadJob").Invoke();