agracio / edge-js

Run .NET and Node.js code in-process on Windows, macOS, and Linux

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Using another option in the dotnet.runtimeconfig.json for the framework won't find coreclr.dll

ArnoKrohne opened this issue · comments

Try this dotnet.runtimeconfig.json :
{ "runtimeOptions": { "tfm": "net8.0", "framework": { "name": "Microsoft.AspNetCore.App", "version": "8.0.2" }, "configProperties": { "System.Reflection.Metadata.MetadataUpdater.IsSupported": false, "System.Runtime.Serialization.EnableUnsafeBinaryFormatterSerialization": false } } }

The initialization will fail with the message that coreclr.dll is not found.

I was not able to replicate this error using https://github.com/agracio/edge-js-quick-start. Try creating a GitHub repo that reproduces this problem.
Since you opened 2 issues on the same topic will close #211.

Just to clarify both this and #211 issues, if you want to override default config for dotnet.runtimeconfig.json follow the steps in this article .NET Runtime configuration settings.
You can either add runtime config overrides during compile or add it to an already compiled .NET Core dll.

The problem is related to setting the framework in the dotnet.runtimeconfig.json to Microsoft.AspNetCore.App instead of Microsoft.NETCore.App.

About #211:
.NET Runtime configuration settings doesn't give me any clues about how to set this in another way. Anyway, I browsed through the cpp code of edge-js, and the dotnet.runtimeconfig.json is the only way you can set this option. Adding a framework include in my .csproj wont work in this case because the needed assemblies must be preloaded by edge-js

I am using node 16.20.1 BTW.
I forked the edge-js-quick-start build it, and got this error without any modifications when the framework is set to Microsoft. AspNetCore.App:

D:\RD\edge-js-quick-start>npm start

> edge-js-quick-start@1.0.0 start
> node main.js core

CoreClrEmbedding::Initialize - Could not resolve CoreCLR path. For more details, enable tracing by setting COREHOST_TRACE environment variable to 1
### Application base path: D:\RD\edge-js-quick-start\src\QuickStart.Core\bin\Debug\net7.0
### Application dll: D:\RD\edge-js-quick-start\src\QuickStart.Core\bin\Debug\net7.0\QuickStart.Core.dll

D:\RD\edge-js-quick-start\node_modules\edge-js\lib\edge.js:178
return edge.initializeClrFunc(options);
^

TypeError: edge.initializeClrFunc is not a function
at Object.exports.func (D:\RD\edge-js-quick-start\node_modules\edge-js\lib\edge.js:178:17)
at Object. (D:\RD\edge-js-quick-start\main.js:26:34)
at Module._compile (node:internal/modules/cjs/loader:1198:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1252:10)
at Module.load (node:internal/modules/cjs/loader:1076:32)
at Function.Module._load (node:internal/modules/cjs/loader:911:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:22:47

Can you explain how you are modifying dotnet.runtimeconfig.json? Are you changing it in dotnet install folder because that would be very wrong.

Maybe start by explaining what you are trying to achieve in the first place by modifying runtime config. If we take a step back from Edge.js and look at C# code only, how are you changing it in pure C# and making your project work?

The article explains how to add runtime config to your project either via runtimeconfig.template.json in your project or by simply adding myapp.runtimeconfig.json to your compiled output.

Unfortunately at this time I do not see Edge.js offering support for changed dotnet.runtimeconfig.json. You are welcome to submit a PR to fix this issue.

I am currently porting a large codebase from .Net Framework 4.7 to .NET 8. Part of the codebase uses edge-js. Changes involve using grpc in some places instead of WCF amongst other things. When I tried to run the modified code using edge-js, at some point it crashed because Microsoft.Extensions.Configuration.Abstractions could not be found..
This was weird because the csproj added it as a nuget package. After a long lime I found the cause: One of the dependencies uses grpc, which has the aspnetcore framework set. Microsoft.Extensions.Configuration.Abstractions is not only part of a nuget package, but also of aspnetcore. As soon as a dependency references the aspnetcore framework the build removes the assemblies from the output!
A standard .NET app knows about this and loads the assemblies from the dotnet installation. Edge-js obviously is not a standard .NET app.
I tried several workarounds, and at some point I modified the runtimeconfig to make edge-js use aspnetcore, but that failed with the above result.

Ok now the problem makes sense however I can offer an easier solution. if you set the following properties in your .csproj

<PreserveCompilationContext>true</PreserveCompilationContext>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>

C# compile will copy all required assemblies to the output directory, this will include Microsoft.Extensions.Configuration.Abstractions if it is added via nuget, tested using QuickStart.

This is not ideal solution since it will dump all the required dlls into the output folder but definitely solves the problem more elegantly than modifying system dotnet.runtimeconfig.json

I am still surprised that it did not work correctly since Edge.js should have picked it up from yourproject.deps.json
If you look at QuickStart example have you set your paths correctly

process.env.EDGE_USE_CORECLR = 1;
process.env.EDGE_APP_ROOT = pathToMyOutput;
const edge = require('edge-js');

These parameter have to be set before you call const edge = require('edge-js');

All assemblies are in the .deps.json. The problem is that they are not in the output folder if you reference any project which has the AspNetCore framework set. When I started investigating I added dependencies one by one until this happened. I also tried the fixes you suggested.

I was about to write a comment that I fixed the problem by separating the grpc client and server implementations. The aspnetcore is only required by the server, and was not used by part that is used in edge-js. The assemblies now load fine.

But now I have another problem:
EF Core sqlite is used. For some reason it can't load the e_sqlite3.dll. It seems as if it is not aware it is running on a windows 10 x64 machine.
A pointer in this direction is that MutexSecurity.AddAccessRule throws a PlatformNotSupported exception.. This is not a big problem, but the e_sqlite3 problem is.

Great at least one problem solved, let me look into e_sqlite3.dll. Unfortunately depending on dll PlatformNotSupported can either be resolved relatively easy or not resolved at all. The only other open issue in this repo is referring to the one that I was not able to resolve at all.

What package are you using for SQLite, tried Microsoft.Data.Sqlite and it ran without any problems in QuickStart.

It is used indirectly with EF Core. I will try to use Microsoft.Data.Sqlite.

If you can give me package names and some code examples I will try to reproduce it, in some cases there is a relatively easy solution to this problem.

EDIT: publishing project rather than just compiling it might solve the problem #191 (comment)

The solution described in this link should fix the problem but you are unlikely to require additional package references so simply try publishing it with correct arch

Another thing to consider is if something runs in QuickStart without PlatformNotSupported it is not always indicative that it will run in another project however it does mean that the issue can be resolved using dotnet publish.

This is not an issue specific to Edge.js but rather an issue with dynamically loaded assemblies as I learned while researching #191

After a long investigation it finally works.
It all had to do with the EDGE_APP_ROOT. When it was not set, the assembly would load and initialize but e_sqlite3 could not be loaded. When EDGE_APP_ROOT is not set, the .deps file from the bootstrap folder is used.
When I did set EDGE_APP_ROOT, the trace would report:

CoreClrEmbedding::Initialize - Failed to initialize CoreCLR, HRESULT: 0x80070057

0x80070057 being "invalid parameter"

I have tried several things with EDGE_APP_ROOT, copying .deps files around etc. and each time got this error.
So at one point I decided to set it to the bootstrap folder which at least should work because it is effectively the default..
Same error????

When I opened the trace output from the with EDGE_APP_ROOT set to the bootstrap folder besides the one without EDGE_APP_ROOT I immediately spotted the difference:
The reported path without EDGE_APP_ROOT set had backslashes in it, and the one in which EDGE_APP_ROOT was set to the bootstrap folder had forward slashes! The latter apparently produces an invalid parameter error!

I have been a programmer for more than 40 years in Microsoft environments, and even in MS-DOS both variants were accepted as a path separator. I always use forward slashes because they are more portable.

@agracio maybe you can mention this in the documentation.

https://github.com/agracio/edge-js-quick-start has EDGE_APP_ROOT set, that is why I mentioned it earlier. Both default and EDGE_APP_ROOT set in https://github.com/agracio/edge-js-quick-start use forward slashes so not sure if you identified the problem correctly.

The likely problem you are facing is that EDGE_APP_ROOT in QuickStart and default resolver use path.join(...) to resolve directory correctly for a given OS, on Windows it will convert forward slashes to backslashes. Using path.resolve(...) or path.join(...) is a common practice in Node.js do not believe it requires documentation.

If you are looking for default resolver for C# interpreter it will be in node_modules/edge-cs/lib/edge-cs.js. If function getBootstrapDependencyManifest is defined in Edge.js language interpreter then defined dependencies will be loaded when using .NET Core. EDGE_APP_ROOT defines execution directory and should be set when using compiled assemblies.

https://github.com/agracio/edge-js-quick-start shows all the basics on how to run .NET Core app including EDGE_APP_ROOT setting.

Did you manage to resolve all of the issues with project migration?

The last step: changing the forward slashes to backslashes fixed it. There are more reports mentioning slash problems in dotnet BTW:
Slash problems

Maybe this is some kind of regression in .NET 8.

I will close the issue