C#通過進(jìn)程調(diào)用外部應(yīng)用的實(shí)現(xiàn)示例
以WINFORM應(yīng)用程序?yàn)槔?,在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>
/// 繪制圖形按鈕點(diǎn)擊事件
/// </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)程沒有被終止,未終止時(shí)值為false,終止時(shí)值為true
processInfo.process.Kill();
}
}
dataType = drawDataType;
//實(shí)例化線程,用來初次調(diào)用matlab,并把圖像窗體放到winform
startload = new Thread(new ThreadStart(RunPythonScript));
//開始線程
startload.Start();
}
/// <summary>
/// 關(guān)閉窗口時(shí)結(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)程沒有被終止,未終止時(shí)值為false,終止時(shí)值為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)試時(shí)使用
//process.StartInfo.RedirectStandardInput = true;//設(shè)置應(yīng)用程序輸入讀取進(jìn)程(程序輸入可讀取進(jìn)程輸入) 調(diào)試時(shí)使用
//process.StartInfo.RedirectStandardError = true;//設(shè)置應(yīng)用程序錯(cuò)誤信息寫入進(jìn)程(程序錯(cuò)誤輸出可在c#控制臺顯示) 調(diào)試時(shí)使用
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)試時(shí)使用
//process.OutputDataReceived += new DataReceivedEventHandler(process_OutputDataReceived); //調(diào)試時(shí)使用
figure1 = IntPtr.Zero;
//循環(huán)查找figure1窗體
while (figure1 == IntPtr.Zero)
{
//查找matplotlib的Figure 1窗體,安裝PYQT組件后,查找類名Qt652QWindowIcon,未安裝查找類名TkTopLevel
figure1 = FindWindow("Qt652QWindowIcon", "Figure 1");
//延時(shí)50ms
Thread.Sleep(50);
count50ms++;
//20s超時(shí)設(shè)置
if (count50ms >= 400)
{
//label1.Text = "matplotlib資源加載時(shí)間過長!";
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);
//再移動一次,防止顯示錯(cuò)誤
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)用的實(shí)現(xiàn)示例的文章就介紹到這了,更多相關(guān)C# 進(jìn)程調(diào)用外部應(yīng)用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#實(shí)現(xiàn)的三種模擬自動登錄和提交POST信息的方法
這篇文章主要介紹了C#實(shí)現(xiàn)的三種模擬自動登錄和提交POST信息的方法,分別列舉了WebBrowser、WebClient及HttpWebRequest實(shí)現(xiàn)自動登錄及提交POST的相關(guān)實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-11-11
C#發(fā)送和接收HTTP請求類HttpWebRequest的用法
這篇文章主要給大家介紹了關(guān)于C#發(fā)送和接收HTTP請求類HttpWebRequest用法的相關(guān)資料,C#中的HttpWebRequest是一個(gè)用于發(fā)送HTTP請求的類,它可以用于向Web服務(wù)器發(fā)送GET、POST、PUT、DELETE等請求,需要的朋友可以參考下2024-06-06
C#中Winfrom默認(rèn)輸入法的設(shè)置方法
這篇文章主要介紹了C#中Winfrom默認(rèn)輸入法的設(shè)置方法,以實(shí)例形式較為詳細(xì)的分析了C#中輸入法設(shè)置的相關(guān)技巧,需要的朋友可以參考下2015-05-05
C#實(shí)現(xiàn)tostring轉(zhuǎn)換成16進(jìn)制的方法
本文介紹了在C#中將整數(shù)、字節(jié)數(shù)組、字符串轉(zhuǎn)換為十六進(jìn)制字符串,以及將十六進(jìn)制字符串轉(zhuǎn)換回整數(shù)的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2025-02-02
C#?使用Fluent?API?創(chuàng)建自己的DSL(推薦)
DSL領(lǐng)域?qū)S谜Z言是描述特定領(lǐng)域問題的語言,聽起來很唬人,其實(shí)不是什么高深的東西,下面通過實(shí)例代碼介紹下C#?使用Fluent?API?創(chuàng)建自己的DSL,感興趣的朋友參考下吧2021-12-12

