-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ijwhost.dll fails to load the .net8.0 runtime in Powershell 7.5 on Windows when using C++/Cli #112402
Comments
You need to enable roll forward for the component/plugin. For C# projects we have an MSBuild property, I don't know if this works for C++/CLI projects though. In any case you can modify the You need to set it to |
Thank you very much @vitek-karas ! Yes, C++/Cli has this msbuild property:
If I add this property to the CPPClrAndNative.vcxproj the value Now the attached Powershell Commandlet is working in Powershell 7.5! So we have the following project "tree": PowershellCmdlet(C#) --referencing/calling--> CPPClr(C++/Cli) --referencing/calling--> CPPClrAndNative(C++/Cli)
It is a little bit strange for me that only the project CPPClrAndNative needs this setting. Does that mean, that PowershellCmdlet and CPPClr are using the .net8.0 runtime assemblies but CPPClrAndNative is using the .net9.0 runtime assemblies? |
When you have managed code calling another managed code, the problem doesn't exist - since in such cases the dependency is loaded by the CLR runtime running that managed code caller - so it knows that it needs to load it into itself. This is how any managed library works. Even if the dependency is C++/CLI, if it's called into through managed code, it behaves like a managed assembly (for the runtime). The difference is between CPPClr -> CPPClrAndNative - that call is native, so the CLR runtime is not aware of it in any way. The dependency (CPPClrAndNative) is loaded via normal OS dependency loading mechanism (LoadLibrary) - and when it starts it says "wait, I have managed code, I need to start CLR runtime" - this step is the same even if it was loaded into a completely native process without any CLR runtime in it. This is the step which has the version requirement - in order to load CLR it needs to know which version to load. In this case, there already is runtime in the process, so the version requirements are compared and if they don't match it fails.
No - everything running on the same CLR runtime - the hosting API prevent you from loading two runtimes into the same process (which would be rather problematic) - so in this case, everything (including Powershell itself) is running on .NET 9. |
Tagging subscribers to this area: @vitek-karas, @agocke, @VSadov |
Thank you very much @vitek-karas ! I have learned a lot here! For now we will go this way:
It is really not an ideal situation for us but it is no longer a show stopper. I will close this issue next week if nobody holds me back... Thanks again! |
Description
Powershell 7.5 (uses .net9.0 runtime) is unable to run a Commandlet in some cases if the CommandLet is implemented using C#, C++ and C++/Cli using .net8.0. If I execute the same commandlet with Powershell 7.4 - which uses .net8.0 runtime - all is fine.
Reproduction Steps
I have attached a Visual Studio Solution for reproducing the issue
Projects in the attached Visual Studio Solution
PowershellCmdlet.dll:
CPPClr.dll:
CPPClrAndNative.dll:
Expected behavior
The attached Add-TestCmdlet writes some output to the console and is executing without an exception.
Actual behavior
The attached Add-TestCmdlet writes some output to the console but before it finish there is an exception:
Add-TestCmdlet: External component has thrown an exception.
Regression?
We are currently porting a big Visual Studio Solution with about 300 C#, C++ and C++/Cli projects from .net Framework 4.8 to .net8.0. This solution also implements Powershell Commandlets using our code base. Using .net Framework 4.8 the Powershell Commandlets are working as expected. Currently this issue is a real showstopper for the migration to .net8.0.
Known Workarounds
No known workaround unless you use PowerShell 7.4. But this is not an option. We cannot force our customers not to update to PowerShell 7.5 or deinstall Powershell 7.5 and install Powershell 7.4.
Configuration
.NET version:
Other information
I opened an issue in Powershell/Powershell before (PowerShell/PowerShell#24979). But they advised me to open an issue here. I am thinking they are right because it is not an issue regarding Powershell but an issue regarding .net runtime and C++/Cli.
If you attach Visual Studio as debugger to the pwsh.exe and execute the Add-TestCmdlet-Commandlet you will see the following error:
The specified runtimeconfig.json [C:\Users\wg\source\repos\Powershell\PowershellCmdlet\bin\Debug\net8.0-windows7.0\CPPClrAndNative.runtimeconfig.json] does not exist
I think this is another issue regarding .net core and C++/cli. The CPPClrAndNative.runtimeconfig.json is not copied to the output folder of the referencing project.. As a workaround I added already CPPClrAndNative.runtimeconfig.json to PowershellCmdlet and set the property "Copy to Output Directory" to "Copy if newer".
Now to the actual problem:
If you execute Add-TestCmdlet-Commandlet in Powershell again the following Exception occurs:
The specified framework 'Microsoft.NETCore.App', version '8.0.11', apply_patches=1, version_compatibility_range=minor is incompatible with the previously loaded version '9.0.1'.
Where does this Exception occur?
In load_fxr_and_get_delegate in fxr_resolver.h:
![Image](https://private-user-images.githubusercontent.com/100278695/411896467-51313ed6-960b-4aa5-bfdb-dce2a630d860.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3Mzk1Mjk4MTYsIm5iZiI6MTczOTUyOTUxNiwicGF0aCI6Ii8xMDAyNzg2OTUvNDExODk2NDY3LTUxMzEzZWQ2LTk2MGItNGFhNS1iZmRiLWRjZTJhNjMwZDg2MC5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwMjE0JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDIxNFQxMDM4MzZaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT0xMTMyZWMyNWE1MjBkNzJhMTc3ZWVlYjlkYTBmNDFlMDA2NTg2NTg2YjA5NWFkYjc1MGJkMmJlNzYzYjQwZTZmJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.49ZuVgFaTHWks0_UU8g3Cw2MuIXIOQ0q1hQ30TtZEpI)
As you can see the rc has the value -2147450715. According to https://github.com/dotnet/runtime/blob/main/docs/design/features/host-error-codes.md it means the following:
"Host configuration is incompatible with existing host context - returned by hostfxr_initialize_for_runtime_config. The component being initialized requires framework which is not available or incompatible with the frameworks loaded by the runtime already in the process. For example trying to load a component which requires 3.0 into a process which is already running a 2.0 runtime."
Some more informations
The text was updated successfully, but these errors were encountered: