項目需要一個升級程序,這時候需要一個添加一個中間引導(dǎo)程序,實現(xiàn)兩個程序互動,一個程序可以調(diào)用另外一個程序,本來程序是wpf實現(xiàn),所以就還想都用wpf實現(xiàn),但是試了幾天各種辦法都調(diào)試不過,只能找到窗體的句柄,但是找不到控件的句柄。所以最終失敗,最后發(fā)現(xiàn)原因可能是:wpf的界面是畫出來的,不是win32窗體,沒法用api操作。
主要實現(xiàn)方式:利用API函數(shù)去找到進程窗口的句柄,然后用API去控制這個窗口
一:第一個程序引導(dǎo)第二個程序后,實現(xiàn)控制第二個程序的隱藏和實現(xiàn)等
WindowsFormsApp1中Form1窗體如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 控制執(zhí)行文件
{
public partial class Form1 : Form
{
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern int ShowWindow(IntPtr hwnd, int nCmdShow);
Process process = new Process();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
process.StartInfo.FileName = @"E:\test\控制執(zhí)行文件\測試程序\bin\Debug\測試程序.exe";
// process.StartInfo.FileName = ConfigurationManager.AppSettings["sb1"];
process.Start();
}
private void button3_Click(object sender, EventArgs e)
{
DisPlayWindow(process.MainWindowHandle,1);
}
public int DisPlayWindow(IntPtr hwnd, int nCmdshow) {
return ShowWindow(hwnd, nCmdshow);
}
private void button4_Click(object sender, EventArgs e)
{
DisPlayWindow(process.MainWindowHandle, 2);
}
private void button2_Click(object sender, EventArgs e)
{
process.Kill();
}
}
}
出現(xiàn)的問題:如果被控制程序自己隱藏后,再從控制程序去顯示被控制程序就會有問題,程序會黑屏
二:被控制程序來操作控制程序,主要實現(xiàn)方式
導(dǎo)入“User32.dll”中的FindWindow、FindWindowEx函數(shù)查找窗口,并獲取窗口句柄。也可直接利用C#中的Process類來啟動程序,并獲取這個進程的主窗口的句柄,等等
[DllImport("user32.dll", EntryPoint = "SendMessage")]
private static extern int SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
//[DllImport("user32.dll")]
//public static extern bool SendMessage(int hWnd, int msg, Boolean wParam, int lParam);
/// <summary>
/// 第一個參數(shù)是窗體的類名、第二個參數(shù)是窗體的標(biāo)題,二者必須要有一個。這里推薦vs自帶的 spy++ 工具查看窗體參數(shù)
/// </summary>
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
///
/// 參數(shù)說明:
hwndParent
主窗體句柄、第一步調(diào)用 FindWindow 函數(shù)返回的值
hwndChildAfter
子窗體的句柄,可空
lpClassName
要尋找的控件的類名
lpWindowName
要尋找的控件的標(biāo)題
然后我們調(diào)用此函數(shù)尋找窗體里的 “button1” 按鈕。
///
[DllImport("User32.dll", EntryPoint = "FindWindowEx")]
private static extern IntPtr FindWindowEx(IntPtr hwndParent, uint hwndChildAfter, string lpszClass, string lpszWindow);
private void btnUpdate_Click(object sender, RoutedEventArgs e)
{
const int WM_SHOWWINDOW = 0x18;
const int BM_CLICK = 0xF5;
IntPtr WINDOW_HANDLER = FindWindow(null, "FormLead");//發(fā)送消息窗口句柄this.Handle.ToInt32(
//IntPtr WINDOW_HANDLER = FindWindow(null, "layoutPnlUpdate");//發(fā)送消息窗口句柄this.Handle.ToInt32(
IntPtr childHwnd = FindWindowEx(WINDOW_HANDLER, 0, null, "button1"); //獲得按鈕的句柄,此按鈕父控件必須是上面搜索的窗體
if (childHwnd != IntPtr.Zero)
{
SendMessage(childHwnd, BM_CLICK, 0, 0);
}
}
注意事項:FindWindowEx(WINDOW_HANDLER, 0, null, "button1"); //獲得按鈕的句柄,此按鈕父控件必須是上面搜索的窗體,要不搜索不到
wMsg常量值:因為字?jǐn)?shù)限制,請看另一篇