Digging deeper in .NET Core applications

Damir Dobric Posts

Next talks:

 

    

Follow me on Twitter: #ddobric



 

 

Archives

.NET Core supports two kinds of application: Portable and Self-Contained.
Portable applications are well known .NET applications. You build application and install it on some machine. If you want to run it, the required version of .NET framework must be installed.
Self-Contained applications do not need platform assemblies to run. You can install them on some machine and they will run, because they contain required framework assemblies as a part of application.

Portable Applications

Portable Applications are build with type: platform. (see below).

{
 
"version": "1.0.0-*"
,
 
"buildOptions"
: {

   
"emitEntryPoint": true

  },

 
"dependencies": {
   
"Microsoft.NETCore.App"
: {
     
"version": "1.0.1"
,
    
"type": "platform" // Means Portable Application

    },
   
"netcorelib": "1.0.0-*"
  },

 
"frameworks": {
   
"netcoreapp1.0"
: {
     
"imports": "dnxcore50"

    }
  },

 
}

When application is built this way, following output is produced.

image

The application is built in DLL named ‘netcoresample.dll’. This application references another netcorelib.dll library, which is here not interesting. If you see, application is built as DLL. If you start it from Visual Studio with F5, the application will be loaded as DLL in dotnet.exe process. All required assemblies are loaded from install location of .NET Framework as you see on the picture below. This is why your application depends on installed framework.

In debugging modules window, you will notice netcoresample.dll

image

In this case VS starts DOTNET.EXE as server (host) and loads the application DLL from working folder: 

"C:\Program Files\dotnet\dotnet.exe" projectmodel-server --port 60128 --host-pid 20116 --host-name aee7fc7e25c44b759b17af29e2834c8b

If we start application from command prompt with dotnet run, first dotnet.exe will be started with argument run.

image

This process will run another dotnet.exe with following arguments:

C:\Program Files\dotnet\dotnet.exe" exec --additionalprobingpath C:\Users\BLA\.nuget\packages C:\Temp\netcoresample\src\netcoresample\bin\Debug\netcoreapp1.0\netcoresample.dll

As you see, application is again run from DLL, by loading it into host process DOTNET.EXE as in a case of run from visual studio.

Self Contained Applications

If you want to build Self-Contained application, simply remove type from buildOptions. Note that this might look different in the future.
Unfortunately, when building (dotnet build) the application without type: platform you will get following error:

Can not find runtime target for framework '.NETCoreApp,Version=v1.0' compatible with one of the target runtimes: 'win10-x64, win81-x64, win8-x64, win7-x64'. Possible causes:
1. The project has not been restored or restore failed - run `dotnet restore`
2. The project does not list one of 'win10-x64, win81-x64, win8-x64, win7-x64' in the 'runtimes' section.
3. You may be trying to publish a library, which is not supported. Use `dotnet pack` to distribute libraries.

The problem in this case is that we have to specify at least one target runtime, which will be packaged with application.

{
 
"version": "1.0.0-*"
,
 
"buildOptions"
: {

   
"emitEntryPoint": true

  },

 
"dependencies": {
   
"Microsoft.NETCore.App"
: {
     
"version": "1.0.1"
,
      //
"type": "" Means Self-Contained Applications

    },
   
"netcorelib": "1.0.0-*"
  },

 
"frameworks": {
   
"netcoreapp1.0"
: {
     
"imports": "dnxcore50"

    }
  },

 
"runtimes": {
   
"win10-x64"
: {},
   
"osx.10.10-x64"
: {},
   
"ubuntu.14.04-x64"
: {}

  }
}

After application is built with this JSON you will see following output.

image

This is still not a Self-Contained application, but it is an application, which runs as executable and not as DLL if you start it directly.
If you navigate in the folder win10-x64 you will see following output:

image

To build application for different runtimes, do following:

dotnet build -r win10-x64
dotnet build -r osx.10.10-x64
dotnet build -r ubuntu.14.04-x64

When application is now started from Visual Studio, it will be again loaded as DLL from win10-x64. But if you start it with dbl-click on netcoresample.exe it will run as any other well known .NET application.

If you start it with dotnet run following command line is created internally to run the application:

Z:\netcoresample\bin\Debug\netcoreapp1.0\win10-x64\netcoresample.exe" --additionalprobingpath C:\Users\BLA\.nuget\packages

This is the result in Process Explorer:

image

To make your application self-contained you should execute following:

dotnet publish

or

dotnet publish -c release -r win10-x64
dotnet publish -c release -r osx.10.10-x64
dotnet publish -c release -r ubuntu.14.04-x64

After that a new folder will be created with name ‘publish’. This folder contains self-contained application.

image

If you navigate to that folder, you will see lot of assemblies, which your application requires to run. In red frame you see executable of application, but also the DLL.

image
You may wander, but your executable application ‘netcoresample.exe’ is not your application. It is a shim executable, which loads application from your DLL Smile.
If you open both assemblies in .NET Reflector you will see following:

image
Application is build in managed assembly netcoresample.dll and shim assembly netcoresample.exe is not a managed code.

If you delete netcoresample.dll and run netcoresample.exe, nothing will happen. Application will not start, because there is no application.

And finally, run application from file explorer by clicking on netcoresample.exe and then attach debugger to executable. Go to modules and you will see following:

image

Notice that this time, all assemblies are loaded from location of your application and not from .NET framework installation folder.


Posted Sep 28 2016, 12:24 AM by Damir Dobric
Filed under:
developers.de is a .Net Community Blog powered by daenet GmbH.