Skip to content

Publishing standalone app (C#) fails with C++/CLI dependency #12345

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

Open
chrisbardon opened this issue Apr 22, 2020 · 47 comments
Open

Publishing standalone app (C#) fails with C++/CLI dependency #12345

chrisbardon opened this issue Apr 22, 2020 · 47 comments
Assignees
Labels
Area-NetSDK For consideration Used for items on the backlog to raise them to the top of that list for discussion
Milestone

Comments

@chrisbardon
Copy link

I'm trying to port a WPF app (C#) to core 3.1, but it has a dependency on a C++/CLI managed wrapper on an unmanaged DLL. The dependency works, and I can build/run and publish as Framework Dependent, but I get a failure when I try to publish self contained. The error that I get in VS 16.5.4 is:

Publish has encountered an error.
Publish has encountered an error. We were unable to determine the cause of the error. Check the output log for more details.

And the .tmp file it generates tells me:

4/21/2020 8:58:07 PM
System.AggregateException: One or more errors occurred. ---> System.Exception: Publish has encountered an error. We were unable to determine the cause of the error. Check the output log for more details.
--- End of inner exception stack trace ---
---> (Inner Exception #0) System.Exception: Publish has encountered an error. We were unable to determine the cause of the error. Check the output log for more details. <---

System.Exception: Publish has encountered an error. We were unable to determine the cause of the error. Check the output log for more details.

Which is not helpful... The publish output however, had this buried in it:

3>Task "NETSdkError" skipped, due to false condition; ('$(Language)' == 'C++' and $(EnableComHosting) == 'true') was evaluated as ('C++' == 'C++' and == 'true').
3>Using "NETSdkError" task from assembly "C:\Program Files\dotnet\sdk\3.1.201\Sdks\Microsoft.NET.Sdk\targets..\tools\net472/Microsoft.NET.Build.Tasks.dll".
3>C++/CLI projects targeting .NET Core cannot use SelfContained=true.
3>Building with tools version "Current".

That implies that there's no way to build this as a self contained application, which was part of the motivation for going to .net core with this app in the first place (zero dependency deployment). Is there a way to get this to work, or is it a bug?

@ghost
Copy link

ghost commented Apr 22, 2020

Tagging subscribers to this area: @ViktorHofer
Notify danmosemsft if you want to be subscribed.

@ghost
Copy link

ghost commented Apr 22, 2020

Tagging subscribers to this area: @vitek-karas, @swaroop-sridhar
Notify danmosemsft if you want to be subscribed.

@vitek-karas
Copy link
Member

I think this is because we don't allow loading "components" as self-contained. Is that right @jkoritzinsky ?

@jkoritzinsky
Copy link
Member

Building a self-contained C++/CLI application is not supported, but I remember some discussions with the SDK team about if C++/CLI dependencies of a self-contained C# app should be supported. @wli3 do you remember where we landed on that?

@wli3
Copy link

wli3 commented May 11, 2020

C++/CLI dependencies of a self-contained C# app should be supported.

That is true. From the error code message $(Language) is evaluated to C++. It might be caused by running /t:publish in the folder. So all projects get published. Maybe try only publish the WPF project.

@CrapuleJack
Copy link

Just for the record, I too am having the same problem. I hope this is a feature .net 5 will bring.

For now I rely on the fact that my app directs the user to download and install the CLR at first run, wich is not ideal. A self-contained publish would be.

@FunksMaName
Copy link

I am experiencing this issue as well, and it would be great if Microsoft can just provide an official stance on the state of affairs, by clearly stating this limitation on their documentation, here are a few places to start:

Your official documentation page on publishing self contained apps for various runtimes
https://docs.microsoft.com/en-us/dotnet/core/deploying/deploy-with-cli

Blog entry touting the new C++/CLI project prowess which does not state this very important limitation
https://devblogs.microsoft.com/cppblog/porting-a-c-cli-project-to-net-core/

It's a very clumsy experience for our end user when we now have to make them download the Runtime prior to our app installation.

@FunksMaName
Copy link

@wli3 Just to remove any ambiguity, attempting to self contained publish just the project which takes a dependency on the C++/CLI project as you appear to suggest does not work either. This is what I get

C:\Program Files\dotnet\sdk\3.1.201\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInference.targets(181,5): error NETSDK1121: C++/CLI projects targeting .NET Core cannot use SelfContained=true. [C:\Dev\yyy\src\yyy\yyy.Driver.Bridge.vcxproj]

@CrapuleJack
Copy link

An other option would be to provide a .netcore runtime merge module I could include in my setups .msi, but I cant find those if they exists, anyone knows about that?

This would be an alternative but the ideal would still be self contained deploy.

@FunksMaName
Copy link

@CrapuleJack my work around was to a WIX Bundle project to install the dependency, if you are using wix then here is a reference

<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" 
     xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
	<Bundle 
    Name="YYYY Driver Installer (Bundle)" 
    Version="1.0.0.0" 
    Manufacturer="YYYY" 
    UpgradeCode="F6396F05-BEDF-4B14-AD41-57C91CBC8772"
    IconSourceFile="app.ico">
    <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
      <bal:WixStandardBootstrapperApplication
        LicenseFile="License.rtf"
        LogoFile="Logo.png" />
    </BootstrapperApplicationRef>
    <Chain>
	  <!-- Dot Net Hosting Runtime exe
	  (the command -q seems to make it install silently but not documented anywhere)  -->
      <ExePackage SourceFile="dotnet-hosting-3.1.5-win.exe"
                  InstallCommand="-q"
                  UninstallCommand="-q">
        <ExitCode Value="0" Behavior="success" />
      </ExePackage>
      <RollbackBoundary />
      <!-- Your Product MSI -->
      <MsiPackage 
        SourceFile="YourInstallationMSI.msi"
        DisplayInternalUI="no" /> 
    </Chain>
	</Bundle>
</Wix>

Some resources around WIX Boostrapping
https://stackoverflow.com/questions/47399366/wix-how-do-i-launch-another-msi-or-exe-inside-my-installer-c
https://www.firegiant.com/wix/tutorial/net-and-net/bootstrapping/

@CrapuleJack
Copy link

CrapuleJack commented Jun 13, 2020

@FunksMaName Thanks a lot for that, I will take a look at that for sure. Yes I am using wix, it is awesome.

@vitek-karas vitek-karas transferred this issue from dotnet/runtime Jul 6, 2020
@vitek-karas
Copy link
Member

I moved this to dotnet/sdk as the issues seems to be around failures during publish.

@l0hn
Copy link

l0hn commented Jul 16, 2020

Will this be supported in .net 5? We have spent quite a long time porting a project over and have just hit this issue.

@Proudloaf
Copy link

Also had this problem attempting to create an MSIX install from Visual Studio. Previously our .Net framework WPF + CLI install worked fine, now we have upgraded to .net core 3.1 WPF +CLI and everything works fine apart from publishing to MSIX where we get: "C++/CLI projects targeting .NET Core cannot use SelfContained=true."
Even if we accept that we can't use SelfContained I can't seem to get the MSIX to do a Framework-dependent publish either.
I really don't want to go back to .Net framework but I'm running out of options.
Anyone got any advise?

@ZenoArrow
Copy link

Is fixing the standalone/self-contained C++/CLI issue on the roadmap for .NET 5? This is blocking our preferred update strategy.

@dsplaisted dsplaisted added the untriaged Request triage from a team member label Dec 1, 2020
@zhuman
Copy link

zhuman commented Dec 29, 2020

I think it's quite puzzling that this wasn't considered a ship-blocker for .NET Core 3.1 and .NET 5.0. There is no technical blocker to publishing a self-contained deployment that happens to include a C++/CLI dependency. Nuget packages that contain C++/CLI assemblies do not suffer from this SDK error message (since they are just seen as managed dependencies). This is in fact a workaround for this problem; people have to package up their component as a Nuget package and reference it from the other managed assemblies, which is a silly amount of work.

It was mentioned above that this error exists to discourage people from trying to ship self-contained "components" where a native host loads a C++/CLI assembly as a native component. However, this is likely a very edge-case scenario, whereas shipping a fully managed EXE as self-contained that happens to also have a C++/CLI project in its dependency graph is an extremely common scenario, especially for people porting .NET framework apps to .NET core. This should be a well-tested scenario by the donet/SDK teams, but clearly it's not as it's blocked by this SDK error. All that really needs to be done here to fix the SDK is to prevent the error from being issued if the user has somehow declared they are not shipping a standalone "native component" DLL.

For anyone that comes here looking for answers, a quick workaround is that you can add the following lines to your .vcxproj files after Microsoft.Cpp.targets file is imported.

<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

<!-- Disable the .NET SDK error that prevents using SelfContained=true -->
<Target Name="_CheckForLanguageAndFeatureCombinationSupport"></Target>

@scnanney
Copy link

scnanney commented Feb 2, 2021

Please fix this.

@AndreyMikhailov
Copy link

AndreyMikhailov commented Feb 15, 2021

Just faced this problem. Thought this would be fixed in .net 5.0. But sadly no.

Also zhuman's advice helped. Thank you.

@wli3 wli3 removed the untriaged Request triage from a team member label Feb 16, 2021
@wli3 wli3 added this to the 6.0.1xx milestone Feb 16, 2021
@daerlnaxe
Copy link

Same problem

@mjfusa
Copy link

mjfusa commented Jul 23, 2021

Same problem as @Proudloaf with Windows App SDK app with C++ CLI dependency. App builds and run fine, but get errors when attempting to create app packages. Unfortunately @zhuman suggestion didn't work for me. However the error is now different:
Severity Code Description Project File Line Suppression State
Error Assets file 'C:\p\Test1\Test1\Test1\obj\wappublish\win10-x86\project.assets.json' doesn't have a target for 'net5.0-windows10.0.19041.0/win10-x86'.
Ensure that restore has run and that you have included 'net5.0-windows10.0.19041.0' in the TargetFrameworks for your project.
You may also need to include 'win10-x86' in your project's RuntimeIdentifiers. Test1 (Package) C:\Program Files\dotnet\sdk\5.0.302\Sdks\Microsoft.NET.Sdk\targets\Microsoft.PackageDependencyResolution.targets 242

@damien78
Copy link

damien78 commented Aug 19, 2021

@mjfusa When the C# project has a target framework with Windows build specifiied (e.g. <TargetFramework>net5.0-windows10.0.17763.0</TargetFramework>), and not just <TargetFramework>net5.0-windows</TargetFramework>, you need to also specify in the same property group, the RuntimeIdentifiers, like <RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
Example of such property group in the WPF .csproj file:

<PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>net5.0-windows10.0.17763.0</TargetFramework>
    <UseWPF>true</UseWPF>
    <Platforms>AnyCPU;x64</Platforms>
    <RuntimeIdentifiers>win-x64</RuntimeIdentifiers>
  </PropertyGroup>

This update then enables to build the app packaged, and run the packaged app from Visual Studio.
But now I'm stuck with the next roadblock when trying to create the .appx for publishing (Using the WAP project Publish > Create App Packages...) command, with a NuGet restore error:
1>The runtime pack for Microsoft.NETCore.App.Runtime.win-x64 was not downloaded. Try running a NuGet restore with the RuntimeIdentifier 'win-x64'.

This error happens with either Visual Studio 16.11.1 and .NET5.0, or 17.0.0 Preview 3.1 and .NET6.0 preview

@dsplaisted
Copy link
Member

@damien78 Could you try setting the RuntimeIdentifier property instead of RuntimeIdentifiers? Just a guess, but that might fix the issue.

@damien78
Copy link

@dsplaisted Thanks, but no luck with this. Build successful, but same error when creating the packages

@marcpopMSFT marcpopMSFT modified the milestones: 6.0.3xx, 7.0.1xx Mar 30, 2022
@dsplaisted dsplaisted added the untriaged Request triage from a team member label Mar 30, 2022
@pantonis
Copy link

@marcpopMSFT so this is moved to .NET7? In 6+ months? Very very sad

@marcpopMSFT marcpopMSFT added the needs team triage Requires a full team discussion label Apr 15, 2022
@jeffward01
Copy link

@marcpopMSFT so this is moved to .NET7? In 6+ months? Very very sad

This ticket has been an active and open ticket for 2 years already. It seems that this should take priority as it is an internal function of .NET Framework versus 'new features' in net7.0

@ZenoArrow
Copy link

@marcpopMSFT so this is moved to .NET7? In 6+ months? Very very sad

It's not even clear that this will be released with .NET 7. I haven't seen evidence that it's included in the .NET 7 alpha releases. Just seems like another delaying tactic. I honestly don't know why this isn't being treated as a higher priority issue, would be good to understand the complexity in making a fix.

@dsplaisted
Copy link
Member

I did some investigation of this, and it looks like it will probably be fixed by the following PRs:

We don't know for sure when we will be able to ship those, though.

The problem has to do with the fact that the SelfContained property flows from the managed project to the referenced C++/CLI project. So there are some possible workarounds:

  • Specify SelfContained in the project file directly instead of via the publish dialog
  • Publish from the command line, specifying the RuntimeIdentifier but not the SelfContained property. When a RuntimeIdentifier is set, then the app will default to self-contained. Here's a sample of how to do this:
msbuild /restore /p:PlatformTarget=x86 /p:RuntimeIdentifier=win-x86 /t:Publish

@marcpopMSFT marcpopMSFT removed untriaged Request triage from a team member needs team triage Requires a full team discussion labels May 4, 2022
@snandos
Copy link

snandos commented Aug 13, 2022

I'm facing the same issue while creating a dotnet 6 Microsoft store app with a C++/CLI interop library. I have tried a lot of workarounds in this thread and seem to go around in circles.
I tried

  • Adding _CheckForLanguageAndFeatureCombinationSupport to the vcxproj
  • Adding deploy.bat with manual msbuild command with PlatformTarget and RuntimeIdentifier
  • Adding lots of PlatformTargets, RuntimeIdentifiers and so forth to the csproj, vcxproj and wapproj files

and some more things which lead to nothing.

And I still get errors like NETSDK1032: The RuntimeIdentifier platform 'win-x86' and the PlatformTarget 'x64' must be compatible, or NETSDK1112: The runtime pack for Microsoft.NETCore.App.Runtime.win-x86 was not downloaded. Try running a NuGet restore with the RuntimeIdentifier 'win-x86'. I guess it is similar to what @mjfusa experienced.

I've created a minimum demo project with a C#, C++/CLI and packaging project. Maybe there is someone who can lead us in the right direction and get this demo deploying? The repository is located here: https://github.com/snandos/CPPCLI_Test

@mgexo
Copy link

mgexo commented Oct 16, 2022

msbuild /restore /p:PlatformTarget=x86 /p:RuntimeIdentifier=win-x86 /t:Publish

Thanks, the trick is really to use msbuild and not dotnet for doing the publish.

This did not work for fully for for us though, because we have C++/CLI libraries in our solution that shall be published.
The trick here is to only publish a specific project for a specific configuration:

msbuild /restore /t:"MyMainExeProjectName:Publish" /P:DeployOnBuild=true  /p:PlatformTarget=x64 /p:RuntimeIdentifier=win10-x64 /p:Configuration=Release MySolution.sln

Unfortunatly, the software crashed on start then, and in debug crash dumps we could see, that it crashed while loading C++/CLI dependencies.

So, additionally, we set ExcludeFromSingleFile=true for all PacketReferences, ProjectReferences, Content includes etc. that are connected to native or mixed/managed c++/cli code or their references.

Then it did not crash any more.

However, this is in the end not really "single-file" but at least the .NET6 is embedded in the .exe (which is now huge i.e. 150MB). It seems a bit unclear, what .NET6 those .dlls in the folder are using i.e. if they use the .NET6 from the .exe or if they use it from the system.

@khoabui1412
Copy link

khoabui1412 commented Nov 16, 2022

I meet the error when tried to publish with cli/c++ project:

Assets file '...<cli/c++ project>\obj\project.assets.json' doesn't have a target for 'net6.0/win10-x86'. Ensure that restore has run and that you have included 'net6.0' in the TargetFrameworks for your project. You may also need to include 'win10-x86' in your project's RuntimeIdentifiers.

Is it possibile to specify RuntimeIdentifiers in cli/c++ project?

@molesmoke
Copy link

Anybody tried this on dotnet 7 yet?

@BenjaminGopp
Copy link

Sadly still not working with dotnet 7. We have to wait at least another year..

@ZenoArrow
Copy link

This is some bulls**t. I'm tired of waiting for a fix for this, or even some kind of sign it's being worked on. At least some vendors know how to deal with production-critical software, I'd be better off switching to Java, at least then I could interop with C++ via GraalVM.

@marcpopMSFT
Copy link
Member

To clarify, is this an issue with publishing a wapproj or is it still a broader issue with dotnet publish of c# apps with native dependencies? If the former (which was a repro project attached to this issue), we've routed this to the correct team now. Wappproj support should go through devcom as that's where they manage their customer feedback. If the latter, please provide a small example repro we can follow up on.

@marcpopMSFT marcpopMSFT modified the milestones: 7.0.1xx, Discussion Dec 14, 2022
@ZenoArrow
Copy link

To clarify, is this an issue with publishing a wapproj or is it still a broader issue with dotnet publish of c# apps with native dependencies?

It's the latter, it's a broader issue with publishing C# apps with C++/CLI project dependencies.

As for reproduction of the issue, it's easy:

  1. In Visual Studio, create solution with one C# project and one C++/CLI project.
  2. Make the C++/CLI project a project dependency of the C# project.
  3. Attempt a self-contained publish of the C# project.

@BenjaminGopp
Copy link

My issue beeing:

  1. Create a C# project.
  2. Reference a nuget package that is a C++\CLI wrapper to a native lib.
  3. Publish to a single file exe (include native lib to its manifest)

@AHorak
Copy link

AHorak commented Jan 5, 2024

Problem still exists with .NET 8
The C++/CLi Part of the project results in a single DLL file, but the other parts of the project should be SelfContained

@JanssonTheBest
Copy link

JanssonTheBest commented Feb 17, 2024

I've successfully resolved the issue! Although the solution may have been discussed previously, I felt the explanations were not sufficiently clear, as well hard to find.

ATTENTION! (The essence of the solution involves programmatically extracting your DLL to a temporary folder at runtime. This note is for those who prefer to skip learning about such a solution.)

Solution:
To address the problem, you should first build the application without enabling the "single file" option. Next, locate and gather the DLL file of your target library. Following this, use any preferred software to obtain the raw bytes of the DLL.

During runtime, hardcode your project to literally extract the DLL into a temporary folder of your choice, I recommend using the system's standard temporary directory and applying a GUID to assign a unique name to the DLL.

Finally, employ .NET reflection to interact with the DLL that has been extracted, tip use visual studio to or dnspy to find the name of the various methods, types and more, that you will use from the dll.

I realize this approach might not seem ideal to everyone, but it's the most effective solution I've found.

I understand that this solution might be obvious to some people, nevertheless not to everyone thus I'm open to help "victims" of this issue further, if people are interested! Personally this problem has been bothering me a lot and I want to help everyone which is battling this issue :)

@bouchraRekhadda
Copy link

  • Publish from the command line, specifying the RuntimeIdentifier but not the SelfContained property. When a RuntimeIdentifier is set, then the app will default to self-contained. Here's a sample of how to do this:

🚧 @dsplaisted this is no longer true starting from .NET 8 : RuntimeIdentifier warning if self-contained is unspecified

@AMArostegui
Copy link

AMArostegui commented Jul 28, 2024

Same here. I have a solution, containing a C++/CLI project and I've run into this trying to publish a self-contained .NET 8 WinForms app. I'm on the latest Visual Studio.

@zhuman suggestion to use _CheckForLanguageAndFeatureCombinationSupport in my C++/CLI project, worked.

However, same as @damien78 I'm now blocked publishing my WAP project, to build an MSIX. I got the 'The runtime pack for Microsoft.NETCore.App.Runtime.win-x64 was not downloaded...' error I haven't been able to overcome.

@RevenantBob
Copy link

It's odd publishing from MSBuild works but publishing from Visual Studio does not with the same configuration. This error happens in Visual Studio but if I use an MSBuild project and target to publish, then everything works fine.

@bouchraRekhadda
Copy link

@zhuman suggestion to use _CheckForLanguageAndFeatureCombinationSupport in my C++/CLI project, worked.

@AMArostegui, did you have to enable the PackageReference (<EnableManagedPackageReferenceSupport>true</EnableManagedPackageReferenceSupport>) in your C++/CLI project to make this work ?
For me, overriding only these two targets isn't enough to publish a self-contained C# entry depending on C++/CLI

  <Target Name="_CheckForLanguageAndFeatureCombinationSupport"></Target>
  <Target Name="_CheckForLanguageAndPublishFeatureCombinationSupport"></Target>
C:\Program Files\dotnet\sdk\8.0.303\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Publish.targets(588,11): error MSB4057: The target "ResolveLockFileCopyLocalFiles" does not exist in the
project.

@damien78
Copy link

did you have to enable the PackageReference (<EnableManagedPackageReferenceSupport>true</EnableManagedPackageReferenceSupport>) in your C++/CLI project to make this work ? For me, overriding only these two targets isn't enough to publish a self-contained C# entry depending on C++/CLI

Thanks for this! This solved it for me, and I can now create the .appx package using the WAP project of my solution.
I've checked creating a new C++/CLI project, and this line is now present (as of MSVC 17.11.2).
@marcpopMSFT : This means the issue is now in the migration to .NET documentation. (e.g. https://learn.microsoft.com/en-us/dotnet/core/porting/cpp-cli)

BTW, I had no need for the following overriding:

  <Target Name="_CheckForLanguageAndFeatureCombinationSupport"></Target>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-NetSDK For consideration Used for items on the backlog to raise them to the top of that list for discussion
Projects
None yet
Development

No branches or pull requests