26

My setup is: I have a solution that had different dotnet4.6 applications (services) in it. Now we added a dotnet core project inside this solution. I can build and debug it, but this doesn't create an executable. In Visual Studio I can rightclick -> Publish... it. I created two profiles (x86 and x64) that should create nice binaries in /bin/Publish/x86 or /x64. In VS this works. The application is self-contained and works on different unprepared machines.

But now I Need to move that process to the buildserver. I messed around with dotnet publish but in the end i get stuck because other components of the solution are not clean dotnet core and so the build fails. So I need to stick with MSBuild.

The current attempt is: "C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\15.0\Bin\MSBuild.exe" NewProject\NewProject.csproj /p:DeployOnBuild=true /p:UsePublishProfile=true /p:PublishProfile=x64Profile.

This says it finished building successfully, but I don't see any results. Also it doesn't make any difference, if I remove all properties and just call msbuild and *.csproj. It just builds the new project in bin/Debug, as dll, not exe.

I also messed around with p:PublishProfile="NewProject\Properties\PublishProfiles\x64Profile.pubxml" and /p:PublishUrl="NewProject\bin\Publish\x64" but it doesn't change anything.

I read a few articles on SO, telling that VS doesn't just call msbuild with parameters but does internal API calls. Still, I need a solution. I need the build server to create an executable. Is there a way to trigger msbuild to create thath?

ecth
  • 1,215
  • 1
  • 16
  • 33

2 Answers2

28

Oh man, I searched for 2-3 days now. And - as always on StackOverflow - shortly after asking I found a working answer myself.

tl;dr:

Project.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>netcoreapp2.1</TargetFrameworks>
    <TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>  
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
    <RootNamespace>Company.Toolset.Exporter</RootNamespace>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
    <RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
  </PropertyGroup>
  
  <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" />
...

MSBuild command:

msbuild Project\Project.csproj -t:restore /t:Build;Publish /p:Configuration=Release /p:Platform=x86 /p:PublishProfile=x86Profile /p:OutputPath=bin/Publish/x86 (and the same for x64)

Explanation:

I think it was the dotnet build/publish command that wanted me to change TargetFrameworks to TargetFramework. But for MSBuild this is wrong. And dotnet wasn't working here, as the solution is mixing dotnet core and dotnet framework. So that had to be fixed.

The <RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers> was needed by the command. I added it to the *.csproj because I know that I build for windows only (at the moment) and that I need both versions.

I don't really know why I needed this line <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0\WebApplications\Microsoft.WebApplication.targets" /> but without this publishing and using the PublishProfiles didn't work as expected.

Links that helped me to get here: (not sorted)

https://github.com/Microsoft/msbuild/issues/1901

https://github.com/aspnet/vsweb-publish/issues/22

How to Publish Web with msbuild?

ASP.NET Core Application (.NET Framework) for Windows x64 only error in project.assets.json

Configure MSBuild output path

ecth
  • 1,215
  • 1
  • 16
  • 33
  • 1
    Just my intuition here, but if you use `` instead of using the library SDK does that simplify your csproj? – TheXenocide Apr 07 '20 at 23:23
  • The first line of this project file is problematic like the other comment indicated. You should not modify it to use `Microsoft.WebApplication.targets` either, as that's a typical step for ASP.NET 4.x projects. This can be a misleading answer, as ASP.NET and ASP.NET Core projects should be treated differently and without so many hacks. – Lex Li May 03 '20 at 23:38
15

I too had a nightmare with inconsistencies between builds from Visual Studio IDE and the dotnet publish command, that were only fixed by doing it using msbuild.exe instead. Also, using /p:PublishProfiles=theXMLthatVSgenerates.xml never worked, so I had to break out every option into the msbuild command line.

Here's what worked for me:

"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\msbuild.exe" C:\Users\xxxx\Source\Repos\netcore-agent1\CoreAgent1\CoreAgent1.csproj /t:Restore;Rebuild;Publish /p:PublishSingleFile=True /p:SelfContained=True /p:PublishProtocol=FileSystem /p:Configuration=Release /p:Platform=x64 /p:TargetFrameworks=netcoreapp3.1 /p:PublishDir=bin\Release\netcoreapp3.1\publish\win-x64 /p:RuntimeIdentifier=win-x64 /p:PublishReadyToRun=False /p:PublishTrimmed=False
Jon R
  • 836
  • 11
  • 9
  • 3
    Been looking for this solution for a few days now - Seems that "dotnet publish" does not do the same as publishing from visual studio. This solved my problem - Thanks alot! – Rasmus Søborg Jun 28 '21 at 22:52
  • 5
    Solved my issue. It is important to point out, that when using the "/p:SelfContained=True " also the RuntimeIdentifier has to be set. Example: "/p:RuntimeIdentifier=win-x64" // And yes, you had it already in your list of options. – Christian Müller Aug 05 '21 at 17:08
  • Haha so true - Msbuild seems to ignore PublishProfiles parameter and carry on doing its own thing - not sure what's wrong but outside of VS it does NOT work as advertised. – torgabor Mar 11 '22 at 17:50