实现 C# 控制台应用程序的正确方法?
Posted
技术标签:
【中文标题】实现 C# 控制台应用程序的正确方法?【英文标题】:Correct way to implement C# console application? 【发布时间】:2010-10-24 14:27:21 【问题描述】:将命令行工具实现和构建为 C# 控制台应用程序的正确方法是什么?
需要解决的问题包括正确解析命令行变量,以及正确输出文本的方式。虽然 Console.WriteLine() 是最明显的输出选择,但在什么情况下应该选择写入标准错误流、.Error、.SetErrorStream 等?
当向调用命令返回正确的返回码时,应用程序退出的正确方法是什么?
应该如何实现CancelKeyPress事件来中断程序?是否仅在单独线程上发生异步操作时使用?
是否有关于 C# 命令行工具编程的简明指南,或者更好的开源项目或模板,我可以使用它来正确实现相对简单的工具?
【问题讨论】:
欺骗?见这里:***.com/questions/817673/… 另见:***.com/questions/664533/… 我的问题是对 .NET 控制台应用程序机制的更广泛探索——包括使用 ErrorStream 和 CancelKeyPress 事件的正确方法。这两篇文章分别与命令行解析和类结构相关。 【参考方案1】:错误消息应写入 stderr aka Console.Error,并将正常输出写入 stdout aka Console.Out。这对于“过滤器”类型的控制台应用程序尤其重要,其输出(stdout)可以通过管道传输到另一个进程,例如在批处理文件中。
一般如果遇到错误,向 Console.Error 写入错误消息并返回非零结果。或者,如果它是一个异常,就不要费心去处理它。
要返回结果代码,您可以将其作为参数传递给 Environment.Exit,设置 Environment.ExitCode 属性,或从 main 返回一个非零值。
对于简单的控制台应用,我会:
有一个帮助类来解析命令行。
有一个外观类,它为您的命令行工具实现的功能提供可测试的 API。与大多数 .NET API 一样,如果发生错误,这通常会引发异常。
主程序仅使用帮助程序解析命令行并调用 API 传递从命令行传递的参数。它可以选择捕获从 API 抛出的异常,记录它们,将面向用户的错误消息写入 Console.Error 并设置非零返回码。
但我不认为这是唯一正确的方法:实际上并不存在这样的事情,这就是为什么您不太可能找到您要找的书的原因。
【讨论】:
【参考方案2】:关于如何实现命令解析,我之前已经成功使用过反射和委托。它们的工作方式是使用您自己创建的特殊属性来装饰命令方法,该属性声明该方法应该是用户可调用的,可以通过方法的名称或属性中指定的字符串,即:
[Command("quit")]
public void QuitApp()
...
在程序启动时,您可以扫描类中的此类方法,并将针对它们的委托存储在字典中,其中键是命令。这使得基于查找字典中的第一个单词(摊销 O(1) )来解析命令变得容易,并且在未来很容易扩展和维护,因为只需添加单独的方法即可添加新命令。
【讨论】:
【参考方案3】:有关命令行处理,请查看 Mono.GetOptions。它使从短(-f 样式)和长(--file 样式)命令行选项填充变量变得容易。
【讨论】:
【参考方案4】:至于命令行参数,你会发现各种方案,但我一直很喜欢
app.exe "self-explanatory arg" /noArgumentSwitch /argumentSwitch="argument"
至于返回码,您可以将Main()
函数的签名更改为返回int
而不是void
。如有必要,这将允许您向调用进程返回代码。
至于错误流,我没有亲自使用过,我认为不应该以在标准输出流中输出错误信息为代价。它可能更适合用于特定的错误调试信息。
【讨论】:
【参考方案5】:我选择将许多控制台实用程序应用程序编写为 Windows 窗体应用程序而不是控制台应用程序。通常,我会添加一个计时器来延迟初始启动,并添加一个带有进度表的取消按钮——从而允许更直观的取消选项。你仍然可以通过这种方式输出到控制台。
【讨论】:
以上是关于实现 C# 控制台应用程序的正确方法?的主要内容,如果未能解决你的问题,请参考以下文章
这是引用包含泛型的 C# 接口的 VB.NET 实现的 FxCop 错误吗?
在 C# .NET Web 应用程序中每天安排任务的正确方法