.NET Core 3.1 added support for C++/CLI (Announcing .NET Core 3.1). The official announcement lists two new project templates, CLR Class Library (.NET Core) and CLR Empty Project (.NET Core), which we can indeed find and use.
However, there is no additional information about supporting technologies such as WPF or Windows Forms. In a blog posts in September, Microsoft said:
we are committed to supporting C++/CLI for .NET Core to enable easy
interop between C++ codebases and .NET technologies such as WPF and
Windows Forms. This support isn’t going to be ready when .NET Core 3.0
first ships, but it will be available in .NET Core 3.1 which ships
with Visual Studio 2019 16.4
Using Visual Studio 2019 16.4.x and targeting .NET Core 3.1, I have tried to create a demo WinForms app using C++/CLI. However, it does not work.
First of all, C++/CLI projects targeting .NET Core must be DLLs:
error NETSDK1116: C++/CLI projects targeting .NET Core must be dynamic
libraries.
So I tried keeping the Win Forms code in a C++/CLI DLL compiled with /clr:netcore and running it from a native app. However, I get a runtime exception:
Unhandled exception. System.BadImageFormatException: Could not load
file or assembly 'System.Windows.Forms, Version=4.0.0.0,
Culture=neutral, PublicKeyToken=b77a5c561934e089'. An attempt was made
to load a program with an incorrect format. File name:
'System.Windows.Forms, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089' ---> System.BadImageFormatException:
An attempt was made to load a program with an incorrect format.
(0x8007000B)
I have referenced in the C++/CLI project the System.Windows.Forms.dll from c:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\3.1.0\, which is the location of the Microsoft.WindowsDesktop.App 3.1.0 runtime.
Is this supposed to work and I'm not doing something right?
I had similar issue with my simple sample of .NET Core C# executable using the C++/CLI (managed C++) .Net Core DLL. Eventually figured out that I needed to explicitly set my C# executable target from Any CPU to x64. Most of the time it comes down to 32 bit / 64 bit mismatch.
I found this document on the microsoft's website.
It explains how to do it, and is accompanied by a github repo you can easily clone and try out yourself:
https://devblogs.microsoft.com/cppblog/porting-a-c-cli-project-to-net-core/
Related
This might be a very specific question. But it might be interesting for some other people, too.
The setting might be quite common: we develop an embedded device using C++ and Linux and have a build system for this. With our device we ship a C# desktop app using a DLL based plugin mechanism. The plugin contains the shared logic used both on the embedded device and the app. To keep processes easy it would be best to create the DLL on our Linux build system (hence I would like to use .Net Core and not "normal" .Net).
As far as my trial and error showed it's not possible - even with .Net Core 3.1. Can you confirm this? The software is for windows only (although it's compiled on Linux) - so theoretically it could possible since .Net Core supports CLI/C++ in Version 3.1 (https://devblogs.microsoft.com/dotnet/announcing-net-core-3-1/).
What I tried:
I compiled pure C# code on Linux to an exe running successfully on windows using the console app dotnet
I successfully created a simple C++/CLI test app on Windows using sample code following this guide: https://devblogs.microsoft.com/cppblog/an-update-on-cpp-cli-and-dotnet-core/
Finally I took the (probably for too naive) approach to replace the test app's .vcxproj with the .csproj of step 1 (.csproj seems to detect files automatically). I got the following error message:
quote CSC : error CS5001: Program does not contain a static 'Main' method suitable for an entry point [/home/vagrant/Projects/cpp_dotnet_on_linux/cs_on_linux.csproj]
Is there something I can improve or is the task just impossible (adding the cpp-files manually to .csproj, ...)? I'm afraid it's just technically impossible because I guess .Net Core is missing a C++ compiler on Linux but I'm not sure.
C++/CLI is not support on Linux.
Some sources:
https://devblogs.microsoft.com/cppblog/the-future-of-cpp-cli-and-dotnet-core-3/ :
We don’t currently have plans for C++/CLI for targeting macOS or Linux. Additionally, compiling with “/clr:pure” and “/clr:safe” won’t be supported for .NET Core.
https://github.com/dotnet/coreclr/issues/659#issuecomment-539742740
C++/CLI on Linux will not be supported and would be very challenging. It would require Microsoft VC++ to support Linux or require Clang or GCC to support C++/CLI. Those are both huge projects with uncertain payoff. It is also unclear if Clang or GCC would ever allow us to upstream our changes. Maintaining an up-to-date fork of a fast moving compiler project forever is very expensive. We have no plans to take on either of those projects.
Can we use ninja to build UWP apps and hence create the appx package for the same?
I don't feel there is an online article for the same. I know how to do it using VS and Make.
In theory: Yes
Notable one thing: Ninja just official support C++, I can't find any result Ninja support other programming languages
With C++ we have 2 options:
C++/CX: You should activate flag /ZW for Windows Metadata
C++/WinRT: With WinRT you just compile without any restrict, this doesn't need Windows Metadata anymore
C++/CX: we have long story behind Windows Runtime development before C++ 11/14 became official so Microsoft add their own implementation features to MSVC. So with C++/CX you can compile with very old SDK like 10240, 10586, ... and in theory it also work with Windows 8.0/8.1 SDK, Windows Phone 8.0/8.1 SDK. Another attemp try to compile UWP with C++/CX on FastBuild (system build like Ninja) is successful, you can read as a reference here: https://github.com/fastbuild/fastbuild/issues/623
C++/WinRT is reunion attempt make Windows Runtime back to standard C++ 17. C++/WinRT can also compile with Clang/GCC. Base on answer from Kenny Kerr (creator of C++/WinRT): C++/WinRT is not limit with old SDK, but he recommended to use newer SDK like 17134. Link his answer https://stackoverflow.com/a/53193711/8707331.
Some useful links for C++ UWP:
https://github.com/MicrosoftDocs/cpp-docs/blob/master/docs/porting/how-to-use-existing-cpp-code-in-a-universal-windows-platform-app.md
https://modernwindows.wordpress.com/2015/05/28/modern-c-and-clang/
you can create uwp apps in following ways:
c# and xaml
web technologies like html, css and js. and you can use any
third party js libraries with it. you can even use hosted web apps
as uwp apps or latest technologies like pwas can also be shipped as
uwp apps. more here : https://developer.microsoft.com/en-us/windows/pwa
c++ and xaml : with this approach you can use c++ libraries (if they comply by uwp platform) the reason you do not have much support online for this is because majority of uwp developers use c# and xaml approach.
There are some work around for that, and one of them is to create a Desktop app and then package that in MSIX packaging , which packages a windows Desktop app into a uwp app and you can even distribute it through Microsoft store.
CMake can't be used to generate UWP package. However, you could use make.exe or Visual Studio to generate UWP package. For more you could refer to Create an app package with the MakeAppx.exe tool and Package a UWP app with Visual Studio.
I just created a clr c++ aplication that combine c++ code and windows form
as resoalt the exe prodused from visual studio cannot use /mt and its not standalone (it require the wright .net installed on the computer)
are there ANY way to make a fully standalone exe from clr c++ exe?
i tried to check out spoon studio and Cameyo but it's look like they work only on files that includes instalation ...
The point is what a standalone application would buy you here? There is no such thing as a "standalone application" anyway - depending on how hard you look at it. You'll always have dependencies at least on the Windows version you intent your application to run on.
In the end it boils down to deployment or distribution issues. If you don't want your users to install a (newer) version of the .NET framework just to run your application, then start by determining the lowest Windows version you want to support with your application. Then check here for the .NET version that comes preinstalled with that version of windows. Then target your application against that version of .NET.
We have a Visual Studio solution with about 90 projects. Most of them are built to DLL files, some are written in C++, others in C#. The projects communicate with each other via COM. We use tlbexp to generate TLB files of some C# projects (the ones that are referenced in C++ projects). And we use tlbimp to generate interop DLLs of the C++ projects. I did not completely dig into the topic, but I think, the interop files just define the interfaces of the C++ classes, to make them usable from other projects is that right?
Now, the question is the following: In order to upgrade the entire solution to Visual Studio 2015 and let it compile against .NET 4.6.1, I inspected the resulting assemblies using dotPeek by JetBrains. I can see, that all the C# projects are correctly using .NET 4.6.1, the C++ DLLs themselves are native and do not reference any .NET. Now, what surprised me was the fact, that dotPeek told me, the interop DLLs (which resulted from the C++ projects), were referencing .NET 4.0.
After a "wonderful" day of trying to make them reference .NET 4.6.1 and lots of research, I finally did not find any way to make the interops reference .NET 4.6.1. Is that even possible? My current guess is, that all interop DLLs generated like this reference just the basic .NET 4.0, just because it uses the same CLR as .NET 4.6.1.
Is that right? It should be possible to execute the assemblies on any system that has .NET Framework 4.6.1 installed, shouldn't it?
You are getting bad info from dotPeek. It doesn't tell you how it figured out what .NET version is targeted. It can be specific on a .NET assembly that's generated by a compiler. Because it automatically inserts a [TargetFramework] attribute into the assembly, it states what version of .NET you selected when you built the project.
But an interop assembly does not specify a .NET version, primarily because it isn't generated by a compiler. Note how you never specified a version when you ran Tlbimp.exe. And can't. All that dotPeek can figure out is that it targets .NET 4, cued by the metadata format. No way it can be more specific.
And it does not matter, since the interop library does not use .NET Framework features. The only point of the library is that your program can use the COM component features. So the version number that dotPeek reports just doesn't matter; any .NET 4.x framework can use the library.
You don't have a real problem.
I have a VS2008 Professional solution that I tried to convert to VS2010 Professional (RTM from MSDN download) today and I am experiencing some problems with some unmanaged and managed C++ DLLs that are referenced by a C# application.
The C# application is set to target .NET 3.5 (as it was in the VS2008 version) but when I try and compile it I get a lot of warnings like:
The primary reference "xxxx.dll" could
not be resolved because it had an
indirect dependency on the .NET
Framework assembly "(various assembly
names)", Version 4.0.0.0 ... which has
a higher version "4.0.0.0" than the
version "3.5.0.0" in the current
target framework
and ultimately I get a failure to build.
From this I understand that it is a mismatch in .Net framework version. So I look at the properties of the unmanaged C++ DLL project and under "Common Properties->Framework and References" I can see "Targeted framework: .NetFramework, Version=v4.0"
So I go WTF!?!?!?, why does a pure C++ DLL now target a .Net framework when it sure as hell didn't in the VS2008 version. I then added on to that exclamation as there appears to be no way to change this. I also look at the managed C++ and see the same thing: targeting .Net version=v4.0 and again no way to change this at all.
In the C++ General properties there is an entry for "Common language runtime support" and I have set this to "No common language run time support" but that hasn't seem to have done anything.
So I have two questions:
Why has my pure C++ DLL now been tagged as targeting a .Net framework?
How can I change/remove this targeting?
Solution
As per Hans' reply and the link he supplied I now see that I have 3 choices:
Stay at VS2008 and everything works
Keep both VS2008 SP1 and VS2010
installed so that I can have .Net
3.5 c# applications and c++ managed code as per the link supplied by Hans.
Move everything to VS2010 and move
to a minimum of .Net 4.0 for all my
c# apps
I am really annoyed to have to make that choice as MS has deliberately chosen to break functionality when moving from VS2008 to VS2010. This is not the sort of behavior I expected. I was expecting to convert the project and have it compile with no issues in the same manner that moving from VS2005 to VS2008 worked.
Fortunately I do have a need to go to .Net 4.0, but I just wasn't expecting to have to do it so soon.
Update
I decided to move to .Net 4 framework and encountered problems with referencing managed c++ projects from c# projects. I was getting errors like the following when trying to add the reference to the c++ managed code project
A reference to 'myproj' could not be
added. An Assembly must have a 'dll'
or 'exe' extension in order to be
referenced.
Google lead me down the path to "cli c project cannot be referenced from c project allowing only assembly dll" which turned up that there was an extraneous "\" in the output path of the managed c++ project. The original VS2008 output path was specified as
$(SolutionDir)\$(ProjectName)\$(Configuration)\
But in the VS2010 project the SolutionDir macro has a trailing "\" (or the VS2008 version didn't care about it) giving a path like
c:\projects\thisproject\solution\\projectname\configuration\
And VS2010 barfed over that path when trying to add a reference to the managed c++ code. My solution was to change the output path to be
$(SolutionDir)$(ProjectName)\$(Configuration)\
And now I am (sort of) happy
Keep your eyes on the ball, the warning you get is for a managed C++ assembly. And the platform target setting for an unmanaged DLL is of no consequence, it won't use any .NET references while being built.
Yes, they could not make the platform target setting editable in the C++ IDE, the VS2008 tool chain is required to build C++/CLI assemblies for 3.5. This blog post explains the workaround. You can upvote this feedback article if you're unhappy with that.