PublishSingleFile does not produce a single executable - c#

I have a .Net Core 3 console application that i'm trying to publish as a self contained single executable. I've been able to do this in the past but to my suprise it no longer works. The project structure is a console application with two assemblies, all in Core 3.
If i use dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true i expect the output to be a single executable of several mb's in size. However the publish folder contains the executable (few hundred kb) and a .dll file together with .cache files and the pdb.
The config for my console app is as follows:
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
<LangVersion>latest</LangVersion>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<Nullable>enable</Nullable>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PublishSingleFile>true</PublishSingleFile>
<PublishTrimmed>true</PublishTrimmed>
</PropertyGroup>
If i publish the app directly from Visual Studio i get the same results as above.
So my question boils down to: Why doesnt this configuration or publish statement result in a self contained single executable?

I can get my 3.1 console app to publish with the following:
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>..\..\Binaries\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<PublishSingleFile>True</PublishSingleFile>
<PublishReadyToRun>False</PublishReadyToRun>
<DebugType>None</DebugType>
</PropertyGroup>
</Project>
If I set PublishReadyToRun to True (or add PublishTrimmed as True) it fails. Adding DebugType None prevents it publishing the pdb file for the exe.
UPDATE: removing the SelfContained tag stops it creating the 'dotnetcoreapp3.1' folder.

According to the command line release, I tested successfully. A single executable file was generated. If you have always failed to publish, I suggest you use VS to publish.The publishing process is as follows:
1.Right click on the project->publish
2.Change configuration
3.Save the configuration and click Publish

Related

Create a .NET Core Nuget package to autogenerate c# classes

I have a .NET Framework project (A) which generates an exe which takes html file as input and outputs an autogenerated C# class file (like a template of sorts). The .csproj of A looks like this:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<OutputType>Exe</OutputType>
<AssemblyName>ProjectA</AssemblyName>
</PropertyGroup>
<ItemGroup>
<None Include="ProjectA.exe.config">
<ItemGroup>
</Project>
In project B, we're using the exe like this: (part of csproj of project B)
<Target Name="_EX_MyGenerateFile_cs" Inputs="MyHtml.html" Outputs="$(O)\MyGeneratedFile.cs" Condition="'$(BuildingOutOfProcess)' != 'False' AND '$(BuildingProject)' == 'True'" BeforeTargets="BeforeCompile">
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" LogStandardErrorAsError="true" Command="<path to projectA exe> MyHtml.html $(O)\MyGeneratedFile.cs" />
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" LogStandardErrorAsError="true" Command="if errorlevel 1 echo $(ERR_MSG) Unable to compile MyHtml.html to $(O)\MyGeneratedFile.cs" />
</Target>
Now, I wish to create a Nuget package (.NetCore) that achieves similar functionality as projectA (i.e somehow be able to consume this new package in a different netcore application and autogenerate the files- in a similar way projectB is able to use ProjectA's exe to generate the files). As I understand, .NET Core project would create a dll (not an exe); what is the way of using this dll to achieve what I want?
Any help is appreciated!
As .NET Core is a cross platform framework. This DLL file works across all platforms that are supported by the .NET Core runtime (Windows, Linux, and macOS). This is known as "framework dependent" deployment.
For your case there are 2 options :
To run any .dll of .NET Core application , command dotnet yourProject.dll is used.
Part of projectB.csproj will look like this:
<Target Name="_EX_MyGenerateFile_cs" Inputs="MyHtml.html" Outputs="$(O)\MyGeneratedFile.cs" Condition="'$(BuildingOutOfProcess)' != 'False' AND '$(BuildingProject)' == 'True'" BeforeTargets="BeforeCompile">
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" LogStandardErrorAsError="true" Command="dotnet <path to projectA dll> MyHtml.html $(O)\MyGeneratedFile.cs" />
<Exec WorkingDirectory="$(MSBuildProjectDirectory)" LogStandardErrorAsError="true" Command="if errorlevel 1 echo $(ERR_MSG) Unable to compile MyHtml.html to $(O)\MyGeneratedFile.cs" />
</Target>
If you really want exe file, generate exe file using a Self-Contained deployment.
This will create an output that contains its own copy of the .NET Core runtime and an yourProject.exe file.
Con of this approach:
It increases the size of the published application.
It needs to be updated when new versions of the runtime are released.
The resulting application only works on the published operating system published.

"Index was outside the bounds of the array" error while publishing a .NET Web application

I have a simple .NET Web application that works fine when I run it on my local machine. However, when I try to publish the application to a local folder, I see the error that says "Index was outside the bounds of the array." This error, I'm afraid, is very vague and I am not able to figure out what the issue is.
I am creating this project on Visual Studio community 2019.
Can someone please help me figure out what the issue is :)
I do not know the issue or solution for this, but here is a workaround I used.
Essentially, you will need to create the publish folder and file profiles manually.
I did this for a .NET Core 3.1 Blazor project
Step 1 - In your project, go to the Properties folder where you should find your launchSettings.json
Step 2 - Inside, create a folder and name it "PublishProfiles"
Step 3 - Inside of the PublishProfiles folder, create a file and name it "FolderProfile.pubxml"
Step 4 - Inside of this file, paste this code and add the location path to the folder you which to publish:
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<DeleteExistingFiles>True</DeleteExistingFiles>
<ExcludeApp_Data>False</ExcludeApp_Data>
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>Your location path where you want to publish your application</PublishUrl>
<WebPublishMethod>FileSystem</WebPublishMethod>
<SiteUrlToLaunchAfterPublish />
<TargetFramework>netcoreapp3.1</TargetFramework>
<ProjectGuid>08d93ba4-c83c-47e9-a83e-73f12d97626a</ProjectGuid>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>
Step 5 - Create another file and name it "FolderProfile.pubxml.user" and paste this code inside. Again, insert the path to your desired folder:
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<_PublishTargetUrl>Your location path where you want to publish your application</_PublishTargetUrl>
<History>True|2021-07-02T16:47:41.7255934Z;True|2021-07-02T12:44:24.1064885-04:00;True|2021-05-21T09:22:02.2383330-04:00;True|2021-05-20T17:42:40.0758569-04:00;True|2021-05-20T09:45:45.4390896-04:00;True|2021-05-20T09:02:32.8340404-04:00;</History>
</PropertyGroup>
</Project>
Step 6 - After this, you should be able to right click your project in Visual Studio, click the option Publish... and the screen with the Publish button should be visible.
It's just a workaround but works.
Use Release instead of Debug in Solution Configuration options at the top of Visual Studio and copy the generated file from "bin\Release" folder to your destination "Publish" folder.

dotnet publish profile ignores pubxml file

I have the following pubxml file which I created via Visual Studio 2019:
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<WebPublishMethod>FileSystem</WebPublishMethod>
<PublishProvider>FileSystem</PublishProvider>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<SiteUrlToLaunchAfterPublish />
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
<ExcludeApp_Data>False</ExcludeApp_Data>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<ProjectGuid>143a6329-27d9-474e-9521-835be634c293</ProjectGuid>
<SelfContained>true</SelfContained>
<publishUrl>bin\Release\netcoreapp3.1\publish\</publishUrl>
<DeleteExistingFiles>True</DeleteExistingFiles>
</PropertyGroup>
</Project>
When I run dotnet.exe publish src\MyProject.Web.sln -p:PublishProfile=Properties\PublishProfiles\ProductionPublish.pubxml Release does not contain anything and publish happens on Debug folder (debug build). Whys does this happens and pubxml is ignored?
Update #1
Structure
src\MyProject\MyProject.csproj
src\MyProject.Utils\ect.Utils.csproj
src\MyProject.Web\MyProject.Web.csproj
src\MyProject.Web.sln
and the path of the pubxml
src\MyProject.Web\Properties\PublishProfiles\ProductionPublish.pubxml
You need the use following command:
dotnet build -c Release /p:DeployOnBuild=true /p:PublishProfile=FolderProfile
It's build, not publish.
Even if my FolderProfile's configuration is set to Release, I had to
include -c Release because otherwise dependent projects were built
with debug configuration.
Files not copied to target location if called without /p:DeployOnBuild=true.
Just the name FolderProfile -without extension- is enough for the
profile file. Or you can give the path
/p:PublishProfile=Properties\PublishProfiles\FolderProfile.pubxml
See Folder publish example from Microsoft Docs.
Found a solution on VS2022 and Core 6 to publish to an specific folder without indicating the output path on the CLI.
I created a profile called IISC
If you open that publish profile, you will see the PublishUrl property as follows
<PublishUrl>bin\Release\net6.0\publish\IISC</PublishUrl>
In My case I'm publishing to the solution folder bin\releas....\IISC
The trick is to add another propery called PublishDir
<PublishDir>bin\Release\net6.0\publish\IISC</PublishDir>
Now you can publish with this:
dotnet publish -c Release /p:PublishProfile=IISC
Find Bellow My complete Profile with and addition of an environment variable specific for this profile and and item group to exclude all the appsettings except for appsettings.json and appsettings.IISC.json
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<ASPNETCORE_ENVIRONMENT>iisc</ASPNETCORE_ENVIRONMENT>
<DeleteExistingFiles>true</DeleteExistingFiles>
<ExcludeApp_Data>false</ExcludeApp_Data>
<LaunchSiteAfterPublish>true</LaunchSiteAfterPublish>
<LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
<LastUsedPlatform>Any CPU</LastUsedPlatform>
<PublishProvider>FileSystem</PublishProvider>
<PublishUrl>bin\Release\net6.0\publish\IISC</PublishUrl>
<PublishDir>bin\Release\net6.0\publish\IISC</PublishDir>
<WebPublishMethod>FileSystem</WebPublishMethod>
<SiteUrlToLaunchAfterPublish />
<TargetFramework>net6.0</TargetFramework>
<ProjectGuid>3e4c25a6-2051-4ccc-a518-645d46d120dd</ProjectGuid>
<SelfContained>false</SelfContained>
</PropertyGroup>
<ItemGroup>
<Content Update="appsettings.*.json">
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
</Content>
<Content Update="appsettings.$(ASPNETCORE_ENVIRONMENT).json">
<CopyToPublishDirectory>Always</CopyToPublishDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<Folder Include="Properties\PublishProfiles\" />
</ItemGroup>
</Project>
I'm gonna answer for those who, like me, do want to use the publish command, because it's been designed to do so.
According to Options section on publish command, you can use the options configuration and output to solve your problem:
dotnet publish -c Release -o "<where you want>" -p:PublishProfile=<your profile name>
Note that where you want can be an absolute path and your profile name is only the name of profile, without "pubxml" and without the relative path (IF AND ONLY IF the profile is in "<project_folder>/Properties/PublishProfiles").

C# Program doesn't work on other computer

I have made an application that connects to a server and listens to certain packets, I used Nuget network library for that. Here is my .csproj file:
<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>remote_client</RootNamespace>
<Platforms>AnyCPU;x64</Platforms>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<StartupObject>remote_client.client</StartupObject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Network" Version="6.1.4.20" />
<PackageReference Include="System.Management.Automation" Version="7.0.0" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
</Project>
Then I had problem how to compile it into a single .exe file. I found a command I used in powershell (I ran it in project's directory):
dotnet publish -r win-x64 -c Release /p:PublishSingleFile=true /p:PublishTrimmed=true
And then I had a single file I could use anywhere on my computer.
When I tried to give it to my friend, it wouldn't work with error from Windows (my translation): Can't run this application. Ask program's developer to do something...
My windows version is 1909 and his is 1809.
So summarizing, I need to fix the issue or get some easy way to publish a application and compile it into a windows-universal single .exe file.
EDIT: actual error message is:
This application will not work on your computer. To find the version for this computer, contact the software publisher.
First sentence is caption of the popup message box, second sentence is being displayed as message.
My bad, I think that it couldn't work because the computer my friend ran the application on was 32 bit but I compiled it for 64 bit.

How to consume a dotnet console application from a Nuget package?

The scenario is as follows:
a) An arbitrary MyProject.csproj invokes MyConsoleApp.exe as part of a post build event.
b) MyConsoleApp.exe is packaged and consumed via Nuget with all its dependencies
I am not convinced this is the "dotnet core 2.0" way of doing things, I tried dotnet pack MyConsoleApp.csproj but that doesn't include the dependencies like the .exe file does. Should it include all references in a nupkg and publish the package at build time?
MyProject.csproj
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>
...
<Target Name="GenerateSomeFiles" BeforeTargets="AfterBuild">
<Exec Command="dotnet run MyConsoleApp.dll $(TargetDir)" />
</Target>
</Project>
You should try running dotnet publish, then running dotnet pack against the publish folder that's created under bin/Release or bin/Debug.
If you still want an exe, you should either setup a target Runtime for x86/x64 in your csproj, or setup multi-targeting for a full framework version.

Categories

Resources