dotnet / sdk

Core functionality needed to create .NET Core projects, that is shared between Visual Studio and CLI
https://dot.net/core
MIT License
2.71k stars 1.06k forks source link

dotnet new console, publish, makes a dll not an exe #8065

Closed danmoseley closed 4 years ago

danmoseley commented 7 years ago
C:\PLAy\asdf>dotnet --version
2.0.0-preview1-005694

C:\PLAy\asdf>dotnet new console
The template "Console Application" was created successfully.

C:\PLAy\asdf>dotnet restore

...
C:\PLAy\asdf>dotnet run
Hello World!

C:\PLAy\asdf>dotnet publish
Microsoft (R) Build Engine version 15.2.47.30403
Copyright (C) Microsoft Corporation. All rights reserved.

  asdf -> C:\PLAy\asdf\bin\Debug\netcoreapp2.0\asdf.dll

Shouldn't I have a console .exe? How do I run this dll?

plasticalligator commented 6 years ago

I just want to add my two cents to this issue so that the dev team understands how I feel: hhhhhhhhhhngggghhhhasdffffffffaaaaaaagfgnggggggggggghhhhhhhhhhhhhhhhgnnnnnnnghhhhhhhhhhhhhhhhhhhhh

A9G-Data-Droid commented 6 years ago

Following the documentation for making a SCD leads to just a DLL for console app. I see people complaining about having a to deploy a DLL with their EXE but I can't even get that. This process is broken and unclear.

https://docs.microsoft.com/en-us/dotnet/core/deploying/deploy-with-vs

livarcocc commented 6 years ago

Where are you looking at that you see only the dll? Note that in .net core, the build output is different from the publish output, if you are publishing your app and trying to distribute it, you should look at the publish folder.

A9G-Data-Droid commented 6 years ago

Yeah, I definitely looking at the publish folder. I cleaned everything up and tried multiple times with multiple settings. Then I just made my class library project target .netstandard instead. The console app is now targeting Framework 4.6.1. This way, my class library can be used in any project and my console app works as expected. After reading more about it I'll likely never touch .net core ever again.

peterhuene commented 6 years ago

@A9G-Data-Droid with .NET Core 2.0, an executable (we call it an "application host") is created for Exe project types if you build with a runtime identifier specified (the -r|--runtime option):

An example:

> dotnet new console -o example
> cd example
> dotnet build -r win-x64
> bin\Debug\netcoreapp2.0\win-x64\example.exe
  Hello World!

Currently, if you publish with a runtime identifier specified, i.e. dotnet publish -r win-x64, it automatically becomes a self-contained deployment, and the runtime-specific publish folder (e.g. bin\Debug\netcoreapp2.0\win-x64\publish) should contain an executable, as well its dependencies and the runtime.

We currently do not support publishing a framework-dependent application with an application host, but that is something I'm currently working on addressing.

oliverjanik commented 6 years ago

Can we get these instruction documented somewhere visibly?

Why do I have to hunt down the answer in some obscure Github issue.

Also I work form visual studio. Give me the stupid dll if you have to and the bloody exe for my current platform i'm on.

This project is infuriating. Death by thousand paper cuts. Everyone on dot net team needs to fired.

oliverjanik commented 6 years ago

Also your instructions are broken for me:

C:\Program Files\dotnet\sdk\2.1.201\NuGet.targets(114,5): error : Failed to retrieve information about 'runtime.win-x64.Microsoft.NETCore.DotNetHostPolicy' from remote source {private nuget repo}. [{my project}]
C:\Program Files\dotnet\sdk\2.1.201\NuGet.targets(114,5): error :   Response status code does not indicate success: 401 (Unauthorized). [{my project}]

Why, oh why, does it talk to my private package repository for and internal package??? Why doen't it just fetch it from nuget or wherever you expect it?

livarcocc commented 6 years ago

Documentation can be found here: https://docs.microsoft.com/en-us/dotnet/core/deploying/.

As for the error you are getting, NuGet does not discern feeds, it tries all feeds because you may have a better package in one of them and it won't know that until it has looked there.

Also, please keep the conversation civil and polity. We are all doing our best here.

itadapter commented 6 years ago

@oliverjanik I share your frustration, but dude you gotta give MSFT people some credit. They have rolled up pretty cool stuff very quickly and I can judge as I have been using MSFT toolset since 1994 Vb3/VCPP days :)

For these very reasons that you experience, I advise my customers to convert code to .NET Standard 2+ today, but host code in .NET framework process for now using Windows (it is in the company bloodstream anyway). I am sure MS will make this just right in 6-12 months! Right guys?

Thank ya all!

peterhuene commented 6 years ago

With the upcoming .NET Core SDK 2.1.4xx (release/2.1.4xx branch), we've added a --mode option to dotnet publish that has the following options:

The default when publishing without a RuntimeIdentifier specified (e.g. dotnet publish) is fx-dependent-no-exe.

The default when publishing with a RuntimeIdentifier specified (e.g. dotnet publish --runtime win-x64) is self-contained. This is for backwards-compatibility reasons.

Unlike the .exe files created for Exe type projects when using the .NET Framework (which are always Windows PE files), executables created by .NET Core are PE on Windows, Mach-O on macOS, and ELF on Linux. This is why we need to know the target runtime to create the executable. Without it, the application is assumed to be portable and you can run on any compatible .NET Core runtime with dotnet app.dll.

We still have a review in progress for this feature, so the above may still change for 2.1.4xx, but we believe this will help users that desire framework-dependent applications with an executable to launch with.

So to amend the root example using a future 2.1.4xx .NET Core SDK:

$ dotnet new console
$ dotnet publish --runtime $RID --mode fx-dependent

Where $RID might be any supported runtime identifier. This would publish the application as framework-dependent (meaning a matching shared framework needs to be installed on the target machine), but with an executable you can use to run the application so you don't have to use dotnet foo.dll.

As such, I'm closing this issue as fixed with a new feature in 2.1.4xx. Please re-open or comment if you have any questions/concerns/feedback. Thank you!

HenrikTP68 commented 6 years ago

My big confusion about this whole scenario is:

If I produce a framework dependent deploy then I need to install the framework runtime on target machine but as far as I can see the CLI is not part of the runtime installation, only the SDK includes the CLI so it's not possible to use runtime for framework dependent deploy?

If I need the SDK for a framework dependent deploy and nothing for a self-contained deploy, then where is the runtime installer used?

dasMulli commented 6 years ago

you only need the SDK (which is the branding of the CLI) to create the framework-dependent deploy (dotnet publish)

You only need the runtime to use the framework-dependent deploy on the target machine.

HenrikTP68 commented 6 years ago

That's where I am confused.

When I make a framework dependent deploy of my app I end up with a .dll. To start an app dll I need to run "dotnet myapp.dll" but dotnet.exe is not part of runtime install.

dasMulli commented 6 years ago

dotnet.exe is part of the runtime installers you will get from https://www.microsoft.com/net/download. if it doesn't work for you, please open another issue where we can take this discussion.

HenrikTP68 commented 6 years ago

Ah, ok - I will definetly look into that. Every time I install runtime I have no dotnet exe or cmd anywhere on my pc (no diff if im installing on my home win 10, my work win 10 pro or my server 2016 datacenter or linux for that matter).

wli3 commented 6 years ago

By default it should under C:\Program Files\dotnet\dotnet.exe

ghost commented 6 years ago

@eerhardt @livarcocc @KathleenDollard

I think the real problem after reading this thread is that the runtime system wasn't designed with the same thought process you would have used inside your software code (as a programmer). You missed using crucial patterns, because you tried to shove universal into a single box -- in the same way a bad program would shove too much into a single class.

The .NET Core dll project should be just that, a dynamic linked library. The library code written in .NET Core ready to run regardless of the platform. Nothing more. Alone, it cannot be run by any platform although it certainly contains the program's entry, hot path, main loop, whatever you call it.

We should also then be required to create templated bootstrap projects for each platform we want to publish against. We should NOT/NOT use confusing config files with ambiguous acronyms and abbreviations that push us into a single direction with the hope of universal on the other end.

Bootstrap projects should be small and clean for us to write, but extremely helpful (i.e. key) to the builder and publisher to signal our intentions. The builder creates the published programs in whatever the need and is a best practice for that OS. If that bootstrap project directs the whole project to be wrapped in an exe file and uses Windows installed frameworks then that's how it should roll out of the build and publish. Other platforms get their own customized builds that work best for their circumstances.

That gives us the opportunity to write programs for our intended audience. Not what you guessed our intended audience would be in 2017.

First, I know you have some dream of a single download that works on any platform. What you have now doesn't do that properly anyway. It also creates more headaches for us and for our users. Finally, platform specific downloads isn't a serious problem. It's minor issue compared to the mess created by this system.

Is using a bootstrap project for each platform a little more work? Sure. A little harder for us, but easy on our users. It will work as we intended. It's also explicit. It's also not brittle. What do you plan to do when another operating system or platform rises up? Will you expand your config file with more nearly secret codes? Is that the pattern you would use if we were just talking about a single software application with different domains?

Bring the pain now to fix this issue. It will not get better with age.

(as an aside, who would think a dll is executable program or a script after decades of it being a dynamic linked library?)

svick commented 6 years ago

@TheRealMal

The .NET Core dll project should be just that, a dynamic linked library. The library code written in .NET Core ready to run regardless of the platform.

How is that different from framework-dependent deployment?

We should also then be required to create templated bootstrap projects for each platform we want to publish against. We should NOT/NOT use confusing config files with ambiguous acronyms and abbreviations that push us into a single direction with the hope of universal on the other end.

How is that better than looking up the Runtime Identifier in the documentation for self-contained deployment? How would such project look like and how would it identify the target OS?

tamusjroyce commented 6 years ago

It isn't about identifying the target OS. But rather, launching the program. The question is, what is launching it? sh, bash, cmd, powershell, IIS, Apache, nginx? There are only a few mainstream ones that need supported. Why is this still be debated?

All a .exe extenion does is tells cmd to launch it as an executable. If it were me, for command line apps, I would make a launcher for sh and a launcher for cmd when making the project. And when you click play in visual studio, it runs either of those launchers and you can then debug and tune your application. Just like asp.net core uses it's own launcher.

May I ask why is any detection needed? Two launchers, sh and .bat, and one .dll that gets launched. (there may be several other dlls depending on how you build...but those details shouldn't effect much)

ghost commented 6 years ago

You're confusing an engineering problem with a user/audience concern. In so doing, you're making engineering arguments for what is really an issue about user (e.g. client) expectations.

I don't care if it's a target OS, xbox platform, whatever.

We need access to instructions that direct the build and publish commands to a specification... regardless of sh, bash, cmd, powershell, IIS, Apache, nginx. Making those build/publish instructions work in a compatible way with those other systems is our job. Why? Because we (as the client facing developer) understand our audience, their needs, and their expectations.

Don't assume a simple wrapper works. In some cases it might, in others maybe not.

KathleenDollard commented 6 years ago

First, we agree that you know best how to run your application and are working on giving you more options.

@TheRealMal You are correct that the .NET Core Runtime was not created with the same process you would use to create an application - because it solves different problems. Do not mistake this for a lack of thought. It is a deeply thought out system, and I think a very good design. Some other comments here reminds me that we largely think this set of details is implementation so do not talk about it much.

Shipped with the runtime is an app host. This and the .NET Core Runtime are platform specific. The app host is small, is named dotnet.exe, and there is one on your machine.

When you type dotnet xyz.dll the host finds the dll and selects the runtime to use executing it based on what it specifies and what is available on the machine. These need to be two separate pieces because it is common for them to come from different runtime versions. This is called a framework dependent application. Since this uses a copy of the runtime that is already on the production machine, it minimizes redundant deployed bits and allows patch uptake the next time you start the app. Your .dll is binary compatible across platform. You just create one and use it everywhere. It is also rather small, but you run in the dotnet process. The runtime must already be on the production machine, or dotnet isn't recognized.

When you create a self-contained application you specify the platform and the app host and the runtime are included in your application. These are quite large because the fixed size of the runtime is included. The author must rebuild and redeploy to uptake patches.

These are the two options available today.

The SDK/CLI is not needed on the production machine. I realize this is a bit confusing because dotnet runs your application and when the SDK is installed runs CLI commands and can run other applications via global tools. Other parts of .NET Core that are only present if the SDK is installed take care of routing to the right code.

I did not understand what this was in relation to:

We need access to instructions that direct the build and publish commands to a specification.

KathleenDollard commented 6 years ago

The fix to create a dotnet framework executable that @peterhuene explained has been moved to the .NET Core 2.2.1xx release. This was because of problems found in testing.

You can see more in the PR to revert.

ghost commented 6 years ago

@KathleenDollard

I know all that. The issue you seem to miss is we aren't making the software for me.

The issue is the knowledge of the people who I make the software for -- our clients. People who might never have heard of github, msdn, or .NET, and if they did they couldn't care less. Your process modifies their behavior and expectations with disastrous results.

There are important people out there who have been trained to expect certain responses from files that look a certain way. Even unix "power users" fill volumes of stack exchange questions about how to path and run simple scripts.

You invented "dotnet xyz.dll" without any thought to how people (i.e. non-engineer programmers) would respond to it given what they already know and expect.

ghost commented 6 years ago

I should add that any fix that results in getting less horsepower out of .NET Core during runtime is going to result in more acrimony.

KathleenDollard commented 6 years ago

@TheRealMal

It is not helpful to make unfounded and incorrect accusations about what people were or were not thinking. Being civil is helpful, appropriate and required by our Code of Conduct.

It is helpful to say this is very important to you and your users. Feedback is welcome.

We planned three models. Two were created first, and one of those allows an executable file. It has disadvantages, but you have an option today.

We had hoped the third model would be available in 2.1.4xxx. This model publishes an apphost in your application (allowing you to assign an icon, run in a process name you recognize and start with a direct call or double click), while relying on the the .NET Core Runtime installed on the production machine. This shrinks the deployment (compared to self-contained) and allows patches.

As I just posted here, that has been pushed out to 2.2.1xx.

You have mentioned scripts several time, and I am unclear where you think scripts are or should be involved. It is possible you have a concern that is not relevant to this issue; I'm happy to help straighten that out.

ghost commented 6 years ago

Fine, this is my last comment and then I'm crawling back under my rock.

Did you even consider the power of creating a .epub (e-book file) that produced all of the expected output to the reader, but actually encapsulated a little .NET engine inside doing the work and spitting out the expected output to the reader. If you give the mob the ability to create that kind of bootstrapped adapter some enterprising nerd will make it for you. Cheers.

NimishDhruv commented 6 years ago

I have one question related to self contained deployment.

I have created two console application named "ConsoleApp1" and "ConsoleApp2". Now when I publish the solution using self contain command "dotnet publish -c release -r win7-x64" the relevant files have been generated in their project bin folder along with "ConsoleApp1.exe" and "ConsoleApp2.exe".

My question is that If my project have two executable files then do I need to copy both the publish folder to production? Or Is there any other way where all the lib and executable files are copied to single folder from where we can copy that folder to production?

ylhyh commented 6 years ago

I have a project with COM reference, and the project must to be running in x86(32-bit) environment. so I have to use Visual Studio or MSBUILD to build the project. And I have to use: "C:\Program Files (x86)\dotnet\dotnet.exe" MyWebApi.dll to start it.

After I created a Publish Profile with RuntimeIdentifier and SelfContained specified, I have found that using Vistual Studio to publish the project will create an exe file named MyWebApi.exe, so I can run the exe file directly to start the web api and it will be ran in x86(32-bit) env. See the .csproj and .pubxm below: csproj

pubxml

BUT! If I use MSBUILD to publish the project with the PublishProfile specified, it's never to create the .exe file, who can tell me WHY?

MSBuild.exe" /p:DeployOnBuild=true /p:PublishProfile=Release-winx86-SelfContained

HELP !!!

The component versions of my project: Microsoft.AspNetCore.App (2.1.1) Microsoft.NETCore.App (2.1.2) Vistual Stuio 2017 15.7.3

vijayrkn commented 6 years ago

@ylhyh - Can you please run the following command and share the output log?

MSBuild.exe" /p:DeployOnBuild=true /p:PublishProfile=Release-winx86-SelfContained /bl

*Please remove any sensitive information from the log (if present)

ylhyh commented 6 years ago

Thanks @vijayrkn. but /bl is not work

vijayrkn commented 6 years ago

When you pass /bl , it should create a log file in that folder, can you please share that?

ylhyh commented 6 years ago

@vijayrkn , see the binlog file @ https://github.com/ylhyh/TempShare/blob/master/msbuild.binlog?raw=true

peterhuene commented 6 years ago

I'm going to re-open this against 3.0 as we're hoping to unify the build / publish experience (while remaining backwards compatible) and make it much easier to get executables built for .NET Core projects.

For 2.2, we are enabling the application host (i.e. the executable) to be built when publishing a framework dependent (--self-contained=false application with a RID).

tonecas commented 5 years ago

just to bump up this issue. also had the same bad experience with this. not intuitive and very misleading for such a simple issue. spent a couple of hours to understand how this works. there should be a "portable executable" and a "stand-alone/self-contained executable" and the mention to "Exe" be removed.

Banyc commented 5 years ago

Try modifying the value of TargetFramework in file *.csproj into like net48 then you will get an EXE that can be run under .NET Framework 4.8 after executing the command dotnet build.

learn more here https://docs.microsoft.com/en-us/dotnet/standard/frameworks

bugproof commented 5 years ago

@peterhuene I would prefer to have a single exe (not a host + dll) on Windows like in .NET Framework. It looks really weird now.

peterhuene commented 5 years ago

@wrathofodin unfortunately that's not how .NET Core activation currently works. .NET Core is designed to be cross-platform and it needs a platform-native executable that cannot rely on special behavior in the operating system loader to work (like the Windows-only .NET Framework does for its executables).

We currently have no plans to change the design of application activation. .NET Core applications will still build to DLLs and an optional application host may be used to activate the application instead of dotnet exec.

While not the same thing, the 3.0 .NET Core SDK will have support for publishing a "single-file" executable that is essentially a packed version of your application that self-extracts to a temporary location (performed one time) before running.

emmenlau commented 3 years ago

Thanks for the clarification @peterhuene

ghost commented 3 years ago

necro yes

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <SelfContained>true</SelfContained>
    <RuntimeIdentifier>win10-x64</RuntimeIdentifier>
  </PropertyGroup>
</Project>

thats ur new csproj should work fine with vs