question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Possible to use `IInitializeWithWindow` (or alternative) to load UI from .NET `.dll` into `HINSTANCE`/`HWND` of window provided by parent `.exe`?

See original GitHub issue

Heya, this might sound a bit convoluted but I’d really like to use .NET to write the UI for a plugin, that will be loaded as a .dll from a closed-source parent .exe.

The host application loads the plugin DLL and calls a named entrypoint function, it passes an hinstance/hwnd to a window it’s allocated for the plugin to use as an arg.

I was thinking of adding an [UnmanagedCallersOnly] attribute to a function in .NET, and using Dotnet Native Exports (https://github.com/AaronRobinsonMSFT/DNNE) and compiling as a shared library + using the assembly directly:

    [UnmanagedCallersOnlyAttribute(EntryPoint = "InitDll")]
    public static int InitDll(IntPtr hwnd)
    {
        // initialize the WinUI application here, use the hwnd that was passed with IInitializeWithWindow
    }

The other alternative that I was thinking might be possible was using the nethost and hostfxr libraries to write a small C++ app to work as a middleman to load + initialize the CLR and the WinUI assembly, and then act as the entrypoint used to start the app:

Parent .exe --> Loads MyAppWrapper.dll --> uses nethost.dll and hostfxr.dll to load MyAppAssembly.dll
            --> initializes the CLR and calls the entrypoint method of the .NET app in C/C++ exported function
            --> Entrypoint of .NET app takes an "IntPtr HWND" and uses this to set the render handle target
#define DLL_EXPORT __declspec(dllexport)

extern "C"
{
  // Entrypoint function called by host .exe when .dll is loaded
  DLL_EXPORT int InitDll(HWND hwnd) {
    load_hostfxr();

    // Initialize and start the .NET Core runtime
    const string_t config_path = root_path + STR("MyAppAssembly.runtimeconfig.json");
    load_assembly_and_get_function_pointer_fn load_assembly_and_get_function_pointer = nullptr;
    load_assembly_and_get_function_pointer = get_dotnet_load_assembly(config_path.c_str());

    // Load app assembly, that has an "UnmanagedCallersOnly" exported entrypoint function taking "IntPtr hwnd"
    const string_t dotnetlib_path = root_path + STR("MyAppAssembly.dll");
    const char_t *dotnet_type = STR("MyAppAssembly.Lib, MyAppAssembly");

    struct dotnet_managed_entrypoint_args { HWND hwnd };

    typedef void (CORECLR_DELEGATE_CALLTYPE *custom_entry_point_fn)(dotnet_managed_entrypoint_args args);
    custom_entry_point_fn custom = nullptr;

    rc = load_assembly_and_get_function_pointer(
        dotnetlib_path.c_str(),
        dotnet_type,
        STR("CustomEntryPointUnmanaged") /*method_name*/,
        UNMANAGEDCALLERSONLY_METHOD,
        nullptr,
        (void**)&winui_app_entrypoint_fn);

    // Call .NET entrypoint, give it the HWND handle
    dotnet_managed_entrypoint_args args{ .hwnd = hwnd };
    winui_app_entrypoint_fn(args);

    return EXIT_SUCCESS;
  }
}

Would be grateful for any wisdom on this, I don’t know very much about .NET Thank you! 😃

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
mdtaukcommented, Jun 10, 2021

This kind of scenario could be used for VST plugins for Digital Audio Workstation software

0reactions
GavinRay97commented, Jun 14, 2021

If you use NativeAOT or LLVM NativeAOT for .NET and there’s no dynamically loaded runtime, then is there still an issue?

Or could you also using Mono and mkbundle to statically embed the entire runtime? https://www.mono-project.com/docs/tools+libraries/tools/mkbundle https://www.mono-project.com/docs/advanced/runtime/#bundles

Read more comments on GitHub >

github_iconTop Results From Across the Web

Add native dlls and other files to .net exe
Now I'm trying to merge all files in to one exe, and I don't know how. ILMerge and similar will not work, as...
Read more >
Display WinRT UI objects that depend on CoreWindow
In this article. Set the owner window handle (HWND) for a WinRT UI object; For classes that implement IInitializeWithWindow; For classes that ...
Read more >
Dynamic-link library search order - Win32 apps
The system can check to see whether a DLL with the same module name is already loaded into memory (no matter which folder...
Read more >
1. Solutions and Projects - Mastering Visual Studio .NET ...
Solutions are the containers for all your work in VS.NET. A solution contains a project for each build output. (For example, if you...
Read more >
Rundll32: The Infamous Proxy for Executing Malicious Code
Today, we are going to dwell on a Microsoft tool, the infamous rundll32.exe, which allows you to load and execute code.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found