Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider providing a "GUI" version of the shared host #2455

Closed
mellinoe opened this issue Jun 28, 2016 · 52 comments
Closed

Consider providing a "GUI" version of the shared host #2455

mellinoe opened this issue Jun 28, 2016 · 52 comments
Labels
area-Host enhancement Product code improvement that does NOT require public API changes/additions
Milestone

Comments

@mellinoe
Copy link
Contributor

Currently, dotnet.exe unconditionally spawns a console window on Windows. This can be annoying / problematic if you are building an app which creates its own UI, or for some other reason do not want a console window to be created. It's possible to "dismiss" the console after it is spawned, but this results in an undesirable "flicker" on app startup.

In practice, this simply means linking against the WINDOWS subsystem. With CMake, this means just adding "WIN32" to the add_executable call.

As far as I'm aware, this is only a meaningful distinction on Windows. Other platforms need not change anything.

@mellinoe mellinoe changed the title Consider providing a "GUI" version of dotnet.exe Consider providing a "GUI" version of the shared host Jun 28, 2016
@gkhanna79
Copy link
Member

Can you share more details on what needs this?

@mellinoe
Copy link
Contributor Author

mellinoe commented Jun 28, 2016

This is just motivated by my own uses currently, but I expect that this will become more common now that RTM is out. The only alternative right now is to build a host yourself. The complexity of the shared host (and its friends), and the size of our runtime support list is high enough that forking is a pretty daunting task.

Anyways, I mainly just wanted to poke at our thoughts here for future use cases. If we expect that we want most apps to be using the shared host, for servicing, etc., then it probably makes sense to invest in something for this scenario eventually.

@wjk
Copy link
Contributor

wjk commented Aug 6, 2016

👍 I need this for my projects as well. I would recommend copying the functionality in corehost.cpp re finding and loading hostfxr.dll into a custom GUI-based entry point (i.e. an executable that uses WinMain), and trampolining into that DLL as the current corehost program does. This would be needed because GUI applications usually don't get any parameters passed to them. Hence, I would need to specify the name and path to the DLL containing the managed entry point in my entry code. All I would need to do then is to copy hostfxr.dll into the same directory as my program, and have it do the hard work of resolving the dependencies and calling into CoreCLR to start the program.

@mellinoe @gkhanna79 Would this work? I used to do something much like this when I built a GUI CoreCLR-based application way back when (before .NET CLI existed in its current form).

@gkhanna79
Copy link
Member

All I would need to do then is to copy hostfxr.dll into the same directory as my program, and have it do the hard work of resolving the dependencies and calling into CoreCLR to start the program.

Do note that copying hostfxr.dll into the application is only supported for standalone apps its related invariants - runtime is next to it, so is the jit and so on. Hostfxr.dll, when not used in standalone scenario, expects the layout in which Microsoft.NETCore.App is installed to do the same lookup.

I think what you are looking for the following:

  1. Get location of hostfxr.dll on a machine
  2. PInvoke a valid entrypoint just like dotnet.exe does

This will allow your GUI app to look like a native host but not get into the business of copy fundamental components all over and remain in the main supported activation scenario.

@wjk
Copy link
Contributor

wjk commented Aug 7, 2016

@gkhanna79 Yes, this is exactly what I need. As long as I have a solid, future-proofed, hopefully Linux-compatible way of finding hostfxr.dll, that technique will work great.

@zwcloud
Copy link

zwcloud commented Nov 2, 2016

@gkhanna79 I'm developing a GUI framework so the built application should be a window application.

I have done that before on .NET 4.5.

  1. Create a C# project.
  2. Change output type to Windows Application
    image
  3. In the main() method, call CreateWindowEx via P/Invoke to create the main window. Just like what WinForm does to create its main window. I think it is related to the /SUBSYSTEM:WINDOWS and WinMain.
  4. The output exe is a window applicaiton without the console.

Here is a short example of the window applicaiton from pinvoke.net.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
using WindowsInterop;

namespace HelloWin
{
    class Program
    {
        static void Main(string[] args)
        {
            IntPtr hInstance = Process.GetCurrentProcess().Handle;
            string szAppName = "HelloWin";

            WNDCLASS wndclass;

            wndclass.style = ClassStyles.HorizontalRedraw | ClassStyles.VerticalRedraw;
            wndclass.lpfnWndProc = (WndProc)((hWnd, message, wParam, lParam ) => {
                IntPtr hdc;
                PAINTSTRUCT ps;
                RECT rect;

                switch ((WM)message)
                {
                    case WM.PAINT:
                        hdc = Win32.BeginPaint (hWnd, out ps) ;
                        Win32.GetClientRect (hWnd, out rect) ;

                        Win32.DrawText (hdc, "Hello, Windows 98!", -1, ref rect,
                            Win32.DT_SINGLELINE | Win32.DT_CENTER | Win32.DT_VCENTER );

                        Win32.EndPaint(hWnd, ref ps);
                        return IntPtr.Zero;
                        break;
                    case WM.DESTROY:
                        Win32.PostQuitMessage(0);
                        return IntPtr.Zero;
                        break;
                }

                return Win32.DefWindowProc(hWnd, (WM)message, wParam, lParam);
            });

            wndclass.cbClsExtra = 0;
            wndclass.cbWndExtra = 0;
            wndclass.hInstance = hInstance;
            wndclass.hIcon = Win32.LoadIcon(IntPtr.Zero, new IntPtr((int)SystemIcons.IDI_APPLICATION));
            wndclass.hCursor = Win32.LoadCursor(IntPtr.Zero,(int)IdcStandardCursors.IDC_ARROW);
            wndclass.hbrBackground = Win32.GetStockObject(StockObjects.WHITE_BRUSH);
            wndclass.lpszMenuName = null;
            wndclass.lpszClassName = szAppName;

            ushort regResult = Win32.RegisterClass(ref wndclass);

            if (regResult == 0)
            {
                Win32.MessageBox(0, "This program requires Windows NT!", szAppName, MessageBoxOptions.IconError);
                return;
            }

            IntPtr hwnd = Win32.CreateWindowEx(
                WindowStylesEx.WS_EX_OVERLAPPEDWINDOW,
                new IntPtr((int)(uint)regResult),
                //szAppName, // window class name
                "The Hello Program", // window caption
                WindowStyles.WS_OVERLAPPEDWINDOW, // window style
                Win32.CW_USEDEFAULT, // initial x position
                Win32.CW_USEDEFAULT, // initial y position
                Win32.CW_USEDEFAULT, // initial x size
                Win32.CW_USEDEFAULT, // initial y size
                IntPtr.Zero, // parent window handle
                IntPtr.Zero, // window menu handle
                hInstance, // program instance handle
                IntPtr.Zero); // creation parameters

            if( hwnd == IntPtr.Zero )
            {
                int lastError = Marshal.GetLastWin32Error();
                string errorMessage = new Win32Exception(lastError).Message;
            }

            Win32.ShowWindow(hwnd, ShowWindowCommands.Normal );
            Win32.UpdateWindow(hwnd);

            MSG msg;
            while (Win32.GetMessage( out msg, IntPtr.Zero, 0, 0) != 0)
            {
                Win32.TranslateMessage( ref msg);
                Win32.DispatchMessage( ref msg);
            }

            return;
        }
    }
}

As for .NET Core, I thought I can run the dll as a window application like dotnet run -subsyetem:window myApp.dll or build a window application like dotnet build -subsyetem:windows.

aspnet/Tooling#824

@gkhanna79
Copy link
Member

Current POR is for .NET Core to be targeted to enable console and cloud scenarios. While supporting GUI applications is not in the cards for now, this is good datapoint nonetheless that we should account for in our planning.

CC @richlander @blackdwarf

@gkhanna79 gkhanna79 assigned blackdwarf and unassigned schellap Nov 2, 2016
@mellinoe
Copy link
Contributor Author

mellinoe commented Nov 3, 2016

Even if it isn't our main focus currently, I think we ought to come up with a plan for how this will work. With the MSBuild SDK being designed right now, and with knowledge of the host being baked into that, we should at least come up with some sort of plan for how you would override it with your own host, even if that isn't one that we directly provide (although I still think we should do that). My fear is that we'll just ignore this and end up with a system that can't accommodate this scenario cleanly when we do want it in the future.

Adding a GUI version of the host nuget package would be very simple, FWIW. It would probably just be a single-line CMake change and then the associated packaging project additions.

@gkhanna79
Copy link
Member

I am not sure what is being baked into MSBuild about the host, but that does not sound right to me. Can you share more details?

My fear is that we'll just ignore this and end up with a system that can't accommodate this scenario cleanly when we do want it in the future.

The current design does support the flexibility to enable overriding the defaults or changing them. I think it would be prudent to first understand the various implications and needs of the GUI scenario before determining the solutions to make that happen. The key here is exposing the API from hostFXR, which is currently an internal implementation detail of the host.

@mellinoe
Copy link
Contributor Author

mellinoe commented Nov 3, 2016

I am not sure what is being baked into MSBuild about the host, but that does not sound right to me. Can you share more details?

I don't know how the new SDK stuff handles this. At the very least, it's always possible to create post-publish targets that rearrange things for a custom host, but things like that are always a bit fragile and hacky. Since the SDK is still being designed and worked on, I was just suggesting that we consider this scenario so that something nicer than "make a post-publish target" is an option. I was talking with @nguerrera and it sounded like this should already be manageable with the current targets that we have.

the various implications and needs of the GUI scenario

"Not creating a console window" is the only thing I'm really interested in here. I'm not really aware of other specific needs, but they could be considered separately.

@dasMulli
Copy link
Contributor

dasMulli commented Nov 6, 2016

"Not creating a console window" is the only thing I'm really interested in here.

Me too, currently working around it using editbin.exe /SUBSYSTEM:windows my.exe as a post-publish step for a self-contained app. Hacky and relies on VC++ installed but works great.

@mellinoe
Copy link
Contributor Author

mellinoe commented Feb 4, 2017

I was discussing this problem a bit more in the context of Avalonia who have a working (but still in-progress) version of their GUI toolkit for .NET Core.

One option that's worth considering is:

  • Unconditionally linking against the Windows subsystem instead of the console subsystem.
  • Conditionally creating a console window if it is detected that the program being run is a console application (project metadata or something).
    OR
  • Conditionally NOT creating a console window, based on project metadata.

This would just leave us with one single host which could behave correctly in both scenarios. The problem with linking with the console subsystem by default is that there is no way to hide the console before it becomes visible.

Me too, currently working around it using editbin.exe /SUBSYSTEM:windows my.exe as a post-publish step for a self-contained app. Hacky and relies on VC++ installed but works great.

For what it's worth, this is what I am doing in my project as well. It is an okay workaround, but it means that I can only publish my self-contained stuff from Windows; when I do so from Ubuntu, for example, the Windows version will spawn a console window.

@wjk
Copy link
Contributor

wjk commented Feb 4, 2017

@mellinoe That still won't quite hit all my required feature boxes, though. I would also need a Win32 common control manifest, an icon, and a VERSIONINFO resource. While I would much prefer a public API in hostFXR I could call into directly, I could insert these resources using an MSBuild target and the Windows resource-modification APIs.

In addition, while a dual-mode EXE as you described might seem like it would work well, I beg to differ. Your idea of creating the console window at runtime breaks a key scenario for console apps: Being able to interact with the app in the console window you launched it from, as well as having the command interpreter block waiting for it to exit. Doing it this way would always spawn a new console window, which would then need to be interacted with separately, even if the user did not intend that; it would also cause the command prompt (both cmd.exe and PowerShell) to think that the command had exited immediately, breaking scripts that assume its commands always run synchronously.

@mellinoe
Copy link
Contributor Author

mellinoe commented Feb 4, 2017

@wjk Yes, you're absolutely correct. Upon further research my idea does not actually work, although it would have been simple and clean if possible.

@dasMulli
Copy link
Contributor

dasMulli commented Feb 4, 2017

This has been a hard-to-solve problem on windows for a long time and this is the reason java ships java.exe and javaw.exe. There isn't really a solution without a flashing console window or loosing outputting / spawning another console (and maybe nano server refusing to launch it?) - even though AttachConsole() and FreeConsole() really want to make you believe otherwise. :trollface:

In order to publish for GUI applications from any platform for both self-contained and shared framework scenarios, there'd probably be a need to introduce an additional property to the msbuild SDK and runtimeconfig.json. maybe like preferConsoleLessHost.
So the shared fx would probably need to ship an additional dotnetw.exe and runtime nugets would also need to include it (or apphostw.exe). The muxer/hostfxr would then need to launch the GUI-host as another process.

For mac, it is enough to create a correct bundle layout on publish - meaning a folder ending in .app and having a Contents subdirectory with an Info.plist and PkgInfo file and an executable placed in a MacOS subdirectory of that. This would only be achievable for self-contained apps and can probably be done through custom msbuild targets.

@mellinoe
Copy link
Contributor Author

mellinoe commented Mar 9, 2017

@dasMulli I think it would be sufficient (at least IMO) to just provide alternative versions of dotnet.exe and apphost.exe to be deployed next to the application. I'm not very concerned about the scenario where the application is invoked through the shared / CLI host program. Doing so implies to me that you are already operating from the command line and thus don't care about the console window. It's not strictly true of course, but I'm okay with a design that assumes it. With that, we would not need to have extra configuration options in the runtimeconfig file.

The real important feature here (again, IMO) is being able to invoke the application directly, either as a "shared" app, or a fully standalone app, without creating a console window. It seems like that can be accomplished by just having a separate version of apphost.exe (call it "apphostw.exe" like you suggested) and baking some knowledge of that into the SDK regarding when it should be deployed. You can imagine that there could be a <PreferConsoleLessHost> property in the project file controlling this behavior. When set to true, the SDK targets would deploy apphostw.exe instead of apphost.exe on Windows. Or, it could be controlled through some other explicit mechanism in the tooling.

@richlander
Copy link
Member

I'm happy to consider this scenario. As @gkhanna79 suggests, the team is focused on scenarios that don't require this, however, I appreciate and love the experimentation and productization we are seeing with .NET Core. I want to encourage that more and part of doing that is developing a track record of helping people do cool stuff. If we can find a good solution that doesn't add significant complication or cost to the mainline .NET Core project, I'm all for it. Do we have a concrete proposal on how to get there?

@Petermarcu
Copy link
Member

Petermarcu commented Mar 9, 2017

I am supportive too. Seems like the leading proposals are:

  1. Provide an alternate entrypoint dotnetw that will do the right thing to avoid the command prompt.
  2. Provide a variant of dotnet in the SDK that gets copied and renamed to myapp depending on a setting in the project. Default would be what it does today. Then the value for GUIApplication could be set to true to get the alternate.

Thoughts? I'd be happy to see a community PR along these lines and as @richlander said, would like to take something like this in a way that doesn't impact any critical dates for the project.

@mellinoe
Copy link
Contributor Author

mellinoe commented Mar 9, 2017

"2." is something I think could be easily accomplished, assuming we agree on the particulars. There's a couple of additional things discussed above which are not necessarily restricted to GUI apps:

  • Renaming the published executable file. Right now .NET Core apps always show up as dotnet.exe in the process list -- not great. This is probably something we should do for non-GUI apps, anyways, although I guess the exact specifics of how this would work are debatable.
  • Embedding things like icons and other resources into the executable. Probably most interesting for GUI apps, but could be interesting for other stuff as well.

I can imagine that the two things above can be readily accomplished with a post-build MSBuild task. On the other hand, which native host we deploy into the project output seems like a more "baked-in" part of the SDK, and therefore could warrant special treatment (e.g. a special property that we define and interpret).

@richlander
Copy link
Member

Clarification -- Is this soley for self-contained apps? The "always dotnet" is a shared fx scenario but then you wouldn't be copying.

@Petermarcu
Copy link
Member

I would start with self-contained. @mellinoe , do you agree? The shared scenario I think would neccesitate something more like dotnet/core-setup#1.

@mellinoe
Copy link
Contributor Author

mellinoe commented Mar 9, 2017

I'm interested in the native host which is published next to all applications, both portable and standalone. I'm not really as interested in having a version of the "global dotnet" host, because the use of that implies to me that you are running from a command line in the first place.

@yzrmn
Copy link

yzrmn commented Mar 9, 2017

Hi guys,

@mellinoe, thanks for bringing this up.

I am currently developing a purely managed, CPU-based graphics toolkit for .NET and running into the same problem that @zwcloud described with Core (console window is showing and output type 'Windows Application' does not work).

This might be OT, but I would like to propose an approach that might be better in terms of user experience for GUI applications (especially on Windows):
Assemblies with entry points (console or window) are executables just like in previous .NET versions and behave in the same way (selected output type). It does the same with Mono under Linux.
Could this work or would it be impossible for the runtime to distinguish between .NET and .NET Core applications?

Greetings

@dasMulli
Copy link
Contributor

dasMulli commented Mar 9, 2017

So i guess this would mean a new "branch" of RIDs?
Like.. you put <RuntimeIdentifier>win7-x64-gui</RuntimeIdentifier> in your csproj and it will resolve a "gui subsystem" host on dotnet publish?

@wjk
Copy link
Contributor

wjk commented Mar 9, 2017

@yzrmn @mellinoe I have already accomplished what is being discussed (mark as GUI subsystem, add resources to entry point) with an MSBuild task in a private repo of mine. No modifications to .NET Core itself are required, and Visual Studio still debugs the application just fine. I will work on moving the code into a public repo sometime in the near future. Thanks!

@mellinoe
Copy link
Contributor Author

mellinoe commented Mar 9, 2017

So i guess this would mean a new "branch" of RIDs?
Like.. you put win7-x64-gui in your csproj and it will resolve a "gui subsystem" host on dotnet publish?

I don't think we need anything so complicated. I was anticipating we could just ship apphostw.exe in the existing Windows package next to apphost.exe. The SDK already understands that it needs to deploy and rename this file for published executable projects, so we should be able to easily modify it to deploy the other one instead, based on a project property.

I have already accomplished what is being discussed (mark as GUI subsystem, add resources to entry point) with an MSBuild task in a private repo of mine.

Could you outline how you are doing this? Using Win32 API's to accomplish it is kind of a non-starter, because they can't be used outside of Windows.

@nguerrera
Copy link
Contributor

nguerrera commented May 4, 2017

@mellinoe Cool!

If you put <UseGuiHost>true</UseGuiHost> in your project

I'm thinking we should use OutputType=WinExe, which controls this for .NET framework exectuables. We have some bugs around it in the SDK (see dotnet/sdk#1176), but we're going to get those fixed. The nice things there beyond consistency with .NET Framework is that we can get VS property page support for free.

@tannergooding
Copy link
Member

It would be great if we "just worked" with the existing OutputType=WinExe (especially since this essentially resolves down to a compiler switch that sets a PE Header flag).

It would be even better if we respected this flag on all platforms and not just on Windows.

@mellinoe
Copy link
Contributor Author

mellinoe commented May 4, 2017

@nguerrera Yeah, OutputType=WinExe is probably the obvious choice here. My only hangup is the fact that it makes you put a "windows-ism" into your project file. That's just a small problem, though; it's probably overcome by the fact that years of tooling understand "WinExe".

@tannergooding What would respecting this flag look like on other platforms? As far as I can tell, there is no such distinction for executables on other systems, only Windows. There is some discussion about producing a macOS bundle above, but I'm not as familiar with those. It seems like they are only tangentially related. Was there something concrete you were thinking of with respect to other platforms?

@tannergooding
Copy link
Member

@mellinoe, I would imagine it would do (or attempt to do) the same thing that Windows does. Launching a "regular" executable would cause a terminal window to appear for all output (or use the current terminal if launched from there). Launching a "WinExe" executable would not cause any terminal window to appear and would require the end user to construct and display a window, if desired.

Also, I think "WinExe" should be fine, as you could say it stands for "Windowed Executable" (that is an executable which has a graphical window) rather than "Windows Executable" (which is an executable specific to the Windows Operating System)

@dasMulli
Copy link
Contributor

dasMulli commented May 4, 2017

Sadly, I think a lot of tools/"SDKs" picked up conditioning on OutputType being Exe.
It also seems weird that if I want to multi-target for multiple TFMs and RIDs, I would need to condition the output type on two other properties. (inverse: it would seem weird if it just worked)

@dasMulli
Copy link
Contributor

dasMulli commented May 4, 2017

@tannergooding I think this console-window experience is pretty much a vs-specific thing.. most other IDEs have integrated console windows and route the stdin/out through it. Even for "Gui type" apps, or mobile apps that run in simulators or attached devices.

Furthermore, I believe the ability to select a different app host is more a deployment-time choice than an app model selection - just like $(SelfContained) (2.0 tooling).

@danwalmsley
Copy link

I am also in need of this feature 👍

@steveharter
Copy link
Member

@mellinoe and I had a discussion on this, using an approach similar to what he has already prototyped.

Tentatively flagging this as 2.1 until we can fully prioritize and schedule that work.

@steveharter
Copy link
Member

Moving to 2.2; a custom build task to re-write the peheader in the exe is probably the least intrusive.

@steveharter
Copy link
Member

See also https://github.com/dotnet/core-setup/issues/230 which requested version, icon and SxS manifest

@wjk
Copy link
Contributor

wjk commented Jan 12, 2018

@steveharter Note that since I posted in dotnet/core-setup#230, I have figured out how to insert the required resources using the Win32 resource-modification APIs. (I also use dumpbin.exe to change the command-line shared host into a GUI shared host.) Therefore, this is a pretty low-priority request for me now. Thanks!

@steveharter
Copy link
Member

Linking issue https://github.com/dotnet/cli/issues/6237 because that also has a need for a app-specific named exe (not the shared dotnet.exe) along with shared framework semantics. Today you can only have an app-specific exe for standalone apps.

Having a named exe for a GUI app (v.s. dotnetw.exe or equivalent) would also allow an icon and other app-specific resources to be embedded (for Windows anyway).

@xoofx
Copy link
Member

xoofx commented Apr 3, 2018

I'm also super interested by this feature! (Mostly for AOT and Standalone apps)

As suggested earlier by @nguerrera I would be in favor of <OutputType>WinExe</OutputType>. Even with a PE rewriter, @steveharter what's the decision around this? (would like to make sure that it will fit with well with CoreRT story...)

@steveharter
Copy link
Member

steveharter commented Jun 5, 2018

With the 3.0 proposed support for WPF and WinForms, setting 3.0 milestone.

Basic functionality would include (on Windows):

  1. Support for standalone and framework-dependent executables via a project setting \ CLI option. This will ensure the PE header change to make it GUI not console.
  2. Support for adding icon(s) and other resources including Title, Description, etc. This needs to change the embedded resources of apphost.exe.

Optional \ TBD:
3) A mechanism to launch the .dll without an apphost (i.e. not using the native executable <myapp.exe>) This may include adding a dotnetw.exe as mentioned earlier. At a minimim, this is useful for using the wdotnet.exe muxer with dlls and to continue to support the muxer for F5 (non-publish) standalone-apps for performance so we don't have to (re)deploy the entire application to run\test each time
4) Consider OSX and some Linux variants

@ericstj
Copy link
Member

ericstj commented Jul 12, 2018

See also dotnet/sdk#1899

@jkotas
Copy link
Member

jkotas commented Nov 13, 2018

The plan is to have apphost .exe by default for GUI apps. It makes the GUI shared host unnecessary.

@jkotas jkotas closed this as completed Nov 13, 2018
@mellinoe
Copy link
Contributor Author

mellinoe commented Nov 14, 2018

@jkotas Could we close the loop on this one with some instructions on how to enable the new functionality? For example -- I have existing projects that should be GUI projects. What do I need to change to make that happen?

@nguerrera
Copy link
Contributor

nguerrera commented Nov 14, 2018

You will get an apphost by default, and it will be GUI if OutputType is WinExe. This is already happening in 3.0 daily builds, which you can try from https://github.com/dotnet/core-sdk

@jkotas
Copy link
Member

jkotas commented Nov 14, 2018

What do I need to change to make that happen?

As Nick said, you need to update to netcoreapp3.0 and build. That's all.

@mellinoe
Copy link
Contributor Author

Thanks, that worked like a charm.

@dasMulli
Copy link
Contributor

Shouldn't it even work with netcoreapp < 3.0? AFAIK there is code in the SDK that just flips the subsystem bit after copying the apphost and embedding the dll name

@nguerrera
Copy link
Contributor

Yes, I believe so, as long as you use the 3.0 sdk.

Cc @peterhuene

@peterhuene
Copy link

peterhuene commented Nov 14, 2018

I believe building with a 3.0 SDK with an OutputType of WinExe is all that's required to flip the subsystem type (provided the RID starts with win too; for netcoreapp3.0 targeted apps, also when the "default RID" starts with win this includes when building without a RID on Windows due to the default apphost RID being used).

@darthwalsh
Copy link

If you want a dotnetw.exe today that has the WinApp bit flipped and are still on 2.x SDK, you can use the awesome project Vittel/RunHiddenConsole and move the output assembly to dotnetw.exe

@msftgits msftgits transferred this issue from dotnet/core-setup Jan 30, 2020
@msftgits msftgits added this to the 3.0 milestone Jan 30, 2020
@dotnet dotnet locked as resolved and limited conversation to collaborators Dec 30, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Host enhancement Product code improvement that does NOT require public API changes/additions
Projects
None yet
Development

No branches or pull requests