什么是句柄(编译原理句柄是什么意思)


(相关资料图)

小编工作的单位性质偏向于服务制造。大家都知道,中国的高端装备基本都依赖进口,而其自带CAM软件一般都是全封闭的,不开放API接口。但是在工业互联网时代,设备联网,生产数据上云已经是大势所趋。那么,如何在国外技术封锁的情况下实现第三方软件的数据获取呢?

在Windows系统下,有一个东西叫句柄,它是Windows编程的基础,只要是运行在Windows上的软件都绕不开它。本文就带大家学习如何利用底层句柄来实现第三方软件的交互。

句柄及其作用

关于句柄的官方解释就不在此处过多提及,一般刚接触这个概念的人也看不懂。掌握句柄只需要理解这几点:

1、句柄不是什么玄乎的东西,它只是一个4字节(64系统下为8字节,后续文章都以32位来展开文章)的数值。但是它是唯一的,系统在启动时会建立一个句柄表,程序在Windows系统上运行时由系统自动分配给每一个对象,例如:窗体句柄、窗体控件句柄(输入框、按钮)、文件句柄等。

2、句柄单独存在于一块固定的区域,由于对象在内存中的地址可能会实时变化,但是系统会将这个变化的地址通过唯一不变的句柄绑定好,以不变应万变。

3、你可以将其理解成类似指针,通过它你能找到程序中的每一个对象。

4、虽然句柄类似指针,可以通过句柄找到对应的对象,但是你却不能像使用指针那样使用句柄,必须通过系统封装的API去使用。

如下图,是通过spy++查看GifCam(一个第三方gif制作小软件)各控件的句柄。图中Handle:000A07F0就是Rec按钮的句柄,获得了它的句柄,就可以通过系统API控制按钮的各项功能,比如单击开始录制。

spy++查看GifCam

类比理解

如果上述表述大家还不能理解的话,请看类比理解:

大家都看过古装电视剧吧?在古代,每个奴隶身上都会被烙上一个奴隶印记,并且每个印记的编号不同。奴隶主在管理奴隶时,都是通过印记来管理的。但是每个奴隶本身也都是有名字的。类比到句柄就可以这样理解:奴隶这个实物就是对象,他的名字就是他在计算机中的地址(名字可以随意变,奴隶想更名改姓重新开始生活,但是奴隶主会愿意吗?),奴隶印记就是句柄(不管你怎么更名改姓,只要这个奴隶印记在,你就跑不掉)。

图示理解:

句柄示意图

句柄实际应用

前文讲了很多关于句柄理解的内容,此处开始回到实际项目中,一起探究句柄在实际项目中如何发挥作用。

需求:如下图,需要实时获取图中振幅和相位的值。

需获取数据的窗体

程序设计思路:

程序设计思路

利用CSharp实现上述功能需要引入usingSystem.Runtime.InteropServices;和using System.Diagnostics;

System.Diagnostics:负责进程相关

System.Runtime.InteropServices:DllImport特性,负责调用系统API。

代码实现:

classProgram{//系统API//通过窗体标题寻找窗体句柄[DllImport("user32.dll",EntryPoint="FindWindow")]publicstaticexternIntPtrFindWindow(stringlpClassName,stringlpWindowName);//遍历主窗体下的所有句柄(各控件对象)[DllImport("user32.dll",EntryPoint="FindWindowEx")]publicstaticexternIntPtrFindWindowEx(IntPtrhWnd1,IntPtrhWnd2,stringlpsz1,stringlpsz2);//通过对象句柄获取控件文字内容[DllImport("user32.dll",SetLastError=true,CharSet=CharSet.Auto)]publicstaticexternintGetWindowText(IntPtrhWnd,StringBuilderlpString,intnMaxCount);//通过对象句柄获取控件类名[DllImport("user32.dll",SetLastError=true,CharSet=CharSet.Auto)]publicstaticexternintGetClassName(IntPtrhWnd,StringBuilderlpString,intnMaxCount);//通过对象句柄给对象发系统消息(系统定义的消息标识:如单击、输入文字等)[DllImport("User32.dll",EntryPoint="SendMessage")]publicstaticexternintSendMessages(IntPtrhWnd,//信息发往的窗口的句柄intMsg,//消息IDintwParam,//参数1intlParam//参数2);//---------------------------staticvoidMain(string[]args){boolfind=false;IntPtrhwnd=IntPtr.Zero;while(!find){stringtitle=null;Process[]process=Process.GetProcesses();foreach(Processpinprocess){title=p.MainWindowTitle.ToString();if(title.Contains("iBalance")){hwnd=p.Handle;find=true;break;}}//Console.WriteLine(title);if(find)hwnd=FindWindow(null,title);else{ProcessStartInfoinfo=newProcessStartInfo(@"C:\ProgramFiles\ANCA\RN31.1-1\TG7\BIN\Vibe_Monitor.exe");Process.Start(info);Thread.Sleep(1000);Console.WriteLine("openit");}}find=false;if(hwnd!=IntPtr.Zero){StringBuildersb_text=newStringBuilder(1024);StringBuildersb_class=newStringBuilder(1024);IntPtrchild=IntPtr.Zero;do{child=FindWindowEx(hwnd,child,null,null);GetWindowText(child,sb_text,sb_text.Capacity);//Console.Write(sb_text.ToString()+"::CLASS::");GetClassName(child,sb_class,sb_class.Capacity);//Console.WriteLine(sb_class.ToString());if(sb_text.ToString().Contains(".")&&sb_class.ToString()=="Static"){find=true;break;}sb_text.Remove(0,sb_text.Length);sb_class.Remove(0,sb_class.Length);}while(child!=IntPtr.Zero);StringBuildermsg=newStringBuilder();if(find){inti=0;stringmsg_combine=string.Empty;try{while(true){Thread.Sleep(10);sb_text.Remove(0,sb_text.Length);GetWindowText(child,sb_text,sb_text.Capacity);intindex=sb_text.ToString().IndexOf("\n");msg_combine=DateTime.Now.ToString()+":"+"震幅:"+sb_text.ToString().Substring(0,index)+"相位:"+sb_text.ToString().Substring(index+1,sb_text.ToString().Length-index-1);i++;Console.WriteLine(msg_combine+"::"+i);msg.AppendLine(msg_combine);if(i==1024){i=0;StreamWritersw=newStreamWriter("msg.txt",true,Encoding.UTF8);sw.WriteLine(msg.ToString());msg=newStringBuilder();sw.Flush();sw.Close();}}}catch(Exceptionex){Console.WriteLine(ex.Message);Console.WriteLine("程序被关闭");}}}Console.Read();}}

推荐内容