• 回复
  • 收藏
  • 点赞
  • 分享
  • 发新帖

C#实现一个程序控制另一个程序

项目需要一个升级程序,这时候需要一个添加一个中间引导程序,实现两个程序互动,一个程序可以调用另外一个程序,本来程序是wpf实现,所以就还想都用wpf实现,但是试了几天各种办法都调试不过,只能找到窗体的句柄,但是找不到控件的句柄。所以最终失败,最后发现原因可能是:wpf的界面是画出来的,不是win32窗体,没法用api操作。

主要实现方式:利用API函数去找到进程窗口的句柄,然后用API去控制这个窗口

一:第一个程序引导第二个程序后,实现控制第二个程序的隐藏和实现等

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 控制执行文件
{
    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\控制执行文件\测试程序\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();
        }
    }
}

出现的问题:如果被控制程序自己隐藏后,再从控制程序去显示被控制程序就会有问题,程序会黑屏

二:被控制程序来操作控制程序,主要实现方式

导入“User32.dll”中的FindWindow、FindWindowEx函数查找窗口,并获取窗口句柄。也可直接利用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>
        /// 第一个参数是窗体的类名、第二个参数是窗体的标题,二者必须要有一个。这里推荐vs自带的 spy++ 工具查看窗体参数
        /// </summary>
        [DllImport("User32.dll", EntryPoint = "FindWindow")]
        private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);


///
/// 参数说明:
hwndParent
 主窗体句柄、第一步调用 FindWindow 函数返回的值
hwndChildAfter
 子窗体的句柄,可空
lpClassName
要寻找的控件的类名
lpWindowName
要寻找的控件的标题
然后我们调用此函数寻找窗体里的 “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");//发送消息窗口句柄this.Handle.ToInt32(
               //IntPtr WINDOW_HANDLER = FindWindow(null, "layoutPnlUpdate");//发送消息窗口句柄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常量值:因为字数限制,请看另一篇

全部回复(0)
正序查看
倒序查看
现在还没有回复呢,说说你的想法