C#中用WinAPI调用外部程序.docx
《C#中用WinAPI调用外部程序.docx》由会员分享,可在线阅读,更多相关《C#中用WinAPI调用外部程序.docx(23页珍藏版)》请在冰点文库上搜索。
C#中用WinAPI调用外部程序
C#中用WinAPI调用外部程序
分类:
WINFORM技术(C#)2012-02-1721:
5636人阅读评论(0)收藏举报
使用别人的程序时,我们常发现一些好的功能,想通过自己的程序来重复调用。
可偏偏这个程序没有留可编程接口,无法通过API、DLL、COM等方式实现调用。
早些年与同仁们讨论时,常对此深表遗憾。
最近,通过研究WindowsAPI的使用方法,终于从理论上解决了这一问题,即可通WinAPI中SendMessage、EnumChildWindows等,从模拟操作的角度来调用指定程序的指定功能。
我们知道,Windows是消息驱动的,即Windows窗口、控件的任何操作,都是通过消息事件来完成的。
从理论上讲,在我们自己的程序中,只要能准确地找到相应功能所在的窗口或控件的句柄Handle,发出相应的消息,即可完成相应任务。
从这个层面上,这种技术可以应用在所有windows程序上。
只是这种技术的处理,需要非常细心。
因为在实际应用中,从某一个程序中找到相应的控件(包括Parent/Child/Next等)还是比较麻琐的,一不小心,调用的功能就实法实现,还有可能导致程序甚至系统的崩溃。
所以,这种技术的关键在于两个地方:
一是找准句柄,二是找对消息。
推荐分析一个窗体(控件)的句柄或消息的工具:
SPY++,这在VisualStudioTools中有,操作起来很简单。
C#中实现外部程序调用,可以通过封装User32.dll中sendmessage等函数来实现。
我已将常用的功能封装成一个类:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Runtime.InteropServices;
namespaceMuliCall
{
classWinApi
{
#region 宏定义
publicconstintWM_KEYDOWN=0x100;
publicconstintWM_KEYUP=0x101;
publicconstintVK_CONTROL=0x11;
publicconstintVK_F5=0x74;
publicconstintKEYEVENTF_KEYUP=0x2;
publicconstintVK_MENU=0x12;
publicconstintWM_SETTEXT=0xC;
publicconstintWM_CLEAR=0x303;
publicconstintBN_CLICKED=0;
publicconstintWM_LBUTTONDOWN=0x201;
publicconstintWM_LBUTTONUP=0x202;
publicconstintWM_CLOSE=0x10;
publicconstintWM_COMMAND=0x111;
publicconstintWM_SYSKEYDOWN=0x104;
#endregion
publicdelegateboolEnumChildWindowsProc(IntPtrhwnd,intlParam);
#region WinAPI定义
[DllImport("User32.dll",EntryPoint="SendMessage")]
publicstaticexternintSendMessage(
inthWnd,//handletodestinationwindow
intMsg,//message
intwParam,//firstmessageparameter
intlParam//secondmessageparameter
);
[DllImport("User32.dll",EntryPoint="SendMessage")]
publicstaticexternintSendTxtMessage(
inthWnd,//handletodestinationwindow
intMsg,//message
intwParam,//firstmessageparameter
char[]lParam
//int lParam//secondmessageparameter
);
[DllImport("user32.dll",EntryPoint="PostMessage")]
publicstaticexternintPostMessage(
inthwnd,
intwMsg,
intwParam,
intlParam
);
[DllImport("user32.dll",EntryPoint="FindWindow")]
publicstaticexternintFindWindow(
stringlpClassName,
stringlpWindowName
);
[DllImport("user32.dll",EntryPoint="FindWindowEx")]
publicstaticexternintFindWindowEx(
inthwndParent,
inthwndChildAfter,
stringlpszClass,
stringlpszWindow
);
[DllImport("user32.dll",EntryPoint="EnumChildWindows")]
publicstaticexternintEnumChildWindows(
inthWndParent,
intlpEnumFunc,
intlParam
);
[DllImport("user32.dll",EntryPoint="EnumChildWindows")]
publicstaticexternintEnumChildWindows(
inthWndParent,
EnumChildWindowsProclpEnumFunc,
intlParam
);
[DllImport("user32.dll",EntryPoint="SetFocus")]
publicstaticexternintSetFocus(
inthWnd
);
[DllImport("user32.dll",EntryPoint="SetWindowText")]
publicstaticexternintSetWindowText(
inthwnd,
stringlpString
);
[DllImport("user32.dll",EntryPoint="keybd_event")]
publicstaticexternvoidkeybd_event(
bytebVk,
bytebScan,
intdwFlags,
intdwExtraInfo
);
[DllImport("user32.dll",EntryPoint="SetForegroundWindow")]
publicstaticexternintSetForegroundWindow(
inthwnd
);
[DllImport("user32.dll",EntryPoint="GetClassName")]
publicstaticexternintGetClassName(
IntPtrhwnd,
StringBuilderlpClassName,
intnMaxCount
);
[DllImport("user32.dll",EntryPoint="GetWindowText")]
publicstaticexternintGetWindowText(
IntPtrhwnd,
StringBuilderlpString,
intcch
);
#endregion
//综合处理全局HWD
privatestaticintCurrnetFormHandle=0;
//综合处理函数
publicstaticvoidSetCurrnetFormHandle(stringstrWindow)
{
SetCurrnetFormHandle(null,strWindow,false);
}
publicstaticvoidSetCurrnetFormHandle(stringstrClass,stringstrWindow,boolbeForeground)
{
CurrnetFormHandle=FindWindow(strClass,strWindow);
if(beForeground)
SetForegroundWindow(CurrnetFormHandle);
}
publicstaticvoidSetCurrnetFormHandle(inthwd,boolbeForeground)
{
CurrnetFormHandle=hwd;
if(beForeground)
SetForegroundWindow(CurrnetFormHandle);
}
publicstaticvoidSetCurrnetFormHandle(inthwd)
{
CurrnetFormHandle=hwd;
}
publicstaticintGetCurrentFormHandle()
{
returnCurrnetFormHandle;
}
//模拟单击按钮
publicstaticvoidClickButton(stringstrWindow)
{
ClickButton("Button",strWindow);
}
publicstaticvoidClickButton(stringstrClass,stringstrWindow)
{
ClickButton(CurrnetFormHandle,0,strClass,strWindow);
}
publicstaticvoidClickButton(inthwdParent,inthwndChildAfter,stringstrClass,stringstrWindow)
{
inthwdButton=FindWindowEx(hwdParent,hwndChildAfter,strClass,strWindow);
SendMessage(hwdButton,WM_LBUTTONDOWN,0,0);
SendMessage(hwdButton,WM_LBUTTONUP,0,0);
}
//修改文本框内容
publicstaticvoidSetWindowsText(stringParnet_strClass,stringParnet_strText,stringstrClass,stringstrText)
{
inthwdParent=FindWindowEx(CurrnetFormHandle,0,Parnet_strClass,Parnet_strText);
//停止ThunderRT6OptionButton
intbntHwd=FindWindowEx(hwdParent,0,"ThunderRT6OptionButton","停止");
inthwdText=FindWindowEx(hwdParent,bntHwd,strClass,null); //ThunderRT6TextBox
SendTxtMessage(hwdText,WM_SETTEXT,0,strText.ToCharArray());
}
publicstaticvoidSetWindowsText(stringstrClass,stringstrText)
{
SetWindowsText(strClass,null,strText);
}
publicstaticvoidSetWindowsText(stringstrClass,stringstrWindow,stringstrText)
{
SetWindowsText(CurrnetFormHandle,0,strClass,strWindow,strText);
}
publicstaticvoidSetWindowsText(inthwdParent,inthwndChildAfter,stringstrClass,stringstrWindow,stringstrText)
{
inthwdText=FindWindowEx(hwdParent,hwndChildAfter,strClass,strText);
SendTxtMessage(hwdText,WM_SETTEXT,0,strText.ToCharArray());
}
//搜索子窗体
publicstaticvoidSearchChild(stringstrWindow)
{
EnumChildWindowsProcmyEnumChild=newEnumChildWindowsProc(EumWinChiPro);
try
{
EnumChildWindows(CurrnetFormHandle,myEnumChild,0);
}
catch(Exceptionex)
{
; //MessageBox.Show(ex.Message+"\r\n"+ex.Source+"\r\n\r\n"+ex.StackTrace.ToString());
}
}
publicstaticboolEumWinChiPro(IntPtrhWnd,intlParam)
{
StringBuilders=newStringBuilder(1256);
GetClassName(hWnd,s,1257);
stringss=s.ToString();
if(ss==null)
ss="";
ss=ss.Trim();
// MessageBox.Show(ss);
//ThunderRT6TextBox
StringBuilders2=newStringBuilder(1256);
GetWindowText(hWnd,s2,1257);
ss=s2.ToString();
returntrue;
}
}
}
使用这个类,在自己的程序中,比较方便地实现外部程序的调用。
inthwnd=(int)MainHandlArray[i];
WinApi.SetCurrnetFormHandle(hwnd);
WinApi.SetWindowsText(textBox_Class_EditPanel.Text,
textBox_Title_EditPanel.ToString(),textBox_Class_Edit.Text,textBoxWorkID.Text);
使用这种方法,我写个程序多开器,主要实现启动多个实例,能给EDIT框付值,能定时调用其中按钮。
C#中实现外部程序调用,可以通过封装User32.dll中sendmessage等函数来实现。
我已将常用的功能封装成一个类:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Text;
usingSystem.Runtime.InteropServices;
namespaceMuliCall
{
classWinApi
{
#region 宏定义
publicconstintWM_KEYDOWN=0x100;
publicconstintWM_KEYUP=0x101;
publicconstintVK_CONTROL=0x11;
publicconstintVK_F5=0x74;
publicconstintKEYEVENTF_KEYUP=0x2;
publicconstintVK_MENU=0x12;
publicconstintWM_SETTEXT=0xC;
publicconstintWM_CLEAR=0x303;
publicconstintBN_CLICKED=0;
publicconstintWM_LBUTTONDOWN=0x201;
publicconstintWM_LBUTTONUP=0x202;
publicconstintWM_CLOSE=0x10;
publicconstintWM_COMMAND=0x111;
publicconstintWM_SYSKEYDOWN=0x104;
#endregion
publicdelegateboolEnumChildWindowsProc(IntPtrhwnd,intlParam);
#region WinAPI定义
[DllImport("User32.dll",EntryPoint="SendMessage")]
publicstaticexternintSendMessage(
inthWnd,//handletodestinationwindow
intMsg,//message
intwParam,//firstm