目前我有一个带有图形用户界面的应用程序。
是否可以使用相同的应用程序从命令行中运行(无需GUI,使用参数)。
还是说我必须创建一个单独的.exe文件(和应用程序)来作为命令行工具?
目前我有一个带有图形用户界面的应用程序。
是否可以使用相同的应用程序从命令行中运行(无需GUI,使用参数)。
还是说我必须创建一个单独的.exe文件(和应用程序)来作为命令行工具?
Main
函数能够接受命令行参数。以下是一个简短的示例:
[STAThread]
static void Main(string[] args)
{
if(args.Length == 0)
{
Application.Run(new MyMainForm());
}
else
{
// Do command line/silent logic here...
}
}
OP编辑 抱歉占用您的答案,Merlyn。只是想让这里有所有信息供其他人使用。
要能够在WinForms应用程序中写入控制台,请执行以下操作:
static class Program
{
// defines for commandline output
[DllImport("kernel32.dll")]
static extern bool AttachConsole(int dwProcessId);
private const int ATTACH_PARENT_PROCESS = -1;
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
// redirect console output to parent process;
// must be before any calls to Console.WriteLine()
AttachConsole(ATTACH_PARENT_PROCESS);
if (args.Length > 0)
{
Console.WriteLine("Yay! I have just created a commandline tool.");
// sending the enter key is not really needed, but otherwise the user thinks the app is still running by looking at the commandline. The enter key takes care of displaying the prompt again.
System.Windows.Forms.SendKeys.SendWait("{ENTER}");
Application.Exit();
}
else
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new QrCodeSampleApp());
}
}
}
Console.WriteLine
将与此解决方案一起进入位桶。此外,如果您关心附加失败的情况,可以检查Marshal.GetLastWin32Error
。 - Merlyn Morgan-GrahamAttachConsole
的缺点是,在控制台被附加之前,cmd调用将立即返回,因此在输出被写入之前就已经返回。这也是为什么需要在末尾添加额外的回车键的原因。如果您想将输出导向其他位置,您只会得到一个空的输出。迄今为止我没有找到真正的解决方案。所提供的解决方案对我来说不适用,但它是最接近的解决方案。 - Robert S.在您的Program.cs类中,保持Main方法不变,但将string[] Args
添加到主窗体。例如...
[STAThread]
static void Main(string[] Args)
{
....
Application.Run(new mainform(Args));
}
在 mainform.cs 构造函数中
public mainform(string[] Args)
{
InitializeComponent();
if (Args.Length > 0)
{
// Do what you want to do as command line application.
// You can hide the form and do processing silently.
// Remember to close the form after processing.
}
}
Application.Run
。隐藏窗口可以起作用,但这是一种hack :) - Merlyn Morgan-GrahamConsole.WriteLine
不会产生任何可见的输出。 - Robert S.我是C#编程的新手。但我改进了来自OP和Merlyn的代码提示。当我使用他们的代码提示时,我遇到的问题是在通过双击app.exe调用app.exe或从CMD调用它时参数长度不同。当app.exe从CMD作为CLI运行时,app.exe本身成为第一个参数。下面是我的改进代码,既可以作为GUI双击app.exe,也可以作为从CMD的CLI运行而令人满意。
[STAThread]
static void Main(/*string[] args*/)
{
string[] args = Environment.GetCommandLineArgs();
Console.WriteLine(args.Length);
if (args.Length <= 1)
{
//calling gui part
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new ACVSAppForm());
}
else
{
//calling cli part
string opt = args[1];
//Console.WriteLine(args[0]);
if(opt == "LastBuild")
{
if(args.Length == 3)
{
var defSettings = Properties.Settings.Default;
defSettings.CIBuildHistPath = args[2];
}
else
{
//
}
CIBuildParser cibuildlst = new CIBuildParser();
cibuildlst.XMLParser();
}
}
}
你可能需要将你的应用程序结构化为控制台应用程序,将像点击按钮这样的“操作”单独放在一个类中,包括一个表单,如果没有提供命令行参数,则可以显示该表单,并通过将事件路由到你的“操作”类中的公共方法来处理事件。
我认为这是可能的,只需将您的子系统设置为“控制台”,您将看到一个控制台窗口以及GUI窗口。
但是为了从控制台窗口接受命令,我想您需要创建一个额外的线程来完成它。
Application.Run(new MyMainForm());
这一行即可。将其放置在一个if
块中,如果您获得了参数,则不要运行该代码行。 - Merlyn Morgan-Graham