C#:有可能有一个单一的应用程序行为作为控制台或Windows应用程序取决于交换机?

我有一个简单的应用程序,我想通过交换机自动化sorting。 但是当我通过开关来运行它时,我并不想显示一个用户界面。 我只是想让它运行,做它的工作,在控制台中打印出来,然后退出。 另一方面,如果我没有使用任何开关运行它,我希望用户界面popup。 而在这种情况下,我真的不想要一个控制台窗口挂在背后。

有什么办法可以做到这一点,还是我必须创build两个单独的项目,一个控制台应用程序和一个Windows应用程序?

虽然不完全符合您的要求,但是通过使用FreeConsole pInvoke删除控制台窗口,我已经实现了此行为的出现

您将项目的输出类型设置为控制台应用程序。 然后,您定义到FreeConsole的外部呼叫:

 [DllImport("kernel32.dll", SetLastError=true)] private static extern int FreeConsole(); 

然后,在你的Main方法你切换根据你的条件。 如果您需要UI,请在打开表单之前先调用FreeConsole以清除控制台窗口。

 if (asWinForms) { FreeConsole(); Application.Run(new MainForm()); } else { // console logic here } 

一个控制台窗口在启动时会短暂出现,但在我的情况下是可以接受的。

虽然有些破绽,但味道很难闻,所以我会认真考虑你是否想要走这条路。

从“新旧事物”

如何编写可以作为控制台或GUI应用程序运行的程序?

你不能。

(我会让你点击文章的细节如何伪造)

当然,只要在静态main(string [] args)中根据命令行中传递的参数放置一个switch语句(或者其他构造)即可。 我也这样做,以执行作为服务或作为控制台之间切换…

注:将项目类型设置为控制台应用程序

 [DllImport("kernel32.dll", SetLastError=true)] private static extern int FreeConsole(); [STAThread] static void Main(string[] args) { if (args.Length == 0 && args[0] == "C") // Console { // Run as console code Console.WriteLine("Running as Console App"); Console.WriteLine("Hit any Key to exit"); Console.ReadLine(); } else { //Console.SetWindowSize(1,1); //string procName = Assembly.GetExecutingAssembly().FullName; //ProcessStartInfo info = new ProcessStartInfo(procName ); //info.WindowStyle = ProcessWindowStyle.Minimized; // EDIT: Thanks to Adrian Bank's answer - // a better approach is to use FreeConsole() FreeConsole(); Application.Run(new MyForm()); } } 

编辑:感谢阿德里安银行的答案,FreeConsole()是更好的方法来“控制”与控制台窗口,而不仅仅是最小化… …

他们是两种不同的范例,我不认为使用这样的命令行开关是一个好主意。 为什么不将核心逻辑构建到控制台应用程序中,然后在需要时从GUI调用? 这将很好地将UI与实现分开,但仍然可以提供一种在需要时单独使用Console应用程序的方法。

我相信答案是否定的,或者是我最后一次研究这个问题。

可执行文件被标记为窗口化应用程序或控制台应用程序。 您可以在Visual Studio中的应用程序,输出类型下,在您的属性中看到此项目

您可以通过使用两个应用程序(一个控制台应用程序,如果不带参数执行)启动GUI应用程序来模拟行为。 您可能会看到一个控制台窗口闪烁,除非您从已经打开的控制台中运行。

如果没有实现自己的控制台窗口版本,答案是否定的。 当Windows加载可执行文件时,它决定是否根据PE头中的数据为您提供控制台窗口。 所以你可以使一个窗口的应用程序没有窗口,但你不能让一个窗口的应用程序有一个控制台。

你可以,但有一些缺点:

如果您为子系统Windows编译,您可以防止启动此黑色窗口。

但是,您必须通过AttachConsole(-1) http://msdn.microsoft.com/en-us/library/windows/desktop/ms681952%28v=vs手动将进程附加到调用控制台(cmd.exe) 。 85%29.aspx

这本身并不能完成这项工作。 您还必须通过这些调用将三个std流重定向到控制台:

 // redirect unbuffered STDOUT to the console lStdHandle = (long)GetStdHandle(STD_OUTPUT_HANDLE); hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); fp = _fdopen( hConHandle, "w" ); *stdout = *fp; setvbuf( stdout, NULL, _IONBF, 0 ); fp = _fdopen( hConHandle, "r" ); *stdin = *fp; setvbuf( stdin, NULL, _IONBF, 0 ); // redirect unbuffered STDERR to the console lStdHandle = (long)GetStdHandle(STD_ERROR_HANDLE); hConHandle = _open_osfhandle(lStdHandle, _O_TEXT); fp = _fdopen( hConHandle, "w" ); *stderr = *fp; setvbuf( stderr, NULL, _IONBF, 0 ); // make cout, wcout, cin, wcin, wcerr, cerr, wclog and clog // point to console as well ios::sync_with_stdio(); 

样本来自: http : //cygwin.com/ml/cygwin/2004-05/msg00215.html

WinMain调用的问题是,窗口已经分叉了你的进程,所以调用cmd.exe控制台已经从你的.exe文件返回,并继续下一个命令。 为了防止你可以用start /wait myexe.exe来调用你的exe start /wait myexe.exe 。这样你也可以得到你的应用程序的返回值,你可以像往常一样用%errorlevel%来检查它。

如果有办法阻止子系统窗口的进程分叉请让我知道。

希望这可以帮助。