在使用别人的程序时,我们常发现一些好的功能,想通过自己的程序来重复调用。可偏偏这个程序没有留可编程接口,无法通过API、DLL、COM等方式实现调用。早些年与同仁们讨论时,常对此深表遗憾。最近,通过研究Windows API的使用方法,终于从理论上解决了这一问题,即可通WinAPI中SendMessage、EnumChildWindows等,从模拟操作的角度来调用指定程序的指定功能。
    我们知道,Windows是消息驱动的,即Windows窗口、控件的任何操作,都是通过消息事件来完成的。从理论上讲,在我们自己的程序中,只要能准确地找到相应功能所在的窗口或控件的句柄Handle,发出相应的消息,即可完成相应任务。从这个层面上,这种技术可以应用在所有windows程序上。只是这种技术的处理,需要非常细心。因为在实际应用中,从某一个程序中找到相应的控件(包括Parent/Child/Next等)还是比较麻琐的,一不小心,调用的功能就实法实现,还有可能导致程序甚至系统的崩溃。所以,这种技术的关键在于两个地方:一是找准句柄,二是找对消息。
    推荐分析一个窗体(控件)的句柄或消息的工具:SPY++,这在Visual Studio Tools中有,操作起来很简单。

C#中实现外部程序调用,可以通过封装User32.dll中sendmessage等函数来实现。我已将常用的功能封装成一个类:

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;

namespace MuliCall
{
    class WinApi
    {
        #region  宏定义

public const int WM_KEYDOWN = 0x100;
        public const int WM_KEYUP = 0x101;
        public const int VK_CONTROL = 0x11;
        public const int VK_F5 = 0x74;
        public const int KEYEVENTF_KEYUP = 0x2;
        public const int VK_MENU = 0x12;
        public const int WM_SETTEXT = 0xC;
        public const int WM_CLEAR = 0x303;
        public const int BN_CLICKED = 0;
        public const int WM_LBUTTONDOWN = 0x201;
        public const int WM_LBUTTONUP = 0x202;
        public const int WM_CLOSE = 0x10;
        public const int WM_COMMAND = 0x111;
        public const int WM_SYSKEYDOWN = 0x104;

#endregion

public delegate bool EnumChildWindowsProc(IntPtr hwnd, int lParam);

#region  WinAPI定义

[DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendMessage(
            int hWnd, // handle to destination window 
            int Msg, // message 
            int wParam, // first message parameter 
             int lParam // second message parameter 
        );
        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        public static extern int SendTxtMessage(
            int hWnd, // handle to destination window 
            int Msg, // message 
            int wParam, // first message parameter 
            char[] lParam
            // int  lParam // second message parameter 
        );
        [DllImport("user32.dll", EntryPoint = "PostMessage")]
        public static extern int PostMessage(
            int hwnd,
            int wMsg,
            int wParam,
            int lParam
        );

[DllImport("user32.dll", EntryPoint = "FindWindow")]
        public static extern int FindWindow(
            string lpClassName,
            string lpWindowName
        );
        [DllImport("user32.dll", EntryPoint = "FindWindowEx")]
        public static extern int FindWindowEx(
            int hwndParent,
            int hwndChildAfter,
            string lpszClass,
            string lpszWindow
        );
        [DllImport("user32.dll", EntryPoint = "EnumChildWindows")]
        public static extern int EnumChildWindows(
            int hWndParent,
            int lpEnumFunc,
            int lParam
        );

[DllImport("user32.dll", EntryPoint = "EnumChildWindows")]
        public static extern int EnumChildWindows(
            int hWndParent,
            EnumChildWindowsProc lpEnumFunc,
            int lParam
        );

[DllImport("user32.dll", EntryPoint = "SetFocus")]
        public static extern int SetFocus(
            int hWnd
        );

[DllImport("user32.dll", EntryPoint = "SetWindowText")]
        public static extern int SetWindowText(
            int hwnd,
            string lpString
        );

[DllImport("user32.dll", EntryPoint = "keybd_event")]
        public static extern void keybd_event(
            byte bVk,
            byte bScan,
            int dwFlags,
            int dwExtraInfo
        );

[DllImport("user32.dll", EntryPoint = "SetForegroundWindow")]
        public static extern int SetForegroundWindow(
            int hwnd
        );

[DllImport("user32.dll", EntryPoint = "GetClassName")]
        public static extern int GetClassName(
            IntPtr hwnd,
            StringBuilder lpClassName,
            int nMaxCount
        );
        [DllImport("user32.dll", EntryPoint = "GetWindowText")]
        public static extern int GetWindowText(
            IntPtr hwnd,
            StringBuilder lpString,
            int cch
        );

#endregion
 
        //综合处理全局HWD
        private static int CurrnetFormHandle = 0;
        //综合处理函数

public static void SetCurrnetFormHandle(string strWindow)
        {
            SetCurrnetFormHandle(null, strWindow, false);
        }
        public static void SetCurrnetFormHandle(string strClass, string strWindow, bool beForeground)
        {
            CurrnetFormHandle = FindWindow(strClass, strWindow);
            if (beForeground)
                SetForegroundWindow(CurrnetFormHandle);
        }
        public static void SetCurrnetFormHandle(int hwd, bool beForeground)
        {
            CurrnetFormHandle = hwd;
            if (beForeground)
                SetForegroundWindow(CurrnetFormHandle);
        }

public static void SetCurrnetFormHandle(int hwd)
        {
            CurrnetFormHandle=hwd;
        }
        public static int GetCurrentFormHandle()
        {
            return CurrnetFormHandle;
        }

//模拟单击按钮
        public static void ClickButton(string strWindow)
        {
            ClickButton("Button", strWindow);
        }

public static void ClickButton(string strClass, string strWindow)
        {
            ClickButton(CurrnetFormHandle, 0, strClass, strWindow);
        }

public static void ClickButton(int hwdParent, int hwndChildAfter, string strClass, string strWindow)
        {
            int hwdButton = FindWindowEx(hwdParent, hwndChildAfter, strClass, strWindow);
            SendMessage(hwdButton, WM_LBUTTONDOWN, 0, 0);
            SendMessage(hwdButton, WM_LBUTTONUP, 0, 0);
        }

//修改文本框内容
        public static void SetWindowsText(string Parnet_strClass, string Parnet_strText, string strClass, string strText)
        {
            int hwdParent = FindWindowEx(CurrnetFormHandle, 0, Parnet_strClass, Parnet_strText);

//停止 ThunderRT6OptionButton
            int bntHwd = FindWindowEx(hwdParent, 0, "ThunderRT6OptionButton", "停止");

int hwdText = FindWindowEx(hwdParent, bntHwd, strClass, null);  //ThunderRT6TextBox
            SendTxtMessage(hwdText, WM_SETTEXT, 0, strText.ToCharArray());
        }
        public static void SetWindowsText(string strClass,string strText)
        {
            SetWindowsText( strClass, null, strText);
        }
        public static void SetWindowsText( string strClass, string strWindow, string strText)
        {
            SetWindowsText(CurrnetFormHandle, 0, strClass, strWindow, strText);
        }
        public static void SetWindowsText(int hwdParent, int hwndChildAfter, string strClass, string strWindow, string strText)
        {
            int hwdText = FindWindowEx(hwdParent, hwndChildAfter, strClass, strText);
            SendTxtMessage(hwdText, WM_SETTEXT, 0, strText.ToCharArray());
        }

//搜索子窗体
        public static void SearchChild(string strWindow)
        {
            EnumChildWindowsProc myEnumChild = new EnumChildWindowsProc(EumWinChiPro);
            try
            {
                EnumChildWindows(CurrnetFormHandle, myEnumChild, 0);
            }
            catch (Exception ex)
            {
                ;   // MessageBox.Show(ex.Message + "\r\n" + ex.Source + "\r\n\r\n" + ex.StackTrace.ToString());
            }

}

public static bool EumWinChiPro(IntPtr hWnd, int lParam)
        {
            StringBuilder s = new StringBuilder(1256);
            GetClassName(hWnd, s, 1257);
            string ss = s.ToString();
            if (ss == null)
                ss = "";
            ss = ss.Trim();
    //        MessageBox.Show(ss);
            // ThunderRT6TextBox

StringBuilder s2 = new StringBuilder(1256);
            GetWindowText(hWnd, s2, 1257);
            ss = s2.ToString(); 
            return true;
        }
    }
}

使用这个类,在自己的程序中,比较方便地实现外部程序的调用。

  int hwnd = (int)MainHandlArray[i];
 WinApi.SetCurrnetFormHandle(hwnd);
 WinApi.SetWindowsText(textBox_Class_EditPanel.Text, textBox_Title_EditPanel.ToString(), textBox_Class_Edit.Text, textBoxWorkID.Text);

使用这种方法,我写个程序多开器,主要实现启动多个实例,能给EDIT框付值,能定时调用其中按钮。

多开程序下载

转载于:https://www.cnblogs.com/yuanbao/archive/2007/10/31/944086.html

C#中用WinAPI调用外部程序相关推荐

  1. WinAPI执行外部程序和创建新进程:CreateProcess()的使用

    WinAPI执行外部程序和创建新进程:CreateProcess()的使用 一.基本原理和流程 执行一个外部程序实质上可以认为就是创建一个进程 windows系统下创建一个进程意味着: 1.创建一个内 ...

  2. 在Word中调用外部程序两法

    你有没有想过,在编辑Word文档的时候,直接从Word中调用外部程序呢?其实这并不难,下面笔者就以在Word中调用计算器程序为例,简述具体的操作方法. 一.利用宏命令 1.点击"工具→宏&q ...

  3. Delphi 调用外部程序并等待其运行结束

    如何让Delphi调用外部程序并等待其运行结束 函数一: uses Windows, SysUtils, Classes, ShellAPI; function RunAndWait(FileName ...

  4. php+方法返回多个参数,PHP中调用外部程序,及其参数与返回值

    用了一下午,终于弄明白了如何在PHP代码中调用外部程序. 在PHP中调用外部程序主要有两个函数,system和exec. system的原型为string system(string command ...

  5. java的外部引用_Java 调用外部程序

    在Java中可以调用外部程序,这需要通过Process等类来实现. 创建进程 先来介绍一下Process的创建,我们需要使用ProcessBuilder类.如果需要命令行参数的话,则传入多个参数.比方 ...

  6. python调用外部程序 退出_2019-09-09 python调用外部程序

    1.wget--用于下载:ffmpeg--多媒体处理(音频,视频):free 2.调用外部程序两种方法: os.system:(标准库中的非内置库)=Windows下的命令行 例如: import o ...

  7. java魔法堂_Java魔法堂:调用外部程序

    前言 Java虽然五脏俱全但总有软肋,譬如获取CPU等硬件信息,当然我们可以通过JNI调用C/C++来获取,但对于对C/C++和Windows API不熟的码农是一系列复杂的学习和踩坑过程.那能不能通 ...

  8. Delphi调用外部程序的集中方法

    Delphi调用外部程序 WinExec主要运行EXE文件.如:WinExec('Notepad.exe Readme.txt', SW_SHOW); WinExec(   lpCmdLine: LP ...

  9. mysql udf编译_MySql UDF 调用外部程序和系统命令

    1.mysql利用mysqludf的一个mysql插件可以实现调用外部程序和系统命令 2.安装说明: 2.1查询mysql插件路径: 在mysql里查询mysql插件目录的路径:show variab ...

  10. Django项目调用外部程序soffice报错subprocess.CalledProcessError: Command 'soffice --headless --convert-to pdf

    1.今天,在Linux上通过libreoffice调用外部程序把docx文档转换为pdf的时候,报了一个错: [Java framework] Error in function createSett ...

最新文章

  1. 推荐一些好的linux学习网站
  2. 【转】C 编译器优化过程中的 Bug
  3. netstat 在windows下和Linux下查看网络连接和端口占用
  4. leetcode—19.二叉树遍历相关题目leetcode总结
  5. UI基础--烟花动画
  6. SCSA网络安全------数据传输安全-------广域网加速解决方案
  7. numberformat java_【Java】java.text.NumberFormat 工具类
  8. nginx源码安装及配置https自签名
  9. c++实现n阶行列式计算
  10. android之标准体重
  11. xp显示连接上不了网络连接服务器地址,xp本地连接受限制|windows xp系统本地连接提示受限制或无连接怎么办...
  12. acme部署https证书
  13. 大数据周周看:金融科技公司融360赴美IPO,小蓝单车人去楼空,用户押金退还困难
  14. 深度学习图像数据库总结(收藏用)
  15. 《深入浅出WPF》系列视频(特辑)——MVVM入门与提高(难度300+)
  16. 光学变焦----景深=景深远界-景深近界
  17. nginx安装、配置文件详解、测试
  18. 【逆向学习】花指令的去除
  19. 推荐Java反编译工具luyten、jd-gui
  20. CAD绘制复杂轴承图形

热门文章

  1. u盘如何修复 新萝卜U盘官方网站原创
  2. new操作符内部原理(二) 及 delete和free
  3. cesium 漫游飞行_cesium 之三维漫游飞行效果实现篇(附源码下载)
  4. Luogu2665[USACO08FEB] 连线游戏
  5. 如何优化及安全设置Linux系统
  6. Oracle函数登录验证,Oracle密码验证函数与Create Profile
  7. 我的世界手机版javaui材质包_我的世界手机版大乱斗卡比模组
  8. mysql or order by_MySQL 2 SQL数据使用(检索、排序、过滤:SELECT/FROM/LIMIT/ORDER BY/DESC/WHERE/AND/OR/IN/NOT)...
  9. 在html5中插入flash,如何将Flash嵌入到HTML5中?
  10. 存在链接注入漏洞_【安全提示】CNVD发布上周关注度较高的产品安全漏洞(20200817-20200823)...