.NET 4.8 not creating a self-contained file for Linux - c#

I have a a little .NET Core console application that I would like to make a self-contained file of. Not only that, I would also like to create a self-contained file that will run on CentOS.
The issue I am having is when I run dotnet publish -r linux-x64 -c release --self-contained true I get multiple files and the files seem to be configured for Windows only. I also tried removing <OutputType>Exe</OutputType>. This makes sure there isn't any EXE file file when publishing, but I still get multiple files that I am not sure if they can even run on CentOS since they are only .dll files. My target framework is set to <TargetFramework>net4.8</TargetFramework>.
Here are some visuals of the output I am getting:
Having <OutputType>Exe</OutputType> set in my .csproj:
Having <OutputType>Exe</OutputType> removed:

As pointed out by Jonathon Chase and Herohtar, I targeted the wrong framework. The framework I used (net4.8) is Windows only.
The correct framework to use would be something like netcoreapp3.0.

Related

.NET Core 6.0 standalone binary compilation

I'm trying to create a .NET Core 6.0 binary as a standalone, with all dependencies packaged in one .exe file.
The trouble I am having is that whilst the binary compiles ok it is reliant on the DLLs placed in the Release/Debug folder.
I have tried compiling from the command line with
dotnet publish --standalone
but in that instance I just get a similar issue with a load more DLLs and the binary itself is the same size and needs to be in that folder to run.
Is what I'm looking for even possible and if so how can this be achieved? I have tried with Visual Studio, dotnet cli and Rider so far.
There are a number of old solutions that mention solutions such as ilmerge but this appears to have been long since deprecated and is no longer maintained.
-- EDIT for future me:
Final solution looked like this, thanks to Andrew's answer below.
My final project.csproj file looked like this based on MS Docs
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishSingleFile>true</PublishSingleFile>
<EnableCompressionInSingleFile>true</EnableCompressionInSingleFile>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
Publish either via Visual Studio GUI or:
dotnet publish -c release -r win-x64
I'd suggest looking at https://learn.microsoft.com/en-us/dotnet/core/deploying/single-file which should hopefully be up to date. I believe the key bit is <PublishSingleFile>true</PublishSingleFile> in the .csproj.

How to run .NET core application by double clicking a file like exe in .NET framework

In .NET framework when we build our solution/project, we get an exe in the debug/release folder and we can run our application by double clicking that exe. But how can we do this in .NET core, i know we can't have an exe in .NET core because it is windows specific. When i build my .NET core application i get the following files in the debug folder.
I know how to run this application using command prompt but i want to have a file like exe by clicking which i can run my application.
You can generate exe (self-contained application).
.NET Core 2.0 +
Open Package Manager Console or any other console in your project directory and type:
dotnet publish -c Release -r win10-x64
dotnet publish -c Release -r ubuntu.16.10-x64
When you use previous version of .NET Core you have to add runtime identifier of the target environment in csproj:
<PropertyGroup>
<RuntimeIdentifiers>win10-x64;ubuntu.16.10-x64</RuntimeIdentifiers>
</PropertyGroup>
Runtime Identifiers (RIDs) list:
https://learn.microsoft.com/en-us/dotnet/core/rid-catalog
One simple solution is to create a .bat file with runs the dll via the dotnet cli, then you get "a file like exe"
dotnet ConsoleApp2.dll

How to publish only required dependencies?

If I create a "Hello World" .NET Core C# Console application in Visual Studio 2017 and run
dotnet publish -c Release -r win10-x64 --self-contained
The resulting publish folder has 215 files in it, totals 62MB and includes the whole of .NET, which the application doesn't use. For example, it has System.Security.Cryptography.OpenSsl.dll.
This is part of the "Microsoft.NETCore.App" dependency which I seem to have no way to edit manually. How can I trim that down to what the application is actually using?
Per the deployment documentation:
Unlike FDD, a self-contained deployment (SCD) doesn't rely on the presence of shared components on the target system. All components, including both the .NET Core libraries and the .NET Core runtime, are included with the application
(emphasis mine)
If you don't want to deploy the whole .NET Core runtime along with your application, then you should use a Framework-dependent Deployment (FDD) instead of a Self-contained Deployment (SCD).
dotnet publish -c Release
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.
Reference: Is there a way to make a console application run using only a single file in .NET Core?
There is a 3rd option as well: "Framework-dependent executables (FDE)"
You need to use --self-contained false e.g.:
dotnet publish <xyz.csproj> -c Release -r win-x64 --self-contained false
The 'Publish' folder still contains some Microsoft.*.dlls. However way less. In my case previous publish was folder size was 84MB now it is 12MB only!

Is there a way to make a console application run using only a single file in .NET Core?

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"...
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.
Tested with .NET Core 2.2 on a console app:
Reference Microsoft.DotNet.ILCompiler package in your output project. You'll need to add MyGet package repository in Visual Studio settings. *
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.
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
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

Setup exe file version when publishing with dotnet

I have a net core consoleapp project, as follows (VS 2017 style):
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
<Version>2.0.0</Version>
<AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>4.0.0.0</FileVersion>
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
<RuntimeFrameworkVersion>1.0.4</RuntimeFrameworkVersion>
</PropertyGroup>
</Project>
I can build the project without any issues, I can publish it using dotnet publish -r win10-x64 and it will generate an exe file together with the dll file. My problem is that the exe file has some strange FileVersion and ProductVersion fields (in my case FileVersion = 1.0.1.4500 and ProductVersion 1.0.1.cee57... (some guid)). Also the rest of the file details (name, copyrights) are related to dotnet instead of my own project.
Is there any way I can control the exe details when publishing?
No, the main build output of your project still is a .dll file, the .exe (or linux, mac executables) file is a copied and renamed dotnet.exe (or in case of upcoming 2.0 versions, apphost.exe with the dll name to run embedded).
The exe file is only a helper that boots the runtime and then loads your dll. However, you can try to use binary editing tools like editbin.exe (VS C++ Tools) to modify the file after publishing.
Dotnet core 3.0 added the functionality of versioning the shim exe during publish, like OP was expecting. It should work out of the box now. However that feature does not function if running builds on a Nanoserver based docker environment.
warning NETSDK1074: The application host executable will not be
customized because adding resources requires that the build be
performed on Windows (excluding Nano Server)

Categories