越來越多的應用程序提供以命令行的方式來運行,通常的做法有兩種:單獨給應用程序寫一個基於命令行運行的控制台程序,用戶運行這個程序時它一定是以命令行的方式來運行;以GUI和Command Line共享一個應用或exe文件,但通過不同的arguments來判斷,最終分別做不同的處理。
對於單獨給應用程序寫基於命令行運行的控制台程序,無非是通過判斷傳遞的args數組來辨別並設置程序運行所需要的參數,最終設定各項參數而完成所需要的工作。在這裡建議提供對於/?的幫助菜單,方便用戶查詢。
if (args.Length != 1) { Console.WriteLine("ERROR: Invalid Argument."); Console.WriteLine(@"Type 'MyConsole.exe /?' for usage."); return false; } else { if (args[0] == @"/?") { Console.WriteLine("The syntax for this program is:"); Console.WriteLine("MyConsole.exe [project file]"); Console.WriteLine(); Console.WriteLine("[project file] The path to the XML project file."); return false; } else { string strFilePath = args[0]; if (File.Exists(strFilePath)) { …… return true; } else { Console.WriteLine("Can not find the specified project file:'" + args[0] + "'"); Console.WriteLine("Please check the path of project file and try again."); return false; } } }
在調試這樣的程序時可以通過給項目屬性中設置參數來調試,這樣設置的參數在項目啟動時會以參數的形式傳入。
對於一套程序入口卻分別接受GUI調用和Command Line方式運行,我們就必須判斷當前是以什麼方式來運行程序的,檢測當前的運行宿主環境就可以幫助我們來判斷出到底是否是運行在Console模式下。通過檢測程序運行的進程我們可以判斷出它的運行方式。
[DllImport("kernel32.dll", SetLastError = true)] static extern bool AllocConsole(); [DllImport("kernel32.dll", SetLastError = true)] static extern bool FreeConsole(); [DllImport("kernel32", SetLastError = true)] static extern bool AttachConsole(int dwProcessId); [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", SetLastError = true)] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); IntPtr ptr = GetForegroundWindow(); int processId; GetWindowThreadProcessId(ptr, out processId); Process process = Process.GetProcessById(processId); if (process.ProcessName == "cmd") { AttachConsole(process.Id); Console.WriteLine("start from command line"); //return false; //isStartFromCommandLine = true; //TODO: Hide the GUI and perform the actions. //Release the console. FreeConsole(); return; } //GUI mode Page01StartUp form = new Page01StartUp(); form.Show(); form.Focus(); form.BringToFront(); Application.Run();
在這個Case中,程序除了以正常的GUI方式運行外就是命令行方式運行,所以只區別判斷了命令行方式,其余時候正常的以GUI方式運行即可。
還有一種方式是這個程序可以在命令行方式裡通過不同的參數來啟動GUI模式運行,Console模式運行等。通過添加一個來表示是以GUI還是console運行的參數來的會更直接些。
using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using System.Diagnostics; using Microsoft.Win32; using System.Windows.Forms; namespace ConsoleApplication1 { class Program { [DllImport("kernel32.dll", SetLastError = true)] static extern bool AllocConsole(); [DllImport("kernel32.dll", SetLastError = true)] static extern bool FreeConsole(); [DllImport("kernel32", SetLastError = true)] static extern bool AttachConsole(int dwProcessId); [DllImport("user32.dll")] static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", SetLastError = true)] static extern uint GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId); static void Main(string[] args) { string mode = args.Length > 0 ? args[0] : "gui"; //default to gui if (mode == "gui") { MessageBox.Show("Welcome to GUI mode"); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Page01StartUp()); } else if (mode == "console") { IntPtr ptr = GetForegroundWindow(); int processId; GetWindowThreadProcessId(ptr, out processId); Process process = Process.GetProcessById(processId); //process name if (process.ProcessName == "cmd" ) { //attach the session to the current console AttachConsole(process.Id); Console.WriteLine("Run within the console"); Console.Write("Press any key to continue..."); Console.Read(); } else { //no console AND we're in console mode ... create a new console. AllocConsole(); Console.WriteLine("Start within a new console"); Console.WriteLine("Press any key to continue ..."); Console.ReadLine(); } FreeConsole(); } } } }