22

I have a .NET Core 2.0 console app. I can successfully build or publish this app and run it locally. I can also successfully build and publish this app in Azure DevOps. However, if I build the app in Azure DevOps, I cannot run the result.

In Azure DevOps, I tried building using:

dotnet build -c Release -r win-x64 -o app

This generates a small number of files with just the project related files. It does not include all of the System.*.dll files, etc that seem excessive for most of my cases. This command works fine when I run it on my local machine and I can successfully click the MyApp.exe file and run my console app. However, if I run the same command on Azure DevOps, the MyApp.exe file that gets generated does not run as expected. Instead, it starts then immediately quits. Nothing is printed in the console app. I see no errors. The app is very basic, includes a "try-catch" around everything and has a Console.ReadLine at the end. So, I thought it would stay open.

When I run:

dotnet publish -c Release -r win-x64 -o app

I get the same files, but with all of the System.*.dll files, etc. included. This time, I've noticed that I can successfully run MyApp.exe and it behaves as expected.

Why does dotnet build ... work locally, but I don't seem to get the same behavior when I run dotnet build ... in Azure DevOps. It seems I'm forced to use dotnet publish. My issue is, the resulting .zip file goes from ~500kb to 30MB. This is big difference.

user687554
  • 8,165
  • 22
  • 64
  • 119

2 Answers2

25

An answer from the horse's mouth:

The dotnet build command builds the project and its dependencies into a set of binaries. The binaries include the project's code in Intermediate Language (IL) files with a .dll extension and symbol files used for debugging with a .pdb extension. A dependencies JSON file (*.deps.json) is produced that lists the dependencies of the application. A *.runtimeconfig.json file is produced, which specifies the shared runtime and its version for the application.

If the project has third-party dependencies, such as libraries from NuGet, they're resolved from the NuGet cache and aren't available with the project's built output. With that in mind, the product of dotnet build isn't ready to be transferred to another machine to run.

dotnet build - Builds a project and all of its dependencies.

dotnet publish - Packs the application and its dependencies into a folder for deployment to a hosting system. (PS - this also builds the application before packing)

The description is actually very good considering it's coming directly from Microsoft so I will not duplicate the words here.

As an exercise create a solution with multiple projects. For one of the projects add a reference to another project. Add some static files which your code references and a few NuGet packages. And run these commands at the solution root level and at the project level and observe the output in the bin folder.

Commands to run: dotnet build dotnet publish

dotnet clean to clean the bin folder

Also, run this at the root level and observe the output with the self-contained flag enabled:

dotnet publish -o ./output --runtime win10-x64 --self-contained

More info on self-contained builds

Shayan C
  • 1,080
  • 1
  • 10
  • 21
8

The different between them is that:

For publish, the necessary assembly files (packages) will be included in build folder and the app uses these assemblies.

But for build, the app references packages that are in the user’s folder. That’s why the zip file just 500 kb.

Since it references packages that are in the user’s folder, so the app needs to be built under the same user’s account, then you can run the app without publishing. So, you need to change build agent’s service account to your account (log on as), then restart the service and queue a new build.

Otherwise, you need to publish the app.

Ognyan Dimitrov
  • 5,392
  • 1
  • 40
  • 64
starian chen-MSFT
  • 31,056
  • 2
  • 22
  • 47
  • 3
    Thank you for your response. However, I don't fully understand this. Let's imagine I have two separate computers that have .NET Core 2.1 already installed. Now, let's say I build my code using `dotnet build` on computer A. Then, I copy the generated files in the `bin\Release\netcoreapp2.1` directory to computer B. Am I hearing that I won't be able to run those files there? The only way to run the app on computer B is by first running `dotnet publish` and including all of the files every time? – user687554 Sep 17 '18 at 12:23
  • 4
    @user687554 The idea is that a published application is **self-contained** -- it has *all* the necessary references to run, and depends on *nothing* being pre-existing on the machine it's running on. – Daniel Mann Sep 17 '18 at 18:01
  • 4
    @DanielMann - That makes sense. However, there are cases where machines will already have .NET Core 2.1 installed. In these cases, `publish` seems excessive, but `build` doesn't seem to work. What am I missing here? It seems like I should be able to deploy a .NET Core 2.1 console app to a machine that already has .NET Core 2.1 installed without using `publish`. Or am I wrong? – user687554 Sep 18 '18 at 11:59