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

本文关键字:Winforms 处理 参数 命令行 加载 我不想 窗体 何处理 如果 | 更新日期: 2023-09-27 18:12:39

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

  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的这种方法对我的应用程序是否正确?

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

你的意思是和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将工作得很好,您将始终在后台打开控制台窗口-如果您关闭控制台窗口,您的应用程序将结束。

再一次,这可能是好的,但我个人认为这是一个hack。

Cheat (do what Visual Studio Does)

Visual Studio有两个独立的应用程序——一个是控制台应用程序,另一个是Windows窗体应用程序。一个简单的解决方案是让它留在那里,并要求用户在运行命令行版本时启动一个不同的可执行文件(例如myprogram_g.exemyprogram_w.exe)。

Visual Studio更进一步,只有一个入口点,devenv。由于兼容性原因,如果存在任何歧义,Windows shell将始终运行.com文件而不是.exe,这是通过使用这一事实来实现的。而所有的捷径等等。指向可执行文件,如果你在命令行上运行devenv, devenv.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 online可以帮助您解决这个问题-检查Application.Run()的帮助条目。

基本上你想要一个控制台应用程序做一些改变。

下面是一个如何开始的例子,使用一个默认的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();
        }
    }
}

我找到了一个简洁的解决方案,使用微软提供的问题示例。

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

class AnApplicationContext: ApplicationContext
{
private Form _currentForm;

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

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();
}

Main在这里,和原来的有一点不同。注意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