C# 为什么应用程序是';未显示的输出?
我有一个应用程序,它有以下C# 为什么应用程序是';未显示的输出?,c#,.net,C#,.net,我有一个应用程序,它有以下Main: static void Main(string[] args) { Console.WriteLine("started"); if (args.Length == 0) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Applicatio
Main
:
static void Main(string[] args)
{
Console.WriteLine("started");
if (args.Length == 0)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
File.WriteAllText("./file.txt", "hello");
}
}
我希望它支持从命令行运行,在一些脚本中使用,以及像GUI应用程序一样运行。但是,如果我从命令行运行它,并向它传递一个参数,我可以看到文件已创建,但我看不到由
Console.WriteLine
生成的任何输出。这是为什么?正如Marco所指出的,您是否尝试过将应用程序的输出类型设置为“控制台应用程序”因为:
这是因为启动WinForms的控制台窗口
应用程序属于cmd.exe进程,它与
您的WinForms应用程序进程
我发现它也提供了一些解决方法,我想我发现了问题,如果我错了,请原谅。
当您创建GUI应用程序并从控制台窗口运行它时,其标准输出流不会发送到以前打开的控制台窗口,因此不会显示。
但是如果你试着运行
yourexe.exe>test.txt
,你可以看到你用Console.WriteLine编写的所有东西
摘录:
你不能,但你可以试着假装
[……]
有些人想写我称之为“机会主义”的控制台程序。这些程序将使用其父级的控制台(如果可用),但不希望为其创建控制台(如果不可用)。内核不支持这种类型的程序,但这并没有阻止一些人提出
问题在于,“附加到现有控制台窗口以进行输入和输出,或作为无控制台GUI应用程序运行?”的决定发生在流程实际启动之前。您不能编写基于命令行参数做出决策的代码
Windows强制您在编译时做出决定:此应用程序将使用控制台(在这种情况下,它总是有一个控制台窗口,如果从图标或“开始”菜单启动,则会打开一个新窗口),还是不使用控制台(在这种情况下,它无法将输入或输出定向到启动它的控制台窗口——但是它可以)。如果您希望始终拥有控制台,请将构建类型更改为“控制台应用程序”;如果您不想拥有控制台,请将其保留为“Windows应用程序”
Raymond在文章中提到的巧妙变通方法是devenv(Visual Studio)和ildasm,以防链接崩溃:
在VisualStudio中,实际上有两个二进制文件:devenv.com和devenv.exe。devenv.com是一个控制台应用程序。devenv.exe是一个GUI应用程序。当您键入devenv时,由于Win32探测规则,会执行devenv.com。如果没有输入,devenv.com将启动devenv.exe并自行退出。如果有输入,devenv.com将按正常方式处理它们nsole应用程序
在ildasm的情况下,只有一个二进制文件:ildasm.exe。它首先作为GUI应用程序进行编译。随后使用editbin.exe将其标记为控制台子系统。在其主要方法中,它确定是否需要以控制台模式或GUI模式运行。如果需要以GUI模式运行,它将作为GUI应用程序重新启动
您似乎希望在控制台模式和GUI模式下运行应用程序。本例就是这样做的。基本上,您可以创建一个表单应用程序,如果从资源管理器运行,则可以有条件地在主应用程序中调用alloconsole
。如果从命令提示符运行,则必须通过查看父进程来检测该命令提示符,您可以附加到它的co使用AttachConsole
解决问题。这里我已经对值进行了硬编码,但是您可以查看参数并决定执行任何操作
基本上这个应用程序有三种模式
bParentConsoleMode
,如果从命令提示符启动,将使用父控制台
bUsingOwnConsole
如果在资源管理器中双击,则必须创建新的控制台
- 最后,当上述两种情况都不成立时,它将作为常规表单应用程序运行
static class Program
{
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
private const int ATTACH_PARENT_PROCESS = -1;
[DllImport("kernel32.dll")]
private static extern bool AllocConsole();
[STAThread]
static void Main()
{
bool bParentConsoleMode = true;
bool bUsingOwnConsole = true;
if (bParentConsoleMode)
{
AttachConsole(ATTACH_PARENT_PROCESS);
Console.WriteLine("Using parent console");
Console.ReadLine();
}
else if (bUsingOwnConsole)
{
AllocConsole();
Console.WriteLine("Using own console");
Console.ReadLine();
}
else //gui mode
{
Console.WriteLine("This is cool");
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
我使用以下代码执行类似操作:
Console.WriteLine("started");
if (args.Length == 0)
{
ProcessForConsole(argsParser);
}
else
{
NativeMethods.FreeConsole();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
。
.
.
将主应用程序设置为控制台应用程序,然后使用FreeConsole将其分离
进程可以使用FreeConsole函数将自身与其控制台分离。如果其他进程共享该控制台,则不会销毁该控制台,但调用FreeConsole的进程无法引用该控制台。当连接到控制台的最后一个进程终止或调用FreeConsole时,控制台将关闭
从如果你的应用类型不是“控制台”,我想你看不到用控制台发送的输出消息。WriteLine
如果你在Visual Studio中调试,我想你会看到。@RichardEv:是的,在“输出”窗口中,我从命令行运行生成的可执行文件。你的项目的“输出类型”是什么设置为?OP时,希望应用程序在带参数运行时充当控制台,在不带参数运行时充当GUI。有趣的是,yourexe.exe>test.txt
获取output@Tempus:嗯,
告诉console将标准输出重定向到文件…并且console
类在标准输出上写入;)是的,我理解:)。我不知道运行GUI应用程序的中间命令提示符。我发现它的输出被发送到下一个命令提示符是很有趣的。这很有趣,但这会打开一个不同的命令提示符。不可能在同一个命令提示符中显示输出吗?这是一个或另一个,而不是两个。第一个是使用控制台而不使用表单,第二个是释放控制台并使用表单。我试图弄清楚如何让应用程序在传递参数时充当控制台应用程序,或者在其他情况下充当GUI应用程序,使用与C#完全不同的语言。但是,通过搜索,我找到了这个答案,它优雅地解决了我的问题。
[DllImport("kernel32.dll", SetLastError = true)]
public static extern int FreeConsole();