欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費電子書(shū)等14項超值服

開(kāi)通VIP
C#實(shí)現對外部程序的調用操作

關(guān)于C#如何調用外部應用程序、如何操作外部程序(如點(diǎn)擊按鈕、輸入文本等),這篇文章介紹的非常詳盡,建議閱讀。

本文代碼下載(VS2010開(kāi)發(fā)):http://download.csdn.net/source/2796362

本文摘要:

1:一個(gè)簡(jiǎn)單的例子   

  1.1:EnumChildWindows介紹

  1.2:主要源碼

2:難點(diǎn):如何獲取指定的控件句柄

  2.1:使用SPY++

  2.2:獲取控件位置

  2.3:獲取控件ID

1:一個(gè)簡(jiǎn)單的例子 

    在日常編碼過(guò)程中,我們常常會(huì )進(jìn)行自動(dòng)化測試。這里的自動(dòng)化測試不是指單元測試,而是模擬人工輸入來(lái)進(jìn)行快速的、高并發(fā)的測試??梢允褂玫淖詣?dòng)化工具有LOADRUNNER,以及目前在VS2010中的功能很強大的測試工作平臺(錄制操作步驟,自動(dòng)生成代碼)。但是,這些工具的熟練掌握也有一定的時(shí)間成本,并且,最主要的,對于一個(gè)程序員來(lái)說(shuō),那不夠靈活。所以,比較高效的一個(gè)做法是,調用WINDOWS API,自己動(dòng)手寫(xiě)編碼來(lái)實(shí)現。

    下面做一個(gè)簡(jiǎn)單的演示。為了簡(jiǎn)便起見(jiàn),假設存在這樣一個(gè)應用程序:

1:提供一個(gè)WINFORM窗體,上面存在一個(gè)TextBox,以及一個(gè)Button;

2:點(diǎn)擊Button,會(huì )彈出提示框,提示框內容為T(mén)extBox的值;

    現在,測試要求如下:

1:在300臺機器上運行上面的程序;

2:到這300臺機器上去點(diǎn)擊這個(gè)Button,看看上文中的功能2有沒(méi)有實(shí)現;

    很顯然,實(shí)際情況中沒(méi)有這么簡(jiǎn)單的程序,實(shí)際的情況有可能是點(diǎn)擊Button,統一下載一個(gè)文件,而測試的要求可能就變?yōu)榭己?a target="_blank" title="服務(wù)器教程">服務(wù)器的負載?,F在,測試部顯然也沒(méi)有300個(gè)人坐在客戶(hù)機上驗證測試的結果,這個(gè)時(shí)候,就需要我們提供一個(gè)自動(dòng)化的測試工具,來(lái)完成必要的測試任務(wù)。

    測試工具,首先也是一個(gè)C#的程序,它的主要目的是:

1:獲取上文應用程序的窗口句柄,繼而獲取TextBox句柄及Button句柄;

2:為T(mén)extBox隨機填入一些字符;

3:模擬點(diǎn)擊Button;

1.1:EnumChildWindows介紹

  在這里需要介紹下EnumChildWindows,

EnumChildWindows可是個(gè)好東西,可以枚舉一個(gè)父窗口的所有子窗口:

BOOL EnumChildWindows( 
  HWND hWndParent,        // handle to parent window // 父窗口句柄 
  WNDENUMPROC lpEnumFunc,  // callback function // 回調函數的地址 
  LPARAM lParam            // application-defined value // 你自已定義的參數 
);

    就這么簡(jiǎn)單,讓我們再定義一個(gè)回調函數,像下面這樣:

BOOL CALLBACK EnumChildProc( 
  HWND hwnd,      // handle to child window 
  LPARAM lParam  // application-defined value 
);

    在調用EnumChildWindows 這個(gè)函數時(shí),直到調用到最個(gè)一個(gè)子窗口被枚舉或回調函數返回一個(gè)false,否則將一直枚舉下去。

1.2:簡(jiǎn)單例子的主要源碼

    測試工具的主要代碼如下:

        private void button1_Click(object sender, EventArgs e)        {            //獲取測試程序的窗體句柄            IntPtr mainWnd = FindWindow(null, "FormLogin");            List<IntPtr> listWnd = new List<IntPtr>();            //獲取窗體上OK按鈕的句柄             IntPtr hwnd_button = FindWindowEx(mainWnd, new IntPtr(0), null, "OK");            //獲取窗體上所有控件的句柄            EnumChildWindows(mainWnd, new CallBack(delegate(IntPtr hwnd, int lParam)            {                listWnd.Add(hwnd);                return true;            }), 0);            foreach (IntPtr item in listWnd)            {                if (item != hwnd_button)                {                    char[] UserChar = "luminji".ToCharArray();                    foreach (char ch in UserChar)                    {                        SendChar(item, ch, 100);                    }                }            }            SendMessage(hwnd_button, WM_CLICK, mainWnd, "0");        }        public void SendChar(IntPtr hand, char ch, int SleepTime)        {            PostMessage(hand, WM_CHAR, ch, 0);            System.Threading.Thread.Sleep(SleepTime);        }        public static int WM_CHAR = 0x102;        public static int WM_CLICK = 0x00F5;        [DllImport("User32.dll", EntryPoint = "SendMessage")]        public static extern int SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, string lParam);          [DllImport("user32.dll")]        public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter,            string lpszClass, string lpszWindow);        [DllImport("user32.dll", SetLastError = true)]        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);        [DllImport("user32.dll")]        public static extern int AnyPopup();        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]        public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);        [DllImport("user32.dll")]        public static extern int EnumThreadWindows(IntPtr dwThreadId, CallBack lpfn, int lParam);        [DllImport("user32.dll")]        public static extern int EnumChildWindows(IntPtr hWndParent, CallBack lpfn, int lParam);        [DllImport("user32.dll", CharSet = CharSet.Ansi)]        public static extern IntPtr PostMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);        [DllImport("user32.dll", CharSet = CharSet.Ansi)]        public static extern IntPtr SendMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);               [DllImport("user32.dll", CharSet = CharSet.Unicode)]        public static extern IntPtr SendMessageA(IntPtr hwnd, int wMsg, int wParam, int lParam);               [DllImport("user32.dll", CharSet = CharSet.Auto)]        static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);               [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]        public static extern int GetWindowTextLength(IntPtr hWnd);        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = false)]        public static extern IntPtr GetParent(IntPtr hWnd);              public delegate bool CallBack(IntPtr hwnd, int lParam);

運行效果:

2:難點(diǎn):如何獲取指定的控件句柄

  細心的人可能已經(jīng)發(fā)現,上文中,給文本框賦值的地方,使用了如下代碼:

            foreach (IntPtr item in listWnd)            {                if (item != hwnd_button)                {                    char[] UserChar = "luminji".ToCharArray();                    foreach (char ch in UserChar)                    {                        SendChar(item, ch, 100);                    }                }            }

  假設我們的窗體上有多個(gè)文本框,那么事實(shí)上,這段代碼會(huì )給所有的文本框輸入"luminji”字樣。這在多數應用程序中都是不允許的,我們需要精確定位需要控制的控件。

  我們在得到OK按鈕的句柄的時(shí)候,使用了函數:

IntPtr hwnd_button = FindWindowEx(mainWnd, new IntPtr(0), null, "OK");

  而想要獲取文本框句柄的時(shí)候,這個(gè)函數卻不能使用,因為,所有文本框都是沒(méi)有標題的,也就是類(lèi)似"OK"這個(gè)值。有人說(shuō),那就使用控件ID吧。且看:

2.1:獲取控件ID

  非.NET程序,一旦程序被生成,控件ID就是固定的,所以這一招,用在非.NET程序中,那是再好也不過(guò)了。

   

  根據ID來(lái)得到控件句柄的函數聲明如下:

        [DllImport("user32.dll ", EntryPoint = "GetDlgItem")]        public static extern IntPtr GetDlgItem( IntPtr hParent, int nIDParentItem); 

  其中,第一個(gè)參數就是窗體的句柄,第二個(gè)參數就是控件ID。

  但是,顯然,這種方法不適用于我們的.NET程序,因為我們會(huì )發(fā)現,我們的.NET程序沒(méi)運行一次,這個(gè)ID是變化的。

2.2:獲取控件位置

  所以,最終的一個(gè)方案是:根據控件位置,人工比對后得到我們想要的控件句柄。該函數的聲明如下:

   好了,現在的關(guān)鍵就是怎么取得這個(gè)控件的位置。我們在VS中查看,某個(gè)控件有X坐標和Y坐標,以上面程序的這個(gè)TextBox來(lái)說(shuō),其在VS中顯示的位置是“70,83”,但是而VS中顯示的,是不包含標題和邊框的坐標值。但是這個(gè)坐標值可以作為我們人工比對的參考。 

   更精確的坐標值,我們寫(xiě)代碼來(lái)實(shí)現,如下:

            EnumChildWindows(mainWnd, new CallBack(delegate(IntPtr hwnd, int lParam)            {                listWnd.Add(hwnd);                StringBuilder className = new StringBuilder(126);                StringBuilder title = new StringBuilder(200);                GetWindowText(hwnd, title, 200);                RECT clientRect;                GetClientRect(hwnd, out clientRect);                int controlWidth = clientRect.Width;                int controlHeight = clientRect.Height;                int x = 0, y = 0;                IntPtr parerntHandle = GetParent(hwnd);                if (parerntHandle != IntPtr.Zero)                {                    GetWindowRect(hwnd, out clientRect);                    RECT rect;                    GetWindowRect(parerntHandle, out rect);                    x = clientRect.X - rect.X;                    y = clientRect.Y - rect.Y;                    Debug.Print(x.ToString());                    Debug.Print(y.ToString());                }                return true;            }), 0);
    注意,上面代碼中的X和Y就是某個(gè)控件的精確的X和Y值,記錄下來(lái),比對一下,我們就能得到精確的坐標值了。在上文的例子中,我們的文本框的坐標最終得到為“78,113”。
    有了這個(gè)坐標值,我們便知道這個(gè)控件的句柄,也就是hwnd是屬于哪個(gè)控件的了。

2.3:根據EnumChildWindows枚舉次序得到句柄

    如果你不想這么麻煩,還有一種簡(jiǎn)單的方案,那就是利用EnumChildWindows的枚舉順序。要知道,在不同的機器上,EnumChildWindows枚舉一個(gè)窗體上子控件的順序是相同的,也就是說(shuō),如果有兩個(gè)文本框,它們在這臺機器上被枚舉的順序一個(gè)是2,一個(gè)是3,那么,它們在其它機器上被枚舉的順序,也是這個(gè)固定次序。通過(guò)比對,我們也能得到它們各自的句柄。當然,如果我們有了這些句柄,還有什么是不能做到的呢?

2.4:使用SPY++

    SPY++是微軟的一個(gè)工具,用戶(hù)獲取窗體上的ID或者類(lèi)型或者句柄等信息。因為在我們的這個(gè)例子里,ID和句柄在每臺機器上都是不變的,所以這個(gè)工具對于我們來(lái)說(shuō),沒(méi)有多大的用處。但是,當你HACK別人的程序的時(shí)候,它會(huì )發(fā)揮一定作用。

   

參考:

1:http://book.21www.cn/info/vb/api/4076.html

2:http://dev.firnow.com/course/3_program/cshapo/csharpjs/20100714/441439.html

關(guān)鍵詞:操作  程序  調用  外部  

本站僅提供存儲服務(wù),所有內容均由用戶(hù)發(fā)布,如發(fā)現有害或侵權內容,請點(diǎn)擊舉報。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
Win32 API對文本框發(fā)送消息(多個(gè)文本Edit,動(dòng)態(tài) 控件 ID) - Soma -...
C#自定義控件:WinForm將其它應用程序窗體嵌入自己內部
[原創(chuàng )]C#應用WindowsApi實(shí)現查找\枚舉(FindWindow、EnumChildWindows)窗體控件,并發(fā)送消息。
MsgBox函數
delphi HooK 指定程序窗體和控件的 WndProc
D3D下的窗口式程序
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導長(cháng)圖 關(guān)注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服

欧美性猛交XXXX免费看蜜桃,成人网18免费韩国,亚洲国产成人精品区综合,欧美日韩一区二区三区高清不卡,亚洲综合一区二区精品久久