[Visual Studio 2008]
I created a new project for console application and modified it to look like this:
class Program
{
static void Main (string[] args) {
Thread.Sleep (2000);
}
}
Then I created another project for Windows Form application and modified it:
static class Program
{
//[STAThread] commented this line
static void Main (string[] args) { //Added args
//Commented following lines
//Application.EnableVisualStyles ();
//Application.SetCompatibleTextRenderingDefault (false);
//Application.Run (new Form1 ()); commented this line
Thread.Sleep (2000);
}
}
Now I have neither written Console functions (Console.Write etc.) in first application nor I have written forms related operations in second one. Looks identical to me.
Still first application shows BLACK window and second one doesn't show anything. What makes it work like this?
If you inspect the exe files usine ILDASM you can see that there is a difference in the Manifest (look for "subsystem").
In a Winforms application:
.subsystem 0x0002 // WINDOWS_GUI
In a console application:
.subsystem 0x0003 // WINDOWS_CUI
There may be more differencies in the IL code.
When it comes to what makes the compiler emit this differently in the two cases, this is controlled by the project file's OutputType value:
In a Winforms application:
<OutputType>WinExe</OutputType>
In a console application:
<OutputType>Exe</OutputType>
Out of curiosity I also checked that value for a Class Library project:
<OutputType>Library</OutputType>
In project properties, Application Tab, Output Type you can set to 'Windows Application' or 'Console Application'.
I believe that behind the scenes VS does exactly what Fredrik presented in his post.
Also, setting it to Console Application will show you the black console application for the windows Forms project.
Under the bonnet, there is no difference in a winform vs console exe except for a flag in the PE-header that says "I need a console". The PE header is not controlled from your C# (since it is a compile thing, not a runtime thing), so this is defined in the project file instead (<OutputType>...</OutputType>).
Or at the command-line (csc /target:exe vs csc /target:winexe).
Arguably, they could have used an assembly-level attribute that the compiler intercepted - but would that really have helped? Probably not.
If you look in the project file (csproj) you'll see that the target is defined there as either a console or windows app.
Related
I am new to using Visual Studio Code. I have always used Visual Studio IDE in Windows. I am trying to run a simple Hello World Program on Mac with VS Code. I ran the following command
dotnet new console
which successfully created the csProj file and Program.cs file with the code Console.WriteLine("Hello, World!"); Now by issuing dotnet run command I can get the output from this Program as well.
But I have a different cs file called "Hello.cs" in the same Project location. How do I get the Hello.cs to run instead of the default "Program.cs" created by dotnet new console command.
I tried giving the following property group in the .csproj file but VS Code reports error this is reserved property.
<PropertyGroup><StartupObject>Hello.HelloWorld</StartupObject></PropertyGroup>
Is there another way to choose your default startup CS File if you have multiple CS files in your Project.
The entry point of your application will be the method called Main() in the default namespace of your project. If you want to change the entry point, you can rename your methods, but a better way would be to simply call the code you want to run from "Hello.cs" in your Main() method in "Program.cs."
With using C# 9 Top-level statement feature you can have only one entry point. so you dont need select a default entry point. Remove all Main methods from other files and other top-level files if you want to use this feature.
Read more about Top-level statements...
dotnet new console
command creates a new C# Console Project based on C# 10.0 . This creates a Program.cs file that has something called as a Top Level Statement without a main method. as shown below:
// See https://aka.ms/new-console-template for more information
Console.WriteLine("Hello, World!");
Notice that this does not have the default Main() method which is usually the starting entry point for CS Console Application Projects
Once this statement is introduced in a .cs file in my csProject any other cs file I create and declare my classic entry point defined by my Main() method will be ignored for the purpose of Entrypoint. <<== This is a very important point to understand.
My Hello.cs file had the following code:
public static void Main()
{
Console.WriteLine("Hello World1");
}
This was ignored by C# 10.0 compiler. [From C# 9.0 onwards this is the behavior].
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements
Now All I had to do to make my Hello.CS Main() method my entry point to my C# Console Project is to get rid of the default top level entry point automatically created by the dotnet new console command.
Now I commented out this line in my Program.cs file
//Console.WriteLine("Hello, World!");
Rerun my Project [Command+Shift+D] and voila! I have my code in Hello.cs now executing.
I have a single dotnet-core GUI application that depending on the argument parameters it may show only the GUI interface (done with Avalonia framework) or if it receives some special arguments then it should work in console-mode and log into the console without showing the GUI.
If I use <OutputType>WinExe</OutputType>, then the GUI shows fine but the app will never log into the console (for example when using Console.WriteLine("some-text")).
This means I need to configure the csproj with <OutputType>Exe</OutputType> in order to be able to log into the console anything, the problem is that when running in GUI mode, along with the GUI application window, another console window pops up which I want to hide to show only the GUI.
In dotnet full-framework 4.X I was able to create WPF apps that did this dual console/gui mode in 1 exe.
A possible solution would be if I could make the console window to be hidden when running in GUI mode, or maybe Avalonia-UI/dotnet-core has some other way to do this.
Does anyone knows how to this?
UPDATE: Here are some clarifications:
The app has 2 modes:
GUI Mode: if you just double click on the "App.exe" (runs with no args parameters) then the GUI should appear (and only the GUI, not the GUI plus another console window as it currently happens). This would be usually done by setting the csproj as <OutputType>WinExe</OutputType>, but that makes the Console.Write function not to work when run in the following Console Mode.
Console Mode: if an advanced user is trying to use some of the app functions from the console automate something, then the app should behave like a console application, with all the features one would expect like app.exe -h to show the available commands, app.exe -v to show the version, etc. This means that it is not OK to show some hand-made GUI window displaying the output text or log anywhere else like into a file.
It could be done in 2 separate executable files, but some people like me find some beauty in applications that are just a simple app.exe file.
There are many examples of this dual behavior, like VisualStudio's devenv.exe or Nirsoft applications.
If I get you right you want to start the console on special parameter and WinForms application on the other hand.
First you have to set
<DisableWinExeOutputInference>true</DisableWinExeOutputInference>
In your project file. See documentation
Try to set the <OutputType> back to Exe and add this to your Program > Main:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
IntPtr h = GetConsoleWindow();
// switch here to show or not show console window
ShowWindow(h, 0);
// ShowWindow(h, 1);
Application.SetHighDpiMode(HighDpiMode.SystemAware);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
// Hide your WinForms application manually if parameter is set
var startup = new MainFormStartup();
Application.Run(startup.CreateForm<MainWindow>());
}
[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
[DllImport("kernel32.dll")]
static extern IntPtr GetConsoleWindow();
}
I tried this locally with
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0-windows</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<DisableWinExeOutputInference>true</DisableWinExeOutputInference>
</PropertyGroup>
</Project>
But to be honest in my optinion you should have two exe files compiled with a shared library to accomplish a console exe file and a UI-exe file, fe.:
yourcode.csproj (Your Businesslogic)
yourapp-console.csproj (Console Application: with a reference to yourcode.csproj)
yourapp-ui.csproj (WinForms Application: with a reference to yourcode.csproj)
Consider the following simple program:
using System;
namespace DebugAssertTesting
{
class Program
{
static void Main(string[] args)
{
System.Diagnostics.Debug.Assert(6 == 7, "Bang!");
Console.WriteLine("Hello World!");
}
}
}
When compiled as a .NET Framework console app and executed, the Assert triggers and the Assert UI dialog box is displayed. (Assert failed. Abort, Retry, Ignore etc)
By adding an App.Config file containing the following, the Assert UI is disabled and "Hello World!" is displayed.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.diagnostics>
<assert assertuienabled="false" />
</system.diagnostics>
</configuration>
When the same code is compiled as a .NET Core console app and executed, the Assert triggers and the app terminates. Instead of a UI dialog box, the console displays this:
Process terminated. Assertion failed.
Bang!
at DebugAssertTesting.Program.Main(String[] args) in C:\Development\DebugAssert\DebugAssert\Program.cs:line 9
C:\Development\DebugAssert\DebugAssert\bin\Debug\netcoreapp3.1\DebugAssert.exe (process 38028) exited with code -2146232797.
Is there a way to disable the Assert within a .NET Core console app like there is in a .NET Framework app?
Adding an App.Config file with the content above does not affect the behaviour. (VS2019 copies the file to the output folder, renaming it as expected but the app still terminates on the Assert.)
Can the Assert behaviour be controlled by settings within the app's runtimeconfig.json file? If so, does anyone know the correct syntax?
I've tried a few so far without any luck. I've searched for the equivalent of assertuienabled and drawn a blank.
The Microsoft documentation for Debug.Assert clearly shows that it is supported in all .NET Core variants, but only mentions controlling via App.Config.
You can remove the DEBUG constant from DefineConstants property in csproj file, change this
<DefineConstants>DEBUG;TRACE</DefineConstants>
to just
<DefineConstants>TRACE</DefineConstants>
Or uncheck the checkbox on Build tab of project properties
Another option is remove the DefaultTraceListener from Trace.Listeners collection
Trace.Listeners.RemoveAt(0);
Debug.Assert(6 == 7, "Bang!");
Console.WriteLine("Hello World!");
It'll print you Hello World! text.
You can also add new listener and set AssertUiEnabled or LogFileName properties in code (in the similar way with app.config in .NET Framework).
Last option is to override Fail method to customize the Assert behavior, have a look at Customizing Assert behavior article for details
I have a Asp.Net MVC Core website that's using public static async Task Main(). For that to work I've set the language version to C# 7.2 (in the properties -> build -> advanced dialog, double checked in the csproj) for both Debug and Release build configurations.
App builds and starts fine in both Debug and Release mode.
Now, I'm trying to publish it to an Azure Website directly from Visual Studio 2017 15.5.2 (with WebDeploy) and I get this:
Program.cs(17,29): Error CS8107: Feature 'async main' is not available
in C# 7.0. Please use language version 7.1 or greater. CSC(0,0): Error
CS5001: Program does not contain a static 'Main' method suitable for
an entry point
In the output window I see it's running C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\15.0\Bin\Roslyn\csc.exe with some flags, probably one of them is wrong?
Anyone know if this is a known issue or I'm doing something wrong?
This appears to be a bug in Visual Studio.
Adding this line to main property group in the .csproj file resolved the issue for me:
<LangVersion>latest</LangVersion>
The issue was also reported here in the ASP.NET Home repository.
Not an answer, per se, but for what it's worth async Main is just syntactic sugar. Behind the scenes Roslyn just adds the standard void Main wrapper construction:
static void Main(object[] args)
{
MainAsync(args).GetAwaiter().GetResult();
}
static async Task MainAsync(object[] args)
{
// your code
}
It's probably not worth your time trying to get the server on the same page C# version-wise, just to save literally three lines of code.
I'm developing a console application that is supposed to run under WinCE 6.0 and WinCE 7.0. I'm using C#, Compact Framework 2.0 for different compatibility reasons.
My application is started by an external runtime called TwinCAT (from Beckhoff). Within this application, my teammate used a function block called nt_startProcess (documentation here) that is in charge of starting my application on demand.
My problem - Two different behaviors depending on the OS :
When started manually (without TwinCAT) from a cmd line :
My application behaves properly on both systems. It means that, the applications starts, displays "Hello World" and then returns to the cmd line.
When started from TwinCAT :
a) On WinCE 6.0, I can see a cmd line opening, displaying "Hello World" and shutting itself right after. Perfect behavior to me.
b) On WinCE 7.0, I can see a cmd line opening, displaying "Hello World" but it remains open forever. This is my problem!
Code snippet :
using System;
using System.Collections.Generic;
using System.Text;
namespace MyBasicExample
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World");
}
}
}
Compilation information
In Visual Studio 2008, within the Project compilation's properties :
Plateform target : Any CPU
Additionnal note :
Please note that the computer who is running WinCE 6.0 is using a i486 processor while the one running WinCE 7.0 is using a Freescale ArmCortex process.
WinCE 6.0 :
WinCE 7.0 :
What I tried :
1) Using return 0; at the end of application.
Doesn't change anything on WinCE 7.0.
2) Using Environment.Exit(0);
Is not available in Compact Framework 2.0.
3) Using the property : IsBackground
Snippet :
// ... Same snippet as above except for the next line...
Thread.CurrentThread.IsBackground = true;
Console.WriteLine("Hello World");
// ...
4) From TwinCAT, calling a batch file (which calls my exe) instead of my exe.
Doesn't work with TwinCAT. I get an error of type "General Sub-Windows error".
5) Tested with the Compact Framework 3.5.
Same behavior.
6) Tested with another CX computer (model 2020) using Windows CE 7.0 and another processor architecture (Intel Pentium III Xeon Model A).
Same behavior.
try this code:
Environment.Exit(0);
Try this:
Tools > Options > Debugging > Automatically Close the Console When Debugging Stops
Are you putting you .exe file in Arguments property of ProcessStartInfo ?
If you must do that, I believe that you're using CMD in FileName property, so you must use /K before your .exe name.
Or just put in FileName the .exe path.
You can clarify a lot if you put the code that calls your application.
Try calling Application.Exit
This works in windowed applications, and may force the console window to close.
I had exactly the same problem. Running console app on Beckhoff PLC which never closed.
Instead of creating Console app I created Windows App.
My code stayed the same as for console app. I just commented out:
// Application.Run(new Form1());
Seems now codes run without opening a form.