基本上有獨立進程的應用,都是以Main函數作為入口,開始運行的。在C#中,Main函數可以無參無返回值,當然也可以是有string[]參數和int返返回值的。WinFrom也滿足這個規則。
那么Main作為一個進程的開始函數,那么是誰傳這些參數呢?然后又是誰來接收這個返回值呢?顯然不可能是進程本身,那么就是系統,或其他進程了。
namespace WinFormDemo01
{internal static class Program{[STAThread]static int Main(string[] args){MessageBox.Show($"Main方法中收到的參數:{string.Join(',', args)}");ApplicationConfiguration.Initialize();Application.Run(new Form1());return 101;} }
}
.NET中,除了在Main方法內接收參數,還可以用Enviroment.CommandLine屬性和GetCommandLineArgs方法來接收,屬性會用空格來區分多個參數,方法返回值就是一個string[],與Main中args不一樣的是,這里多一個應用運行所在的路徑。下面的代碼是在Form1窗體里,用一個按鈕來顯示接收到的Main方法參數。
namespace WinFormDemo01
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){//MessageBox.Show(Environment.CommandLine);var args = Environment.GetCommandLineArgs();if (args.Length > 1){label1.Text = $"主程序:{args[0]},\r\n\r\n參數:{string.Join(',', args[1..])}";} } }
}
用批處理來調用進程
我們看一下用在widnows系統中來調用bat,實現對Main函數的送參和取返回值,比如這個bat名稱為result.bat,要求這個文件與我們程序在一個文件夾下,啟一個命令行程序,進入到該目錄,運行rusult.bat即可。
@echo off
WinFormDemo01 guisuwei 1234567890
@if "%ERRORLEVEL%" == "0" goto ok :fail echo Execution Failed echo return value = %ERRORLEVEL% goto end :ok echo Execution succeeded echo Return value = %ERRORLEVEL% goto end :end
結果如下,可以看到Main中的彈框參數
Form1中取Main函數參數
在命令行中接收到的返回值是101
用一個進程來調用這個進程
用批處理來調用的情況雖然可實現,但使用場景還有有限的,一般情況下我們是用一個進程調用另一個進程,就像一個是主程序,其他都是子程序類似。
我們用WinFormDemo00來調用WinFormDemo01,這里使用了兩種方式,阻塞方式,也叫同步方式,另一種是非阻塞方式,也可以叫異步方式。buton1_click方法里是異步,就是調起WinFormDemo01后,WinFormDemo00該做什么做什么,不會卡住等它的返回值。button2_click就是這種情況,會卡住,直到返回結果。
using System.Diagnostics;namespace WinFormDemo00
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){//WinFormDemo01所在路徑var pro = Process.Start(@"C:\MyFile\Asp.NetCoreExperiment\Asp.NetCoreExperiment\WinForm\WinFormDemo01\bin\Debug\net7.0-windows\WinFormDemo01.exe", new string[] { "gsw", "abcd" }); //必須啟用這個屬性,事件才能生效pro.EnableRaisingEvents = true;pro.Exited += Pro_Exited;}private void Pro_Exited(object? sender, EventArgs e){//由于是異常,這個方法所在的線程與UI線程不是同一個,所以用這種方式來操作UI線程的控件this.Invoke((object sender) =>{label1.Text = $"{DateTime.Now},WinFormDemo01返回值:{(sender as Process)?.ExitCode.ToString()}";},?sender);?}private void button2_Click(object sender, EventArgs e){var pro = Process.Start(@"C:\MyFile\Asp.NetCoreExperiment\Asp.NetCoreExperiment\WinForm\WinFormDemo01\bin\Debug\net7.0-windows\WinFormDemo01.exe", new string[] { "gsw", "abcd" });//阻塞 pro.WaitForExit(); label1.Text = $"{DateTime.Now},WinFormDemo01返回值:{pro.ExitCode.ToString()}";}}
}
WinFormDemo00界面布局。
其實大部分桌面應用都是單體,所以Main函數的參數和返回值無所謂,但如果你們是做系列產品的,有很多個應用,每個應用都需要登錄,那么,可以通過這種方法把一個應用中的用戶信息或其他信息傳送到另一個應用中,不需要重新登錄,當然,前提是兩個系統共享用戶系統數據。另外,涉密數據的傳送要注意加密。