Skip to content
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

Support mixed-mode assemblies on Windows #10333

Closed
4 tasks done
morganbr opened this issue May 16, 2018 · 107 comments
Closed
4 tasks done

Support mixed-mode assemblies on Windows #10333

morganbr opened this issue May 16, 2018 · 107 comments

Comments

@morganbr
Copy link
Contributor

This issue will track progress toward supporting loading and running mixed-mode assemblies on CoreCLR. The main goal is to provide support for WPF and other existing C++/CLI code on .NET Core. Some of the work will be dependent on updates to the MSVC compiler.

Steps include:

  • Documenting how mixed-mode assemblies work in general
  • Proposing a .NET Core design
  • Loading mixed-mode assemblies into running managed code
  • Starting the runtime from native code in mixed-mode assemblies

This is related to #4116, but cross-platform support is outside of the scope of this issue as it's a compiler feature, not a runtime feature.

@morganbr morganbr self-assigned this May 16, 2018
@rickbrew
Copy link
Contributor

Paint.NET author here ... you've got my attention :D I have 50 KLOCs of C++/CLI code ... let me know if you need a guinea pig :)

@morganbr
Copy link
Contributor Author

Thanks, @rickbrew. It'll be a while until we're ready for Paint.NET, but we'll keep you in mind.

@mjsabby
Copy link
Contributor

mjsabby commented Jun 28, 2018

I think we can start by reverting dotnet/coreclr@1aa7d6b to at least allow the ability to load multi module assemblies.

@morganbr
Copy link
Contributor Author

@mjsabby, multi-module assemblies are orthogonal to mixed-mode. (Multi-module means you linked together netmodules using alink.exe, mixed mode means you have a combination of managed and native code in the same assembly). If you have a requirement for multi-module assemblies, I'd suggest filing a separate issue outlining what you need.

@mjsabby
Copy link
Contributor

mjsabby commented Jun 28, 2018

@morganbr Thanks. I'm not sure why I concluded that C++/CLI needs netmodule support.

@pongba
Copy link

pongba commented Sep 15, 2018

Awesome we're making progress on this ground. C++/CLI is what we use to bridge native service to the awesome .NET world. So far no other alternative achieves the elegance of C++/CLI as a glue language so it's fair to say that we're going to rely on C++/CLI as an integral part of our service.

Some time ago in the spirit of searching for performance gains by migrating from .NET framework to .NET core I sadly found that .NETCore doesn't go together with C++/CLI (even though we don't care about cross-platform yet).

And now this thread lifts my mood 👍 Looking forward to the release (as while I searched for solutions I saw a lot of people had the same need with C++/CLI in their own projects)

@nietras
Copy link
Contributor

nietras commented Oct 18, 2018

@morganbr given that "Loading mixed-mode assemblies into running managed code" is done, should it be possible to use latest .NET Core 3.0 preview together with mixed mode assemblies on Windows? E.g. from a C# application?

We intent to use .NET Core 3.0 with WPF and have quite a lot of C++/CLI dependencies/libraries (a lot third party too), so looking forward to this.

@morganbr
Copy link
Contributor Author

@nietras, I'm glad to hear you're eager to give this a shot. It's probably a little early to try it with the latest preview though. While the runtime can run mixed-mode assemblies now, the C++ compiler also needs some changes to make everything work smoothly.

In case anyone's interested in details, the main C++ compiler changes are:

  1. Be able to build against .NET Core assemblies instead of .NET Framework (this isn't strictly blocking, but can cause issues if the assembly references a type that isn't in Core or wants to use a type that isn't' in Framework)
  2. An assembly built with the current release of the C++ compiler will load and call into mscoree.dll on startup, which starts up .NET Framework. As you might imagine, having both runtimes think they loaded the assembly can cause lots of problems.

@pongba
Copy link

pongba commented Oct 23, 2018

@morganbr will the changes to C++(CLI) compiler that supports .NETCore be released together with the next version of Visual Studio, or will it be released out-of-band?

@morganbr
Copy link
Contributor Author

@pongba, I don't think we're ready to say exactly when or how we'll first distribute that version of the compiler, but it will eventually get distributed with Visual Studio.

@batzen
Copy link
Contributor

batzen commented Dec 8, 2018

So should it be possible to load assemblies which have ddlexports (vtfixup etc.) in them with the current preview of .net core 3.0? I am asking this because i just get a BadImageFormat exception when trying to load such assembly which i compiled with .net core 3.0 and used ildasm and ilasm to add the exports. The same code works when compiling with .net 4.6.2. I can provide the il code if required as a repro.

@Berrysoft
Copy link

Considering of C++/WinRT, is it possible to write a standard C++ projection for .NET Core?

@batzen
Copy link
Contributor

batzen commented Dec 21, 2018

@morganbr Would be nice to get a response from you. Not being able to at least load assemblies which contain an dll export prevents me from porting https://github.com/cplotts/snoopwpf to .NET core 3.0.

@morganbr
Copy link
Contributor Author

morganbr commented Jan 2, 2019

@batzen, you could be hitting a few different issues. You might be able to narrow them a bit by seeing if directly calling LoadLibrary on your assembly in the .NET Core process works. Some possible issues:

  1. Processor architecture mismatch (in particular, .NET Core is x64 by default while .NET Framework is x86 by default)
  2. Depending on how exactly your imports/exports are set up, your assembly might be causing mscoree.dll to load. If that happens, it tries to start .NET Framework and all kinds of bad things (including BadImageFormat) can happen. You should be able to spot mscoree.dll loading in a debugger if you have mixed-mode debugging enabled.
  3. Something specific to your ildasm/ilasm process. You'd need to debug further into the error to find out if there's something .NET Framework-specific that you're relying on.

@morganbr
Copy link
Contributor Author

morganbr commented Jan 2, 2019

@Berrysoft, .NET Core supports WinRT, although some of the features may only be available in UWP applications.

@Berrysoft
Copy link

@morganbr Oh, no, I mean, the current grammar of C++/CLI is non-standard. It is possible to make a projection of .NET Core with standard C++ grammar, so that other standard C++ compilers will compile the code, just like what C++/WinRT did for WinRT?

@batzen
Copy link
Contributor

batzen commented Jan 3, 2019

@morganbr

  1. Architecture is ok. Tried both, x86 and x64.
  2. It's a pure .net core 3.0 assembly. No reference to mscoree. Just one method in one class. IL code can be found at https://gist.github.com/batzen/8b1ed3e7269b4aaaacee846f188ef347
  3. I just run ilasm ManagedCore.il /outfile=ManagedCoreExported.dll /dll on the IL code from the gist.

Doing exactly the same for the equivalent IL code for .NET framework, which then of course contains mscoree references, works without an BadImageFormatException.
Loading of the modified assembly is done via Assembly.LoadFile.

If mixed mode assembly loading is supported in .NET core 3.0 are there any samples available? Some UnitTests you can point me to?

@jkoritzinsky jkoritzinsky self-assigned this Jan 31, 2019
@batzen
Copy link
Contributor

batzen commented Feb 2, 2019

As this issue is assigned now, i guess you were able to reproduce it?

@AaronRobinsonMSFT
Copy link
Member

@batzen Mixed mode assemblies aren't supported in .NET Core 3.0 yet. This issue is tracking that support. @jkoritzinsky is actively working on investigating what needs to happen and the changes that will need to be introduced. Look for a design doc on this in the next week or two.

@batzen
Copy link
Contributor

batzen commented Feb 4, 2019

@AaronRobinsonMSFT if loading mixed mode assemblies not currently not support the task point "Loading mixed-mode assemblies into running managed code" in this issue should be unchecked, shouldn't it?

@jkoritzinsky
Copy link
Member

@batzen We support loading mixed-mode assemblies into running managed code with some specific workarounds to avoid accidentally loading .NET Framework into the process. The runtime work is already complete for that feature.

We're still working on starting the runtime when a mixed-mode assembly is loaded from native code instead of managed code and starting the runtime if needed. Additionally, there's some compiler work needed to have the Visual C++ compiler link against something other than .NET Framework's mscoree.dll for loading the runtime.

Support for setting up the vtfixup table in a non-mixed mode assembly is something else that I think is the base problem of your isssue.

@ovebastiansen
Copy link
Contributor

ovebastiansen commented Feb 5, 2019 via email

@meirkr
Copy link

meirkr commented Mar 19, 2019

Hi.
Any progress with the ability to create c++/cli assembly and load it into my .Net core app?
Is it planned for. Net core 3.0 release?

@AaronRobinsonMSFT
Copy link
Member

@meirkr There is good progress. See dotnet/coreclr#22636 and dotnet/core-setup#5185. Much of what we are waiting on is VC++ tooling support. The plan is for the .NET Core 3.0 release.

@jkoritzinsky
Copy link
Member

The runtime/hosting work for C++/CLI has been merged in. We're just waiting on the VC++ compiler/tooling support now before we can validate the end-to-end experience.

@fabricefou
Copy link

@jkoritzinsky, will the new VC++ compiler targeting .Net core be able to compile old c++ runtime (vc10 for example) ?
Thanks

@weltkante
Copy link
Contributor

weltkante commented Oct 22, 2019

I want to try this out but I'm getting

1>C:\Program Files\dotnet\sdk\5.0.100-alpha1-014915\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(282,5): error NETSDK1073: The FrameworkReference 'Microsoft.NETCore.App' was not recognized

  • I have the latest VS preview update
  • the project is set to netcoreapp3.1 (by default, but verified it anyways, project file has <TargetFramework>netcoreapp3.1</TargetFramework>)
  • I have the latest dotnet 5 nightly just to make sure I'm not running into any already fixed bugs

any way to prevent VS picking up the wrong SDK?

@nguerrera
Copy link
Contributor

That is an issue with the 5.0 SDK builds at this point. They don't support targeting netcoreapp3.1. I suggest uninstalling that and using the 3.1.100-preview SDK that comes with VS.

5.0 is in very early days and the branches are not in great shape right now.

@weltkante

This comment has been minimized.

@nguerrera
Copy link
Contributor

Sorry, you can tell VS to use a specific SDK using global.json.

@nguerrera
Copy link
Contributor

@weltkante
Copy link
Contributor

oh, thanks, I'll try that out then!

@eightcloud83
Copy link

.net core 3.1(/VS16.4) at november 2019

.net core 3.1 has been set to december 2019. (so as VS16.4?)
(c++/cli .net core works on .net core 3.1 preview1 and VS16.4 preview2 (or VS16.3 with modifed proj setting ) )

@cocowalla
Copy link

Does this mean we can run existing C++/CLI assemblies in .NET Core apps without recompiling them?

@jeffschwMSFT
Copy link
Member

Does this mean we can run existing C++/CLI assemblies in .NET Core apps without recompiling them?

Existing C++/CLI assemblies are hardcoded to initialize .NET Framework, as such they need to be recompiled against .NET Core to function properly.

@Berrysoft
Copy link

Does this mean we can run existing C++/CLI assemblies in .NET Core apps without recompiling them?

Well, I've tried a few existing C++/CLI assemblies compiled with .NET Framework, and they run successfully even on .NET Core 3.0, but I strongly suggest recompiling them. I think they could run on .NET Core because of the compatible mode of .NET Core, but it doesn't ensure the success.

@cocowalla
Copy link

Existing C++/CLI assemblies are hardcoded to initialize .NET Framework, as such they need to be recompiled against .NET Core to function properly.

Ach, that's really disappointing 😢

We use some 3rd party mixed-mode assemblies which are the only thing tying us to the .NET Framework, and the chance of the vendor recompiling is close to zero.

No chance of some kind of compatibility layer then?

@jeffschwMSFT
Copy link
Member

No chance of some kind of compatibility layer then?

API wise they are likely close to compatible. The challenge is around activation. If the assembly believes it needs to activate .NET Framework there is very little we can do.

@shmuelie
Copy link
Contributor

shmuelie commented Nov 6, 2019

@jeffschwMSFT what if .NET Core is initialized by the caller? Would the mixed assembly just use what's already loaded?

@jeffschwMSFT
Copy link
Member

what if .NET Core is initialized by the caller? Would the mixed assembly just use what's already loaded?

The C++/CLI activation rules are complicated. Having .NET Core initialized is not sufficient. The rules can generally be distilled down to - if assembly's dllmain determines that the runtime needs to be activated, it will activate .NET Framework. There is not a reliable way to ensure that.

For testing purposes we have provided a shim for mscoree to intercept these calls, but that is not something that we would recommend as a durable solution.

@ericwj
Copy link

ericwj commented Nov 7, 2019

Is this only a problem if unmanaged exports are being used, or will DllMain be hit during managed load? In other words if I understand the process correctly will the native import which causes mscoree to load chain back to the native entry point?

Second question if this is a WPF or desktop app will someone start calling the DLL from native code?

My thought is that if C++/CLI is being used for native needs internal to the app and native pinvokeimpl methods are only called from IL then DllMain might never run?

@jeffschwMSFT
Copy link
Member

It is a combination of the OS and binary making these decisions. It is likely possible to model these and narrowly avoid the unintended loading of .NET Framework, but I would advise against it. Our recommendation is to rebuild with .NET Core - which avoids all of these issues.
You have the right direction on when it is possible for .NET Framework to be loaded (both in dllmain and the first time that p/invokes are executed).

@ericwj
Copy link

ericwj commented Nov 7, 2019

Well if you don't have source code it'd be worth a try - first check would be to see if there are any native exports beyond what an empty project would create (a staggering lot, I warn you). Also if the time is still that men are made of steel and ships from wood as opposed to the other way around then you could figure out everything with dumpbin /DISASM and ildasm and/or IL Spy.

@cocowalla
Copy link

I just tried porting an old managed C++/CLI project, but I'm getting a BadImageFormat exception when I try to use it:

Unhandled exception. System.BadImageFormatException: Could not load file or assembly 'MyAssembly, Version=2019.0.1.0, Culture=neutral, PublicKeyToken=null'. An attempt was made to load a program with an incorrect format.
File name: 'MyAssembly, Version=2019.0.1.0, Culture=neutral, PublicKeyToken=null'
   at TestApp.Program.Main(String[] args)

Both the managed assembly and test app target X64, and I'm using Visual Studio Preview 16.4.0 Preview 4 with .NET Core 3.1 preview 2. The built assembly looks to be the correct size, and decompilers such as JustCompile or ildasm work with it just fine. I can see it has a TargetFrameworkAttribute set pointing to NETCoreApp,Version=v3.1.

Any ideas what could be the problem?

@nietras
Copy link
Contributor

nietras commented Nov 8, 2019

We use some 3rd party mixed-mode assemblies which are the only thing tying us to the .NET Framework, and the chance of the vendor recompiling is close to zero.

Just wanted to acknowledge that as with @cocowalla we are in the exact same position, we have mixed-mode assemblies from third parties that have no intention of updating to .NET Core, this basically ties us to a dead platform in the form of .NET Framework 4.8 and we are left (again) with stagnant technology. This is a problem. I love .NET Core and all the great things in it, but what use is it if we can't use it in key projects?

@shmuelie
Copy link
Contributor

shmuelie commented Nov 8, 2019

this basically ties us to a dead platform in the form of .NET Framework 4.8 and we are left (again) with stagnant technology

Stagnant fine but dead?

".NET Framework 4.8 will be the last major version of .NET Framework. If you have existing .NET Framework applications that you are maintaining, there is no need to move these applications to .NET Core. We will continue to both service and support .NET Framework, which includes bug–, reliability– and security fixes. It will continue to ship with Windows (much of Windows depends on .NET Framework) and we will continue to improve the tooling support for .NET in Visual Studio (Visual Studio is written on .NET Framework). " - .NET Core is the Future of .NET

@weltkante
Copy link
Contributor

weltkante commented Nov 8, 2019

Any ideas what could be the problem?

@cocowalla Mismatch between 32/64 bit? Are you sure you are running the .NET Core application in the same bitness as the C++/CLI library was compiled?

@cocowalla
Copy link

@cocowalla Mismatch between 32/64 bit? Are you sure you are running the .NET Core application in the same bitness as the C++/CLI library was compiled?

Nope, as I mentioned, both the managed assembly and test app target X64. I even confirmed with dumpbin /headers 😞

@jeffschwMSFT
Copy link
Member

@cocowalla for new issues it likely makes sense to open new issues. In this case can you ensure that ijwhost.dll is present? For .NET Core to successfully activate C++/CLI this component is necessary. We are aware that the error message is not helpful, and are looking to improve that experience.
By default if you build with VS 16.4+ with a C++/CLI project this file is added automatically.

@cocowalla
Copy link

@jeffschwMSFT fair point, will open a new issue. Regarding ijwhost.dll tho, is this meant to be in the same dir as the app running the managed C++/CLI assembly?

@jeffschwMSFT
Copy link
Member

ijwhost should be along side the C++/CLI assembly

@cocowalla
Copy link

@jeffschwMSFT brilliant, thanks!

The ijwhost.dll was indeed missing - it was output by the C++/CLI project, but wasn't in the output of the test app. Now it's there, it seems to work!

@msftgits msftgits transferred this issue from dotnet/coreclr Jan 31, 2020
@msftgits msftgits added this to the 3.0 milestone Jan 31, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 17, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests