C#通過進(jìn)程調(diào)用外部應(yīng)用的實現(xiàn)示例
以WINFORM應(yīng)用程序為例,在C#應(yīng)用程序中調(diào)用PYTHON程序(Matplotlib繪制圖形程序),將調(diào)用PYTHON程序生成的窗口程序嵌入在WINFORM窗口中
窗口程序類
using System; using System.Collections.Generic; using System.Data; using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Forms; namespace MyForm { public partial class Form2 : DevComponents.DotNetBar.Office2007Form { private static log4net.ILog log = log4net.LogManager.GetLogger(typeof(Form2)); [DllImport("shell32.dll")] private static extern IntPtr ShellExecute(IntPtr hwnd, string lpOperation, string lpFile, string lpParameters, string lpDirectory, Int32 nShowCmd); private string pyFileName = @"code.py"; //需要在生成完文件后修改該參數(shù)值為生成的文件絕對路徑 private string pyParamsfilePath = @"pyParams.dat"; private string args = "-u"; private string dataType = ""; public delegate void UpdateUI();//委托用于更新UI Process p = null;//接收python程序進(jìn)程,用于控制進(jìn)程 Thread startload;//線程用于matplotlib窗體處理 IntPtr figure1;//圖像句柄 #region 繪圖事件Windows API調(diào)用 [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] public static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent); [DllImport("user32.dll", CharSet = CharSet.Auto)] public static extern int MoveWindow(IntPtr hWnd, int x, int y, int nWidth, int nHeight, bool BRePaint); const int GWL_STYLE = -16; //const int WS_CAPTION = 0x00C00000; const int WS_CAPTION = 0x00CC0000; const int WS_THICKFRAME = 0x00040000; const int WS_SYSMENU = 0X00080000; [DllImport("user32")] private static extern int GetWindowLong(System.IntPtr hwnd, int nIndex); [DllImport("user32")] private static extern int SetWindowLong(System.IntPtr hwnd, int index, int newLong); [DllImport("user32")] private static extern int InvalidateRect(System.IntPtr hwnd, object rect, bool bErase); /// <summary>最大化窗口,最小化窗口,正常大小窗口 /// nCmdShow:0隱藏,3最大化,6最小化,5正常顯示 /// </summary> [DllImport("user32.dll", EntryPoint = "ShowWindow")] public static extern int ShowWindow(IntPtr hwnd, int nCmdShow); #endregion /// <summary> /// 繪制圖形按鈕點擊事件 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void Draw3D(object sender, EventArgs e) { Create3DChart("Z"); } /// <summary> /// 創(chuàng)建3D圖形 /// </summary> private void Create3DChart(string drawDataType) { if (processInfo.process != null) {//如果python程序進(jìn)程不為null if (!processInfo.process.HasExited) {//如果當(dāng)前進(jìn)程沒有被終止,未終止時值為false,終止時值為true processInfo.process.Kill(); } } dataType = drawDataType; //實例化線程,用來初次調(diào)用matlab,并把圖像窗體放到winform startload = new Thread(new ThreadStart(RunPythonScript)); //開始線程 startload.Start(); } /// <summary> /// 關(guān)閉窗口時結(jié)束進(jìn)程 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> public void Close3DChart(object sender, FormClosedEventArgs e) { if (processInfo.process != null) {//如果python程序進(jìn)程不為null if (!processInfo.process.HasExited) {//如果當(dāng)前進(jìn)程沒有被終止,未終止時值為false,終止時值為true processInfo.process.Kill(); } } } /// <summary> /// 調(diào)用python腳本繪制3D圖形 /// </summary> public void RunPythonScript() { log.Info($"開始繪圖線程---{DateTime.Now.ToString()}"); int count50ms = 0; //獲取python的絕對路徑(將文件放在c#程序的debug文件夾中可以這樣操作) string path = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + pyFileName; //創(chuàng)建進(jìn)程 Process process = new Process(); //沒有配置環(huán)境變量的話,可以寫python.exe的絕對路徑,如果配置了,直接寫"python.exe"即可 process.StartInfo.FileName = SystemConfigClass.PythonPath; //設(shè)置python文件路徑參數(shù) string sArguments = path; //設(shè)置執(zhí)行方式參數(shù) sArguments += " " + dataType; sArguments += " " + Application.StartupPath + "\\" + pyParamsfilePath; sArguments += " " + args; log.Info($"繪圖參數(shù)---{DateTime.Now.ToString()}:{sArguments}"); process.StartInfo.Arguments = sArguments;//設(shè)置命令行自變量 process.StartInfo.UseShellExecute = true;//設(shè)置直接從可執(zhí)行文件創(chuàng)建進(jìn)程 //process.StartInfo.RedirectStandardOutput = true;//設(shè)置應(yīng)用程序輸出寫入進(jìn)程(程序輸出可在c#控制臺顯示) 調(diào)試時使用 //process.StartInfo.RedirectStandardInput = true;//設(shè)置應(yīng)用程序輸入讀取進(jìn)程(程序輸入可讀取進(jìn)程輸入) 調(diào)試時使用 //process.StartInfo.RedirectStandardError = true;//設(shè)置應(yīng)用程序錯誤信息寫入進(jìn)程(程序錯誤輸出可在c#控制臺顯示) 調(diào)試時使用 process.StartInfo.CreateNoWindow = true;//設(shè)置新窗口啟動進(jìn)程 process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;//設(shè)置窗口隱藏啟動 processInfo.process = process; process.Start();//進(jìn)程開始 //process.BeginOutputReadLine();//在Process.StandardOutput異步讀取數(shù)據(jù) 調(diào)試時使用 //process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived); //調(diào)試時使用 figure1 = IntPtr.Zero; //循環(huán)查找figure1窗體 while (figure1 == IntPtr.Zero) { //查找matplotlib的Figure 1窗體,安裝PYQT組件后,查找類名Qt652QWindowIcon,未安裝查找類名TkTopLevel figure1 = FindWindow("Qt652QWindowIcon", "Figure 1"); //延時50ms Thread.Sleep(50); count50ms++; //20s超時設(shè)置 if (count50ms >= 400) { //label1.Text = "matplotlib資源加載時間過長!"; return; } } //跨線程,用委托方式執(zhí)行 UpdateUI update = delegate { ShowWindow(figure1, 0); //隱藏標(biāo)簽 //label1.Visible = false; //設(shè)置matlab圖像窗體的父窗體為panel SetParent(figure1, PlotPanel.Handle); //獲取窗體原來的風(fēng)格 var style = GetWindowLong(figure1, GWL_STYLE); //設(shè)置新風(fēng)格,去掉標(biāo)題,不能通過邊框改變尺寸 SetWindowLong(figure1, GWL_STYLE, style & ~WS_CAPTION & ~WS_THICKFRAME); //移動到panel里合適的位置并重繪 MoveWindow(figure1, 0, 0, PlotPanel.Width, PlotPanel.Height, true); //調(diào)用顯示窗體函數(shù),隱藏再顯示相當(dāng)于刷新一下窗體 ShowWindow(figure1, 5); }; PlotPanel.Invoke(update); //再移動一次,防止顯示錯誤 Thread.Sleep(100); MoveWindow(figure1, 0, 0, PlotPanel.Width, PlotPanel.Height, true); //process.WaitForExit();//等待退出 } } }
進(jìn)程信息類
/// <summary> /// 進(jìn)程信息類 /// </summary> public static class processInfo { public static Process process { get; set; } = null; }
系統(tǒng)設(shè)置類
/// <summary> /// 系統(tǒng)設(shè)置類 /// </summary> public static class SystemConfigClass { public static string PythonPath { get; set; } = @"D:\Python\python.exe"; /// <summary> /// /// </summary> /// <param name="dataFilePath>Application.StartupPath + "\\SystemConfig.DAT"</param> public static void SetSystemConfig(string dataFilePath) { if (File.Exists(dataFilePath)) { //如果文件存在 刪除文件后保存文件 string content = ""; using (StreamReader dataFile = new StreamReader(dataFilePath)) { while ((content = dataFile.ReadLine()) != null) { content = content.ToString(); var tempArr = content.Split("^".ToCharArray()).ToList(); if (tempArr != null && tempArr.Count == 2) { SystemConfigClass.PythonPath = tempArr[1]; } else { SystemConfigClass.PythonPath = @"D:\Python\python.exe"; } } dataFile.Close(); dataFile.Dispose(); }; } } }
到此這篇關(guān)于C#通過進(jìn)程調(diào)用外部應(yīng)用的實現(xiàn)示例的文章就介紹到這了,更多相關(guān)C# 進(jìn)程調(diào)用外部應(yīng)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#入門學(xué)習(xí)之集合、比較和轉(zhuǎn)換
本文詳細(xì)講解了C#中的集合、比較和轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-05-05C# 使用Free Spire.Presentation 實現(xiàn)對PPT插入、編輯、刪除表格
小編發(fā)現(xiàn)使用.NET組件——Free Spire.Presentation,在C#中添加該產(chǎn)品DLL文件,可以簡單快速地實現(xiàn)對演示文稿的表格插入、編輯和刪除等操作,具體實現(xiàn)代碼大家參考下本文吧2017-09-09C# 9 新特性——record的相關(guān)總結(jié)
這篇文章主要介紹了C# 9 新特性——record的相關(guān)總結(jié),幫助大家更好的理解和學(xué)習(xí)使用c# 9的新特性,感興趣的朋友可以了解下2021-02-02