我想创建一个行为如下的应用程序:
对于1和3,我可以在表单的构造函数中处理参数,如下所示:
public ConfigurationActionManagerForm()
{
InitializeComponent();
Environment.GetCommandLineArgs();
// do stuff with that argument
}
但是这种方法不允许我在列表中应用2.的行为。
在program.cs
中,我可以编辑它以在创建表单之前处理参数,但如果我不想传递表单,使用Application.Run()
的正确方法是什么?我如何告知Program
类实例我需要终止或显示出现错误的消息,或者甚至显示进程正在执行操作的小任务栏图标(将其视为解压缩过程)。 / p>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ConfigurationActionManagerForm());
}
来自MSDN的this接近我的申请是否正确?
答案 0 :(得分:7)
您的意思与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.exe
和myprogram_w.exe
)。
Visual Studio更进一步,只有一个入口点devenv
。它通过使用以下事实来实现这一点:出于兼容性原因,如果存在任何歧义,Windows shell将始终运行.com
文件而不是.exe
。所有快捷方式等等。指向可执行文件,如果在命令行上运行devenv
,devenv.com
应用程序将运行而不是使用魔术来判断它是否作为控制台或Windows应用程序运行
我的建议是创建两个不同的应用程序并保留它。
有关详细信息,请参阅How do I write a program that can be run either as a console or a GUI application?(请务必阅读包含其他有用建议的评论)。
另请参阅How to make an application as both GUI and Console application?了解ildasm
如何做到这一点。
答案 1 :(得分:3)
您可以在没有表单实例的情况下调用Application.Run()。
这样,它将在不打开表单的情况下启动消息循环。
您也可以在调用.Run()之前调用MessageBox.Show()。
您甚至可以创建并打开表单,然后在不指定参数的情况下调用Run() - 这只是意味着关闭表单不会自动退出应用程序。
E.g。
MessageBox.Show("Messaage!");
Form1 f = new Form1();
f.Show();
Application.Run();
如上所述,这种方式执行Run()意味着关闭表单不会自动关闭应用程序。您需要在窗体的Close事件处理程序中处理此问题。 (Application.Exit())
MSDN在线可以帮助您解决这个问题 - 查看Application.Run()的帮助条目。
答案 2 :(得分:2)
我使用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
答案 3 :(得分:1)
基本上,您需要一些控制台应用程序,只需进行一些更改。
这是一个如何使用默认的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());
}
}
}
}
}
关于Box1类:
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();
}
}
}