如果我不想加载主窗体,如何在Winforms中处理命令行参数?

我想创建一个行为如下的应用程序:

  1. 在没有参数的情况下,它显示主窗体
  2. 参数“a”执行作业但主表单未加载。
  3. 在参数“b”上,表单使用传递的参数加载(加载该文档)

对于1和3,我可以在表单的构造函数中处理参数,如下所示:

public ConfigurationActionManagerForm() { InitializeComponent(); Environment.GetCommandLineArgs(); // do stuff with that argument } 

但是这种方法不允许我在列表中应用2.的行为。

program.cs我可以编辑它以在创建表单之前处理参数,但是如果我不想传递表单,那么使用Application.Run()的正确方法是什么? 我将如何通知Program类实例我需要终止或显示出现错误的消息,或者甚至显示一个小任务栏图标,表明该过程正在进行操作(想想它就像解压缩过程一样)。

 [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new ConfigurationActionManagerForm()); } 

这种来自MSDN的方法对我的应用程序是否正确?

你的意思与Visual Studio的工作方式相同吗?

如果是这样,那么你无法在普通的Windows应用程序中执行此操作 – Visual Studio作弊。

问题是Windows应用程序可以是Windows窗体应用程序,也可以是控制台应用程序,但它不能同时 – 它在编译时决定(对于.Net应用程序,这是在项目属性窗口中)。 你的选择是:

使您的应用程序成为Windows窗体应用程序

在这种情况下,#1和#3将完美地工作,但对于#2,您会发现您无法读取/写入控制台(因为没有一个!)。 如果您的申请不需要提供任何反馈,那么这可能没问题 – 按照您的惯例做您的工作,只是不显示表格:

 [STAThread] static void Main(string[] args) { if (args.Length > 0) { // Handle #2 here } else { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new ConfigurationActionManagerForm()); } } 

使您的应用程序成为控制台应用

在这种情况下,#2将完美地工作,但是虽然#1和#3可以正常工作,但您将始终在后台打开控制台窗口 – 如果您关闭控制台窗口,您的应用程序将结束。

这可能是好的,但我个人认为这是一个黑客。

作弊(做Visual Studio所做的)

Visual Studio通过2个独立的应用程序作弊 – 一个是控制台应用程序,另一个是Windows窗体应用程序。 简单的解决方案是将其保留,并要求用户在运行命令行版本时启动不同的可执行文件(例如myprogram_g.exemyprogram_w.exe )。

Visual Studio更进一步,并且有一个入口点devenv 。 它通过使用以下事实来实现这一点:出于兼容性的原因,如果存在任何歧义,Windows shell将始终运行.com文件而不是.exe文件。 所有快捷方式等等都指向可执行文件,如果你在命令行上运行devenvdevenv.com应用程序将运行而不是使用魔术来判断它是否作为控制台或Windows应用程序运行。

我的建议是创建两个不同的应用程序并保留它。

请参阅如何编写可以作为控制台或GUI应用程序运行的程序? 有关更多详细信息(请务必阅读有其他有用建议的评论)。

另请参阅如何将应用程序同时用作GUI和控制台应用程序? ildasm如何做到这一点。

您可以在没有表单实例的情况下调用Application.Run()。

这样,它将在不打开表单的情况下启动消息循环。

您也可以在调用.Run()之前调用MessageBox.Show()。

您甚至可以创建并打开表单,然后在不指定参数的情况下调用Run() – 这只意味着关闭表单不会自动退出应用程序。

例如

  MessageBox.Show("Messaage!"); Form1 f = new Form1(); f.Show(); Application.Run(); 

如上所述,这种方式执行Run()意味着关闭表单不会自动关闭应用程序。 您需要在窗体的Close事件处理程序中处理此问题。 (Application.Exit())

MSDN在线可以帮助您解决这个问题 – 查看Application.Run()的帮助条目。

我使用microsoft提供的问题中的示例找到了一个简洁易用的解决方案。

我创建了这个应用程序上下文类,负责应用程序中的所有内容,我使用它而不是Application.Run()中的表单,如下所示。 为了实现问题中的行为,我使用隐藏的第二个表单,只显示任务栏图标。 如果用户想要查看进程的运行方式,他们可以单击任务栏图标并查看日志窗口,该窗口实际上是示例下面的ConfigurationApplierForm

 class AnApplicationContext: ApplicationContext { private Form _currentForm; 

注意构造函数是私有的,main是在这个类中并声明为static。

 private AnApplicationContext() { Application.ApplicationExit += new EventHandler(this.OnApplicationExit); // choose which form to show based on arguments if(Environment.GetCommandLineArgs().Contains("-apply")) { _currentForm = new ConfigurationApplierForm(); } else { _currentForm = new ConfigurationActionManagerForm(); } // initialize the form and attach event handlers _currentForm.FormClosed += new FormClosedEventHandler(this.OnCurrentFormClosed); _currentForm.ShowDialog(); } 

主要在这里,与原来有点不同。 注意Run方法中的参数

 [STAThread] static void Main() { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); // context is passed instead of a form Application.Run(new AnApplicationContext()); } private void OnCurrentFormClosed(object sender, EventArgs e) { ExitThread(); } private void OnApplicationExit(object sender, EventArgs e) { /* is there anything to do when all forms are closed and the application is going to die?*/ } } 

此外,我们需要告诉项目这是启动项目。

 Project Properties -> Application -> Startup Project 

基本上你需要一个控制台应用程序,只需进行一些更改。

这是一个如何使用默认的aboutbox类开始的示例:

 using System; using System.Windows.Forms; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { if (args.Length == 0) { Console.WriteLine("No Arguments"); } else { if (args[0] == "a") { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new AboutBox1()); } } } } } 

而AboutBox1类:

 using System.Reflection; using System.Windows.Forms; namespace ConsoleApplication1 { partial class AboutBox1 : Form { public AboutBox1() { InitializeComponent(); this.Text = String.Format("About {0} {0}", AssemblyTitle); this.labelProductName.Text = AssemblyProduct; this.labelVersion.Text = String.Format("Version {0} {0}", AssemblyVersion); this.labelCopyright.Text = AssemblyCopyright; this.labelCompanyName.Text = AssemblyCompany; this.textBoxDescription.Text = AssemblyDescription; } #region Assembly Attribute Accessors public string AssemblyTitle { get { object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); if (attributes.Length > 0) { AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0]; if (titleAttribute.Title != "") { return titleAttribute.Title; } } return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase); } } public string AssemblyVersion { get { return Assembly.GetExecutingAssembly().GetName().Version.ToString(); } } public string AssemblyDescription { get { object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); if (attributes.Length == 0) { return ""; } return ((AssemblyDescriptionAttribute)attributes[0]).Description; } } public string AssemblyProduct { get { object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); if (attributes.Length == 0) { return ""; } return ((AssemblyProductAttribute)attributes[0]).Product; } } public string AssemblyCopyright { get { object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); if (attributes.Length == 0) { return ""; } return ((AssemblyCopyrightAttribute)attributes[0]).Copyright; } } public string AssemblyCompany { get { object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); if (attributes.Length == 0) { return ""; } return ((AssemblyCompanyAttribute)attributes[0]).Company; } } #endregion private void okButton_Click(object sender, EventArgs e) { Close(); } } }