microsoft / node-api-dotnet

Advanced interoperability between .NET and JavaScript in the same process.
MIT License
524 stars 58 forks source link

Path to Microsoft.JavaScript.NodeApi.DotNetHost.dll in electron binary is incorrect #332

Open sumeet-singh04 opened 4 months ago

sumeet-singh04 commented 4 months ago

When electron apps are packaged with ASAR enabled, all binaries get placed inside app.asar archive, but when accessed those need to be accessed via app.asar.unpacked directory if the node module does not use path or fs to resolve file names.

For now I am doing the below inside init.js to get things working on my end, but it would be nice to have this handled within the node-api-dotnet library.

let managedHostPath = __dirname + `/${targetFramework}/${assemblyName}.DotNetHost.dll`
  managedHostPath = managedHostPath.indexOf('app.asar.unpacked') < 0 ? 
    managedHostPath.replace('app.asar', 'app.asar.unpacked') : managedHostPath;
jasongin commented 4 months ago

I'm not sure about putting this kind of electron-specific logic in the library. Why isn't this a problem for any other npm package that loads binaries?

jasongin commented 3 months ago

Apparently it is a common problem, and is the reason the hazardous package was created. However that reportedly has problems with newer Electron builds.

jasongin commented 3 months ago

A potential solution here could be to offer a more general way to customize the initialization. Something like this:

const initDotnet = require('node-api-dotnet/init');
const dotnet = initDotnet({
    targetFramework: 'net8.0',
    binDir: 'path/to/asar.unpacked',
});

The optional binDir would be used instead of __dirname as the base path for locating the .NET hosting binaries.

Once initialized, any other calls to require('node-api-dotnet') return the existing already-initialized instance.

sumeet-singh04 commented 1 month ago

A potential solution here could be to offer a more general way to customize the initialization. Something like this:

const initDotnet = require('node-api-dotnet/init');
const dotnet = initDotnet({
    targetFramework: 'net8.0',
    binDir: 'path/to/asar.unpacked',
});

The optional binDir would be used instead of __dirname as the base path for locating the .NET hosting binaries.

Once initialized, any other calls to require('node-api-dotnet') return the existing already-initialized instance.

that or give the ability to pass a path resolution callback method, which the consuming application can use to provide logic to manipulate the binary paths to the exact location. My reasoning behind this that electron applications might not be packaged as asar's always. It's configurable.