zoukankan      html  css  js  c++  java
  • C#中用WinAPI调用外部程序

        在使用别人的程序时,我们常发现一些好的功能,想通过自己的程序来重复调用。可偏偏这个程序没有留可编程接口,无法通过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, 
    00);
                SendMessage(hwdButton, WM_LBUTTONUP, 
    00);
            }

            
    //修改文本框内容
            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框付值,能定时调用其中按钮。  

        多开程序下载



  • 相关阅读:
    从 OKR 工作法到 OKRs-E,落地OKR不能错过的转变
    OKR : 不要让目标仅仅成为口号
    [MySQL]Software caused connection abort: recv failed 问题分析与解决
    VS2010 vcpkgsrv.exe进程CPU占用高的解决方法
    Lync Server 2013企业版部署系列之九:前端部署后续工作
    Lync Server 2013企业版部署系列之八:安装lync server系统
    Lync Server 2013企业版部署系列之七:使用拓扑生成器规划拓扑
    Lync Server 2013企业版部署系列之六:AD准备
    Lync Server 2013企业版部署系列之五:前端服务器软件准备
    Lync Server 2013企业版部署系列之四:SQL准备
  • 原文地址:https://www.cnblogs.com/yuanbao/p/944086.html
Copyright © 2011-2022 走看看