国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

C#調用API向外部程序發送數據

2019-11-17 03:04:58
字體:
來源:轉載
供稿:網友

C#調用API向外部程序發送數據

C#調用API向外部程序發送數據

最近有可能要做一個項目。在項目中有這么一個功能,在A程序中調用B程序,同時在A程序中進行登陸后,要將A程序的登錄名和密碼自動填充到B程序的登陸對話框中,這樣B程序就不需要再輸入一次用戶名和密碼了,簡化操作人員的操作。剛好最近閑著沒事,就在怎么想怎么去實現。經過兩天的折騰,基本上完成了上述功能的實現。下面就把實現方法、過程與大家進行分享。

一、原理

要實現上述功能,需要調用Win API來實現。Win32 API即為Microsoft 32位平臺的應用程序編程接口(application PRogramming Interface)。所有在Win32平臺上運行的應用程序都可以調用這些函數。

那么在本程序的實現過程中,需要用到以下三個API函數(函數說明均從網上找的,方便大家查看),以及自己編寫的一個FindWindowByIndex函數。

1、static extern int SendMessage1(IntPtr hwnd, uint wMsg, int wParam, int lParam);

顧名思義,SendMessage函數的功能是“發送消息”,即將一條消息發送到指定對象(操作系統、窗口或控件等)上,以產生特定的動作(如滾屏、修改對象外觀等)。

其中四個自變量的含義和說明如下:

hWnd:對象的句柄。希望將消息傳送給哪個對象,就把該對象的句柄作為實參傳送。

wMsg:被發送的消息。根據具體需求和不同的對象,將不同的消息作為實參傳送,以產生預期的動作。

wParam、lParam:附加的消息信息。這兩個是可選的參數,用來提供關于wMsg消息更多的信息,不同的wMsg可能使用這兩個參數中的0、1或2個,如果不需要哪個附加參數,則將實參賦為NULL(在VB中賦為0)。

2、public static extern IntPtr FindWindow(string className, string windowName);

FindWindow函數返回與指定字符創相匹配的窗口類名或窗口名的最頂層窗口的窗口句柄。這個函數不會查找子窗口。

lpClassName:指向一個以null結尾的、用來指定類名的字符串或一個可以確定類名字符串的原子。如果這個參數是一個原子,那么它必須是一個在調用此函數前已經通過GlobalAddAtom函數創建好的全局原子。這個原子(一個16bit的值),必須被放置在lpClassName的低位字節中,lpClassName的高位字節置零。

lpWindowName:指向一個以null結尾的、用來指定窗口名(即窗口標題)的字符串。如果此參數為NULL,則匹配所有窗口名。

返回值:如果函數執行成功,則返回值是擁有指定窗口類名或窗口名的窗口的句柄。如果函數執行失敗,則返回值為 NULL 。可以通過調用GetLastError函數獲得更加詳細的錯誤信息。

3、static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);

在窗口列表中尋找與指定條件相符的第一個子窗口 。該函數獲得一個窗口的句柄,該窗口的類名和窗口名與給定的字符串相匹配。這個函數查找子窗口,從排在給定的子窗口后面的下一個子窗口開始。在查找時不區分大小寫。

hwndParent:要查找的子窗口所在的父窗口的句柄(如果設置了hwndParent,則表示從這個hwndParent指向的父窗口中搜索子窗口)。如果hwndParent為 0 ,則函數以桌面窗口為父窗口,查找桌面窗口的所有子窗口。Windows NT5.0 and later:如果hwndParent是HWND_MESSAGE,函數僅查找所有消息窗口。

hwndChildAfter :子窗口句柄。查找從在Z序中的下一個子窗口開始。子窗口必須為hwndParent窗口的直接子窗口而非后代窗口。如果HwndChildAfter為NULL,查找從hwndParent的第一個子窗口開始。如果hwndParent 和 hwndChildAfter同時為NULL,則函數查找所有的頂層窗口及消息窗口。

lpszClass:指向一個指定了類名的空結束字符串,或一個標識類名字符串的成員的指針。如果該參數為一個成員,則它必須為前次調用theGlobaIAddAtom函數產生的全局成員。該成員為16位,必須位于lpClassName的低16位,高位必須為0。

pszWindow:指向一個指定了窗口名(窗口標題)的空結束字符串。如果該參數為 NULL,則為所有窗口全匹配。

返回值:Long,找到的窗口的句柄。如未找到相符窗口,則返回零。會設置GetLastError如果函數成功,返回值為具有指定類名和窗口名的窗口句柄。如果函數失敗,返回值為NULL。

4、static IntPtr FindWindowByIndex(IntPtr hwndParent, int index)

該函數通過隱含的索引來查找相應的控件。

該函數源代碼如下:

static IntPtr FindWindowByIndex(IntPtr hwndParent, int index)

{

if (index == 0)

return hwndParent;

else

{

int ct = 0;

IntPtr result = IntPtr.Zero;

do

{

result = FindWindowEx(hwndParent, result, null, null);

if (result != IntPtr.Zero)

++ct;

} while (ct < index && result != IntPtr.Zero);

return result;

}

}

二、API調用方法(注:本段文字從網上摘錄)

1、使用相應的命名空間using System.Runtime.InteropServices;

2、使用DllImportAttribute特性來引入api函數,注意聲明的是空方法,即方法體為空。

[DllImport("user32.dll")]

public static extern ReturnType FunctionName(type arg1,type arg2,...);

//調用時與調用其他方法并無區別

可以使用字段進一步說明特性,用逗號隔開,如: [ DllImport( "kernel32", EntryPoint="GetVersionEx" )]

DllImportAttribute特性的公共字段如下:

1、CallingConvention 指示向非托管實現傳遞方法參數時所用的 CallingConvention 值。CallingConvention.Cdecl : 調用方清理堆棧。它使您能夠調用具有 varargs 的函數。CallingConvention.StdCall : 被調用方清理堆棧。它是從托管代碼調用非托管函數的默認約定。

2、CharSet 控制調用函數的名稱版本及指示如何向方法封送 String 參數。

此字段被設置為 CharSet 值之一。如果 CharSet 字段設置為 Unicode,則所有字符串參數在傳遞到非托管實現之前都轉換成 Unicode 字符。這還導致向 DLL EntryPoint 的名稱中追加字母“W”。如果此字段設置為 Ansi,則字符串將轉換成 ANSI 字符串,同時向 DLL EntryPoint 的名稱中追加字母“A”。大多數 Win32 API 使用這種追加“W”或“A”的約定。如果 CharSet 設置為 Auto,則這種轉換就是與平臺有關的(在 Windows NT 上為 Unicode,在 Windows 98 上為 Ansi)。CharSet 的默認值為 Ansi。CharSet 字段也用于確定將從指定的 DLL 導入哪個版本的函數。CharSet.Ansi 和 CharSet.Unicode 的名稱匹配規則大不相同。對于 Ansi 來說,如果將 EntryPoint 設置為“MyMethod”且它存在的話,則返回“MyMethod”。如果 DLL 中沒有“MyMethod”,但存在“MyMethodA”,則返回“MyMethodA”。對于 Unicode 來說則正好相反。如果將 EntryPoint 設置為“MyMethod”且它存在的話,則返回“MyMethodW”。如果 DLL 中不存在“MyMethodW”,但存在“MyMethod”,則返回“MyMethod”。如果使用的是 Auto,則匹配規則與平臺有關(在 Windows NT 上為 Unicode,在 Windows 98 上為 Ansi)。如果 ExactSpelling 設置為 true,則只有當 DLL 中存在“MyMethod”時才返回“MyMethod”。

3、EntryPoint 指示要調用的 DLL 入口點的名稱或序號。

如果你的方法名不想與api函數同名的話,一定要指定此參數,例如:

[DllImport("user32.dll",CharSet="CharSet.Auto",EntryPoint="MessageBox")]public static extern int MsgBox(IntPtrhWnd,string txt,string caption, int type);

4、ExactSpelling 指示是否應修改非托管 DLL 中的入口點的名稱,以與 CharSet 字段中指定的CharSet 值相對應。如果為 true,則當DllImportAttribute.CharSet 字段設置為 CharSet 的Ansi 值時,向方法名稱中追加字母 A,當 DllImportAttribute.CharSet 字段設置為CharSet 的 Unicode 值時,向方法的名稱中追加字母 W。此字段的默認值是 false。

5、PreserveSig指示托管方法簽名不應轉換成返回 HRESULT、并且可能有一個對應于返回值的附加 [out, retval] 參數的非托管簽名。

6、SetLastError指示被調用方在從屬性化方法返回之前將調用 Win32 API SetLastError。 true 指示調用方將調用 SetLastError,默認為 false。運行時封送拆收器將調用 GetLastError 并緩存返回的值,以防其被其他 API 調用重寫。用戶可通過調用 GetLastWin32Error 來檢索錯誤代碼。

三、程序實現過程

程序A:兩個文本框與一個啟動按鈕。兩個文本框用來輸入用戶名和密碼,啟動按鈕用來啟動程序B。

程序B:兩個文本框,用來接受程序A所發送過來的字符串。

1、A程序代碼清單如下:

using System.Runtime.InteropServices;

using System.Threading;

private staticSystem.Diagnostics.Process p;

[DllImport("user32.dll", EntryPoint = "SendMessage", CharSet = CharSet.Unicode)]

static extern int SendMessage1(IntPtrhwnd, uint wMsg, intwParam, int lParam);

[DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true, CallingConvention = CallingConvention.Winapi,CharSet = CharSet.Unicode)]

public static extern IntPtrFindWindow(string className, string windowName);

[DllImport("user32.dll", EntryPoint = "FindWindowEx", CharSet = CharSet.Auto)]

static extern IntPtr FindWindowEx(IntPtrhwndParent, IntPtr hwndChildAfter, string lpszClass, stringlpszWindow);

static IntPtrFindWindowByIndex(IntPtr hwndParent, int index)

{

if(index == 0)

returnhwndParent;

else

{

intct = 0;

IntPtrresult = IntPtr.Zero;

do

{

result =FindWindowEx(hwndParent, result, null, null);

if(result != IntPtr.Zero)

++ct;

} while(ct < index && result != IntPtr.Zero);

returnresult;

}

}

2、啟動按鈕事件代碼

privatevoid button4_Click(objectsender, EventArgs e)

{

if(p == null)

{

p = newSystem.Diagnostics.Process();

p.StartInfo.FileName =”B程序Path”;

p.Start();

//必須讓線程掛起一定時間,否則字符串不能自動發送過去。

Thread.Sleep(500);

IntPtrParenthWnd = new IntPtr(0);

IntPtrpp = new IntPtr(0);

IntPtrmwh = IntPtr.Zero;

//通過窗口標題來獲取窗口

ParenthWnd = FindWindow(null, "******");

//通過索引來獲取B程序的文本編輯框,通過索引先獲取該控件的ID,然后將該ID轉換為16進制,與Spy++查看到ID進行對比,從而確定控件的索引。

IntPtrbutt = FindWindowByIndex(ParenthWnd, 5);

uintWM_CHAR = 0x0102;

// SendMessage1每次發送一個字符串,所以通過循環發送完整用戶名

foreach(char c in this.textBox1.Text)

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 临夏市| 孙吴县| 通榆县| 哈尔滨市| 沙田区| 台安县| 香河县| 柳州市| 青冈县| 富川| 沙田区| 上蔡县| 昌宁县| 临漳县| 化德县| 韩城市| 武城县| 垦利县| 鹤岗市| 贡觉县| 贵溪市| 鄂托克旗| 山阴县| 黄龙县| 汉阴县| 夏河县| 斗六市| 沁源县| 攀枝花市| 木兰县| 临清市| 晋城| 新津县| 云阳县| 平武县| 中牟县| 沙坪坝区| 崇左市| 西昌市| 延川县| 衡阳县|