《2022年Api用C#调用WindowsAPI和其它进程通信 .pdf》由会员分享,可在线阅读,更多相关《2022年Api用C#调用WindowsAPI和其它进程通信 .pdf(7页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、用 C#调用 Windows API 和其它进程通信作者:边城浪子 2005-01-16 关键字:C#,API,FindWindow,FindWindowEx,SendMessage,进程,注册表设计初衷:公司为了便于网络管理,使用了IEEE 802.1X 的网络访问控制,这样每次开机需要输入两次登录密码,于是我就研究了一下用C#来帮我输入第二此登录的密码设计思想:主要是通过调用 Windows API 中的一些方法,主要使用的也就是FindWindow,FindWindowEx和 SendMessage 这三个函数,循环遍历当前的所有窗口,找到目标窗口和进程以后把保存在特定位置的用户名密码以
2、及域信息自动填入输入框中,然后再触发一下button 事件,最后程序本身退出。环境:在 Windows 2000中文版 +sp4,VS.net 2003 中文版下开发在 Windows 2000中文版下测试通过程序截图:具体设计这个 Form的代码就略过不详细说了为了使用 Win32 API,需要先引入下面这个命名空间:using System.Runtime.InteropServices;另外还需要用到进程和注册表,所以还需要引入下面的两个命名空间:名师资料总结-精品资料欢迎下载-名师精心整理-第 1 页,共 7 页 -using System.Threading;using Micros
3、oft.Win32;下面的代码是用来添加对API 的引用:#region Dll Import DllImport(User32.dll,EntryPoint=FindWindow)privatestaticextern IntPtr FindWindow(string lpClassName,string lpWindowName);DllImport(user32.dll,EntryPoint=FindWindowEx)privatestaticextern IntPtr FindWindowEx(IntPtr hwndParent,IntPtr hwndChildAfter,string
4、 lpszClass,string lpszWindow);DllImport(User32.dll,EntryPoint=SendMessage)privatestaticexternint SendMessage(IntPtr hWnd,int Msg,IntPtr wParam,string lParam);#endregion主要用到的就是这三个方法,具体的我这里就不详细介绍了,请参考MSDN。需要用到的一些参数:constint WM_GETTEXT=0 x000D;constint WM_SETTEXT=0 x000C;constint WM_CLICK=0 x00F5;从名称上应
5、该就可以了解这些参数具体的含义是什么了,而且这些参数都可以通过 VS附带的工具 Spy+查到。下面是整个程序的核心部分,查找窗体并对它进行操作:#region SearchWindow privateint SearchWindow()int retval=0;/增加一个返回值用来判断操作是否成功 /下面的这些参数都可以用Spy+查到名师资料总结-精品资料欢迎下载-名师精心整理-第 2 页,共 7 页 -string lpszParentClass=#32770;/整个窗口的类名string lpszParentWindow=本地连接;/窗口标题string lpszClass=Edit;/需
6、要查找的子窗口的类名,也就是输入框string lpszClass_Submit=Button;/需要查找的 Button 的类名string lpszName_Submit=确定;/需要查找的 Button 的标题string text=;IntPtr ParenthWnd=new IntPtr(0);IntPtr EdithWnd=new IntPtr(0);/查到窗体,得到整个窗体 ParenthWnd=FindWindow(lpszParentClass,lpszParentWindow);/判断这个窗体是否有效if (!ParenthWnd.Equals(IntPtr.Zero)/得
7、到 User Name这个子窗体,并设置其内容 EdithWnd=FindWindowEx(ParenthWnd,EdithWnd,lpszClass,);if (!EdithWnd.Equals(IntPtr.Zero)text=this.tbUserName.Text.Trim();/调用 SendMessage 方法设置其内容 SendMessage(EdithWnd,WM_SETTEXT,(IntPtr)0,text);retval+;/得到 Password 这个子窗体,并设置其内容 EdithWnd=FindWindowEx(ParenthWnd,EdithWnd,lpszClas
8、s,);if (!EdithWnd.Equals(IntPtr.Zero)text=this.tbPassword.Text.Trim();SendMessage(EdithWnd,WM_SETTEXT,(IntPtr)0,text);retval+;/得到 Domain这个子窗体,并设置其内容 EdithWnd=FindWindowEx(ParenthWnd,EdithWnd,lpszClass,);if (!EdithWnd.Equals(IntPtr.Zero)名师资料总结-精品资料欢迎下载-名师精心整理-第 3 页,共 7 页 -text=this.tbDomain.Text.Trim
9、();SendMessage(EdithWnd,WM_SETTEXT,(IntPtr)0,text);retval+;/得到 Button 这个子窗体,并触发它的Click 事件 EdithWnd=FindWindowEx(ParenthWnd,EdithWnd,lpszClass_Submit,lpszName_Submit);if (!EdithWnd.Equals(IntPtr.Zero)SendMessage(EdithWnd,WM_CLICK,(IntPtr)0,0);retval+;return retval;#endregion这里有一点需要说明的是,当一个窗体下面有几个类名相同
10、的子窗体时,也就是说如果有三个输入框,这三个输入框的类名都是Edit,查找结果是依次从上往下的,最开始我不知道该怎么办才能分出具体的每个不同的输入框,后来只能这样一个一个来查找来试一下,没想到居然是对的。(有别的办法么?)上面的这段代码也只适用于中文版的操作系统,因为不同的操作系统下同一个窗体的名称都是不一样的,我这里也没有英文版的系统,所以也没办法进行测试。为了免去每次都让用户手动输入的烦恼,我需要把这些信息都保存到一个特定的文件里面去,当用户在第一次运行这个程序的时候,只需要输入一次,点下Save,先把这些信息保存到一个文件中,然后再把程序本身加载到系统启动项里去,这样下次开机的时候程序就
11、可以自启动,然后从文件中读取信息完成以下的操作。选择存放文件的路径:privatestring UserPro=System.Environment.GetEnvironmentVariable(USERPROFILE);privatestring PATH=System.Environment.GetEnvironmentVariable(USERPROFILE)+Local SettingsAutoLog.ini;当用户点下 Save按钮所触发的事件:名师资料总结-精品资料欢迎下载-名师精心整理-第 4 页,共 7 页 -#region Button Submit Click privat
12、evoid btSubmit_Click(object sender,System.EventArgs e)SaveData();privatevoid SaveData()try /Save Data FileInfo obj=new FileInfo(PATH);if(obj.Exists)obj.Delete();FileStream ofile=new FileStream(PATH,FileMode.Create);/Hidden the file File.SetAttributes(PATH,FileAttributes.Hidden);StreamWriter sw=new S
13、treamWriter(ofile);/把用户名密码和域信息写入文件 sw.WriteLine(this.tbUserName.Text);sw.WriteLine(this.tbPassword.Text);sw.WriteLine(this.tbDomain.Text);sw.Flush();sw.Close();ofile.Close();/把当前文件拷贝到指定位置,然后再添加到注册表的启动项里string opath=Application.StartupPath+Login.exe;string tpath=UserPro+Local SettingsLogin.exe;if(Fil
14、e.Exists(tpath)File.Delete(tpath);File.Copy(opath,tpath);RegistryKey hklm=Registry.CurrentUser;RegistryKey run=hklm.CreateSubKey(SOFTWAREMicrosoftWindowsCurrentVersionRun);run.SetValue(AutoLogin,tpath);/最后程序退出 MessageBox.Show(OK,Information,MessageBoxButtons.OK,MessageBoxIcon.Information);Applicatio
15、n.Exit();名师资料总结-精品资料欢迎下载-名师精心整理-第 5 页,共 7 页 -catch(Exception ex)MessageBox.Show(ex.ToString(),Error,MessageBoxButtons.OK,MessageBoxIcon.Error);#endregion这样的话,程序就可以从文件中读取已经存放好的信息来进行验证了。最后要做的就是,需要单独开一个进程来循环执行上面的SearchWindow这个方法,直到找到符合条件的窗口并成功验证为止,并且这个进程需要随程序的启动而启动。我们可以在构造函数中添加一个名为LoadData 的方法,然后在这个方法中
16、进行具体的读文件信息和启动进程的操作。当然,先定义好这个进程:private Thread thread;然后是 LoadData 这个方法:#region Load privatevoid LoadData()/Load Data FileStream ofile=new FileStream(PATH,FileMode.OpenOrCreate);StreamReader sr=new StreamReader(ofile);this.tbUserName.Text=sr.ReadLine();this.tbPassword.Text=sr.ReadLine();this.tbDomain
17、.Text=sr.ReadLine();sr.Close();ofile.Close();/Thread Start thread=new Thread(new ThreadStart(Watch);thread.IsBackground=true;thread.Start();名师资料总结-精品资料欢迎下载-名师精心整理-第 6 页,共 7 页 -privatevoid Watch()/循环查找这个窗口,直到成功为止while(true)int i=this.SearchWindow();if(i=4)break;/程序退出并释放资源 Application.Exit();this.Dispose();this.Close();#endregion名师资料总结-精品资料欢迎下载-名师精心整理-第 7 页,共 7 页 -