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

UseWindowsForms='true' with OutputType='Exe' produces GUI instead of CUI executable #13331

Closed
StevenBonePgh opened this issue Sep 2, 2020 · 8 comments

Comments

@StevenBonePgh
Copy link

StevenBonePgh commented Sep 2, 2020

In the old .csproj format, setting <OutputType>Exe</OutputType> produced an executable that is a console application, even if WinForms was used in the application. Similarly, <OutputType>WinExe</OutputType> always produced a windows GUI application. There are times when a console application is desired, though I'd agree not most times.

This old behavior can be easily confirmed by creating a legacy WinForms project, compiling it with both OutputTypes and running dumpbin /headers MyApp.exe and looking in the output for subsystem. The results are 3 subsystem (Windows CUI) for Exe and 2 subsystem (Windows GUI) for WinExe. Pay attention of the C vs G in that output - it is easy to miss.

After converting to the new SDK format csproj for multitargeting support (as we all want to move to .NET 5.0 but it does not happen overnight), this behavior is broken in the full framework (net48) project - but only if the 'WindowsDesktop' is used and/or 'UseWindowsForms' is true. I'd consider this a regression.

The following project will generate, always, the equal of OutputType == WinExe regardless of what is specified . This is easily confirmed by dumpbin on the output of compilation with both settings.

<Project Sdk="Microsoft.NET.Sdk.WindowsDesktop">
  <PropertyGroup>
   <TargetFrameworks>net48;netcoreapp5.0</TargetFrameworks>
   <UseWindowsForms>true</UseWindowsForms>
   <OutputType>Exe</OutputType>
  </PropertyGroup>
</Project>

The following project, without WindowsDesktop and/or UseWindowsForms the OutputType is respected, and will produce an executable with the expected subsystem. Confirmation achieved with the above process.

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
   <TargetFrameworks>net48;netcoreapp5.0</TargetFrameworks>
   <OutputType>Exe</OutputType>
  </PropertyGroup>
</Project>

If your application does use WinForms, adjusting the project to look like the latter example results in failed compilation., as one would expect.

The only workaround I have been able to discover is not a reasonable one. A post-build step to run editbin /subsystem:console MyApp.exe to twiddle the appropriate bits in the PXE header will make the compiled output behave as desired. To fully/properly integrate this type of workaround in the build pipeline would require something along the lines of Kirill Osenkov's LargeAddressAware package.

Is there a better workaround to restore the previous, and desired, behavior, making the specified OutputType consistent and predictable regardless of what SDK or UseXYZ was also in the project?

@StevenBonePgh
Copy link
Author

Possible related work that impacted dotnet runtime, specifically to be respectful of the differences between the OutputType, which made it more like outputs from Full .NET Framework. Perhaps a change related to this is involved in the regression on the .NET Framework side where a new expected variable is not created in the pipeline.

#1899 (.NETCore apps cannot specify a Windows application manifest and other things that must go in exe)
#2470 (Add ability to mark self-contained .exe as Windows GUI program.)
dotnet/runtime#2455 (Consider providing a "GUI" version of the shared host)

@sfoslund
Copy link
Member

This was a purposeful behavior change with #11398. You can opt out of this behavior by setting the DisableWinExeOutputInference property to true.

@StevenBonePgh
Copy link
Author

I still say this is a regression as it is a breaking behavior change. Also, the word Inference is defined as 'a conclusion reached on the basis of evidence and reasoning' Reasoning that the output type should not be EXACTLY as the user specified (the evidence) is a bug in your inferencing logic. If the user was silent on the output type, then I agree with the remainder of the logic.

@joakimriedel
Copy link

joakimriedel commented Oct 14, 2020

@StevenBonePgh just wasted hours debugging this for a small console utility that had to set UseWindowsForms to be able to use ResXResourceWriter. All my console logging from System.CommandLine just disappeared and I couldn't understand it until I found this issue. Thanks for the workaround flag, but this default behaviour feels really odd!

@Kryptos-FR
Copy link

Kryptos-FR commented Dec 9, 2020

@sfoslund can this "purposeful change behavior" be reverted?

I have working on a .NET framework project that uses the new "sdk-style" format and having this break overnight with no code changes (just because I updated Visual Studio and installed a new SDK) is not acceptable. That is a breaking change and usually the rule is not have breaking changes.

The fact that the code change was made before the doc is updated (see https://github.com/MicrosoftDocs/visualstudio-docs/issues/5893) is also bad practice. I had no way to know that change and only found the issue by chance. In my team we have a rule that the doc should be updated before the code is merged. Microsoft should follow such practice.

At the very least it should have only affected project targeting net5-windows and not .NET framework or .NET Core 3.1.

@sfoslund
Copy link
Member

sfoslund commented Dec 9, 2020

@Kryptos-FR thanks for your feedback. In general, we do allow for breaking changes across major releases (for example, this change was made in the 5.0 major release). cc @wli3 @dsplaisted

@dsplaisted
Copy link
Member

Thanks for the feedback folks. See my comment on the docs issue here: dotnet/docs#21952 (comment)

We try to avoid breaking changes, but we also try to have a balance between making improvements and avoiding impactful breaking changes. We try to strike a balance though, as most any change we make has the potential to be a breaking change and we want to be able to make improvements in the tools.

@dsplaisted
Copy link
Member

Hi folks,

Sorry for the inconvenience this caused. We've reverted the change for .NET 6: #19651

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants