我有一个 WinForm 项目,如果将某些参数传递给它,我希望它可以用作控制台应用程序。使用我从此处阅读的一些技巧,我使用以下代码来完成这项工作。
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AllocConsole();
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AttachConsole(int pid);
...
if (!AttachConsole(-1))
{
AllocConsole();
}
这可行,但有一个令人讨厌的副作用 - 所有输出似乎都是从后台线程生成的。当我从命令提示符运行程序时,输出会在显示输出之前显示下一个提示。
我将项目属性的输出类型设置为控制台应用程序,它解决了这个问题,但现在总是显示一个控制台窗口 - 即使它在“WinForm 模式”下运行。
有没有一种方法可以两全其美,控制台的行为就像程序是当前进程,并且当程序显示 WinForm 时不显示控制台窗口?
更新:
我很抱歉没有澄清这一点。我在 Program.cs 中在控制台和 WinForm 模式之间切换,如下所示:
// nowin is a bool that is set based on a parameter
if (nowin)
{
if (!AttachConsole(-1))
{
AllocConsole();
}
//... Console mode code here...
}
else
{
// run in window
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(argDict));
}
I have a WinForm project that I want to be usable as a console app if certain arguments are passed into it. Using some tips I read from here, I used the following code to make this work.
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AllocConsole();
[System.Runtime.InteropServices.DllImport("kernel32.dll")]
private static extern bool AttachConsole(int pid);
...
if (!AttachConsole(-1))
{
AllocConsole();
}
This works, but there is one annoying side effect - all the output seems to be generated from a background thread. When I run the program from a command prompt, the output displays the next prompt before displaying the output.
I set the project properties' Output Type to Console Application and it fixed this problem, but now there is always a console window displayed - even when it is run in 'WinForm mode'.
Is there a way to get the best of both worlds where the console behaves like the program is the current process and the console window is not displayed when the program displays the WinForm?
UPDATE:
My apologies for not clarifying this. I am toggling between console and WinForm mode in Program.cs like this:
// nowin is a bool that is set based on a parameter
if (nowin)
{
if (!AttachConsole(-1))
{
AllocConsole();
}
//... Console mode code here...
}
else
{
// run in window
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1(argDict));
}
发布评论
评论(4)
也许我一直做错了,但我总是这样做混合:
Maybe I've been doing it wrong but I've always done hybrids like this:
您可以通过仅创建一个 winforms 应用程序并且在命令行上传递某个参数时不显示主窗体来实现此目的,而不是使用这种不确定的方法。
由于控制台应用程序不需要消息循环,因此在控制台模式下调用时无需调用 Application.Run()。
所以你的 Main() 会是这样的:
我还没有尝试过这个,但我认为它会起作用。
Instead of this iffy method, you can accomplish this by just creating a winforms application and not displaying the main form if a certain argument is passed on the command line.
Since a console application doesn't need a message loop, you don't call Application.Run() when called in console mode.
So your Main() would be something like:
I haven't tried this but I think it would work.
看起来没有办法绕过它:
1)如果我希望控制台模式下的输出表现得像专用控制台应用程序,则控制台窗口必须始终存在。
2)如果我想在窗口模式下运行控制台时隐藏控制台,我将丢失阻塞打印。
It looks like there is no way around it:
1) If I want the output in console mode to behave like a dedicated console app, the console window must always be there.
2) If I want to hide the console when I run it in windowed mode, I will lose the blocking prints.
上面的方法可以工作,但是它不允许您写入控制台,如果您尝试调试异常,这会让人抓狂。要从 Win Forms 应用程序写入控制台,您需要应用此处描述的代码: http://www.codeissue.com/issues/i24e1ef8e5a93b4/run-windows-form-application-as-console-app-c。
The above will work, but it won't allow you to write to the console which is maddening if you're trying to debug exceptions. To write to the console from a Win Forms app, you need to apply the code described here: http://www.codeissue.com/issues/i24e1ef8e5a93b4/run-windows-form-application-as-console-app-c.