22

In .NET framework, you can make a single .EXE file that will run from the command line without having any extra config files (and if using ILMerge, you can put all .DLL references into the 1 .EXE assembly).

I am taking a stab at using .NET Core to accomplish the same thing, but so far without success. Even the simplest Hello World application with no dependencies requires there to be a file named <MyApp>.runtimeconfig.json in order to run using dotnet.exe.

dotnet F:\temp\MyApp.dll

The contents of the <MyApp>.runtimeconfig.json are as follows:

{
  "runtimeOptions": {
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "1.1.1"
    }
  }
}

Without this config file in the same folder as the .DLL, I get the following error:

A fatal error was encountered. The library 'hostpolicy.dll' required to
execute the application was not found in 'F:\temp'.

My question is: Is there some way to change the application so it doesn't require this config file to be present, so that the defaults of this information are compiled within the .DLL but can be overridden by adding the config file?

NOTE: I also want to ensure it "just works" regardless of the platform it is installed on it provided the platform has the right version of .NET Core.

Background

I am trying to get a smooth user experience for running some utilities that are useful sometimes, but are rarely ever needed. Since it doesn't appear to be possible to use the same .DLL that is referenced from a client application as a console application, the next best thing would be to have a single file that could be downloaded and run without any dependencies.

For example, in Java you can simply download a .jar file on any supported platform and run:

java <package>.jar <namespace>.SomeClass [args]

and it will "just work" without any extra files. How can I get a similar user experience using .NET Core?

In a nutshell, I want to try to avoid the extra step of "unzip to a directory first"...

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • Do you need to produce an DLL, or would an EXE work for your case? – Shaun Luttin Jun 30 '17 at 01:19
  • 3
    Given the fact that [making an `.EXE`](https://learn.microsoft.com/en-us/dotnet/core/deploying/deploy-with-vs#a-namesimpleselfa-self-contained-deployment-without-third-party-dependencies) means I have to build and maintain a file for [each supported platform](https://learn.microsoft.com/en-us/dotnet/core/rid-catalog), I would definitely prefer using a `.DLL`. 1 binary that works on any platform (provided the .NET Core version is installed) is a lot less to maintain. – NightOwl888 Jun 30 '17 at 08:35

3 Answers3

16

Update 2018: .NET Core 3.0 aims to enable a new scenario: packing the .NET Core runtime and all application dependencies into a single executable.

At the moment, there are no fail-safe methods to create a single executable file. Since there are a lot of type-forwarding dll files involved, even ILMerge and similar tools might not produce correct results (though this might improve, the problem is that those scenarios haven't undergone extensive testing, esp. in production applications)

There are currently two ways to deploy a .NET Core application:

  • As a "portable application" / "framework-dependent application", requiring a dotnet executable and installed framework on the target machine. Here, the XYZ.runtimeconfig.json is used to determine the framework version to use and also specifies runtime parameters. This deployment model allows running the same code on various platforms (windows, linux, mac)
  • As a "self-contained application": Here the entire runtime is included in the published output and an executable is generated (e.g. yourapp.exe). This output is specific to a platform (set via a runtime identifier) and can only be run on the targeted operating system. However, the produced executable is only a small shim that boots the runtime and loads the app's main dll file. This also allows an XYZ.runtimeconfig.json to set additional runtime properties like garbage collection settings.(think of it as a "new" app.config file)

In the future, the CoreRT runtime – which is still under development at the time of writing – aims to allow creating a single pre-compiled native executable that is specific to a runtime and does not require any other files.

Martin Ullrich
  • 94,744
  • 25
  • 252
  • 217
  • 1
    For the .NET Core 3.0 solution, see my answer where I explain it in detail, I just finished my first live deployment using that solution. – Marcell Toth May 11 '19 at 18:45
6

Tested with .NET Core 2.2 on a console app:

  1. Reference Microsoft.DotNet.ILCompiler package in your output project. You'll need to add MyGet package repository in Visual Studio settings. *
  2. Publish the project via command line, dotnet publish C:\src\App\App.csproj -c release -r win-x64 -o output-win-x64. If there's no "Desktop Development for C++" component installed, do it in Visual Studio Installer, or the command will fail.
  3. Go to the output folder (e.g. "C:\src\App\output-win-x64") and grab the native image (.exe file).

On Windows it produced a fully functional 5Mb .exe file (compared to original self-contained publish with folder size at ~60Mb). On macOS the ILComplier though produced output without any error, the app crashed with unhandled expection (on the line with LINQ expression).

*Go to "Tools -> Options -> Package Manager -> Package Sources" and add new source at https://dotnet.myget.org/F/dotnet-core/api/v3/index.json

Maxim Saplin
  • 4,115
  • 38
  • 29
5

It is possible in .NET Core 3.0+

The feature is enabled by the usage of the following property in your project file (.csproj):

<PropertyGroup>
    <PublishSingleFile>true</PublishSingleFile>
</PropertyGroup>

There are other options as well, such as packaging the pdb into the bundle, or leaving certain files out.

Documentation can be found here: https://learn.microsoft.com/en-us/dotnet/core/deploying/#publish-self-contained

True it just works:

Combine this technique with the Self Contained Deployment workflow, you can get a true "it just works" experience for your user, they don't even have to install the .NET Core runtime for your app to run.

I am currently deploying applications to my clients as single .exe files.

Read more about that here: https://learn.microsoft.com/en-us/dotnet/core/deploying/#self-contained-deployments-scd

Marcell Toth
  • 3,433
  • 1
  • 21
  • 36