3
votes

I am trying out Visual Studio 2017 and .NET Core in what is my first attempt at C#/.NET in a few years (returning from Golang). I tried to create a small hello world style networking application that just listens and echos the input from tcp clients:

using System;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Text;

namespace TaskSockets
{
    class Program
    {

        static void Main(string[] args)
        {
            Console.WriteLine("Hello World!");

            TcpListener server = new TcpListener(IPAddress.Any, 5555);
            server.Start();

            while (true)
            {
                TcpClient newClient = server.AcceptTcpClientAsync().Result;

                Task.Run(async () => {

                    StreamWriter sWriter = new StreamWriter(newClient.GetStream(), Encoding.ASCII);
                    StreamReader sReader = new StreamReader(newClient.GetStream(), Encoding.ASCII);

                    Boolean bClientConnected = true;
                    String sData = null;

                    while (bClientConnected)
                    {
                        sData = await sReader.ReadLineAsync();

                        Console.WriteLine("Client: " + sData);
                    }
                });
            }

        }
    }
}

My project/build config looks like the following:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netstandard1.6</TargetFramework>
    <RuntimeIdentifiers>win7-x64</RuntimeIdentifiers>
  </PropertyGroup>
  <ItemGroup>
     <PackageReference Include="Microsoft.NETCore.Runtime.CoreCLR" Version="1.1.1" />
     <PackageReference Include="Microsoft.NETCore.DotNetHostPolicy" Version="1.1.0" />
   </ItemGroup>

</Project>

After publishing the application (dotnet publish) I get a folder with the executable I need. The problem I encounter, however, is that the folder contains 205 files (mostly .NET related DLL files) and is more than 30 MB in size. This includes dll files with reference to .NET libraries I don't even use such as System.Xml and Linq.

Is there any way to reduce the number of files and size of the published application so that just what I need is included?

UPDATE: Tried to re-create the project from scratch using the dotnet tool rather than visual studio:

dotnet new console --language C# --name Socket --output Socket --framework netcoreapp1.0

This created this project (which for some reason compiles to a dll despite the exe output type and console application target):

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.0</TargetFramework>
  </PropertyGroup>
</Project>

Then manually modify the csproj file so it looks like this:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.0</TargetFramework>
    <RuntimeIdentifiers>win7-x64</RuntimeIdentifiers>
  </PropertyGroup>
  <ItemGroup>
     <PackageReference Include="Microsoft.NETCore.Runtime.CoreCLR" Version="1.0.6" />
   </ItemGroup>
</Project>

Now publish with:

dotnet publish --runtime win7-x64 --configuration Release

And go to:

./bin/Release/netcoreapp1.0/win7-x64

Now suddenly there is a working exe-file and just a few DLL files that is approximately 1 MB in size. By deleting the subfolder called "publish" I now have something that works without most of the bloat. No idea why this worked and if its considered expected behavior. No idea what the publish folder is for either or whether or not its needed for deployment on a computer without .NET installed. Microsoft have some work to do on its documentation.

1
Use .NET Framework and not .NET Core unless you want it to work cross-platform. Otherwise, just remove unused references within your project.ThePerplexedOne
@ThePerplexedOne I need cross-platform; is there any way to get the dotnet tool to discard or somehow identify which references are not actually needed? Sound a bit scary to just start deleting DLL's at random and hope everything works afterwards.agnsaft
Use ReSharper. It's an amazing tool for tidying up code. It also identifies unused references/namespaces.ThePerplexedOne
Is it not just the dependencies for kestrel which .net core uses?BigTallJosh
This code should not depend on kestrel imhoagnsaft

1 Answers

2
votes

Have a look at https://docs.microsoft.com/en-us/dotnet/articles/core/deploying/index

In the 1st case, your publish command generates output for a Framework-dependent deployment that is relying on the presence of the .NET Core framework on the target machine. Your code (in the form of dll(s)) will be executed by the runtime.

In the 2nd case, when you specify the target runtime using the --runtime option, publish generates output for a Self-contained deployment in which the used version of the .NET Core framework is included. There's a way to reduce the total size of the output as described in the above mention article in the Deploying a self-contained deployment with a smaller footprintsection.

As for why <OutputType>Exe</OutputType> didn't generate a exe-file, check out https://docs.microsoft.com/en-us/dotnet/articles/core/tools/dotnet-build

It basically says the generated

binaries include the project's code in Intermediate Language (IL) files with a .dll extension

and that the difference between specifying and not specifying <OutputType>Exe</OutputType>

is that the IL DLL for a library doesn't contain entry points and can't be executed.