首页
社区
课程
招聘
[旧帖] 求邀请码--无缝扩充现有应用程序的途径, 0.00雪花
发表于: 2010-10-1 10:07 1138

[旧帖] 求邀请码--无缝扩充现有应用程序的途径, 0.00雪花

2010-10-1 10:07
1138
无缝扩充现有应用程序的途径
-------用户所开发的工具无缝嵌入到应用程序中的途径

王玉英    王平安     徐裕生

摘要:由于通用的商业软件很难满足用户的特殊需求,所以有时需要对这些软件进行扩充,即需要将所开发的工具无缝嵌入到应用程序中。本文在对Windows消息机制、应用程序资源动态连接库等进行分析的基础上,以扩充Word等软件为例,给出了将用户所开发的应用程序无缝嵌入到应用程序中的几种方法。
关键词:窗口过程 资源动态连接库 菜单  Word 无缝嵌入
中图分类号: TP311

目前软件市场上有许多通用的商业软件,这些软件在某种程度上满足了用户的大部分需求,但很难满足用户的所有需求,这就需要对现有软件进行扩充。如何在没有源代码的情况下,为软件增加新的功能?我们在 “十五”军事电子预研重点课题“C3I系统应用软件逆向工程开发工具研究”(编号413060601.x)中成功的解决了这个问题。该课题主要面向军事电子信息系统,通过研究,研制一套逆向工程工具,以提供符合UML标准的动态模型的逆向生成、符合UML标准的静态模型的逆向生成与分层抽象等方面的能力;将这一套工具无缝集成到Rational开发环境中,并与该环境中的其他工具协同工作,以扩充Rational开发环境在与源代码结构和语义相关的工具方面的支持 。
在此课题中,我们所开发的逆向工程工具是一个支持自动化技术的COM进程内组件,通过为Rational Rose2000添加新的菜单项,实现对这个组件的调用,从而把我们所开发的工具无缝集成到Rose中。
   
1.  Windows的消息机制
Windows系统是一个消息驱动的OS。Windows应用程序的输入由Windows系统以消息的形式发送给应用程序的窗口。这些窗口通过窗口过程来接收和处理消息,然后把控制返还给Windows。
从消息的发送途径上看,消息分两种:队列消息和非队列消息。队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。
鼠标、键盘事件由鼠标或键盘驱动程序转换成输入消息并把消息放进系统消息队列,例如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR等等。
应用程序通过消息循环来获得对消息的处理。
每个GDI应用程序在主窗口创建之后,都会进入消息循环,接受用户输入、解释和处理消息。
消息循环从消息队列中得到消息,如果不是快捷键消息或者对话框消息,就进行消息转换和派发,让目的窗口的窗口过程来处理。

图1  Windows消息驱动模型

Windows消息驱动模型如图1所示:

2  Windows应用程序的资源文件
典型的Windows应用程序一般由三部分组成:源程序文件(.c或.cpp)、头文件(.h或.hpp)和资源文件(.rc)。资源文件包含了应用程序所使用的全部资源定义。这里的资源是应用程序所能够使用的一类预定义工具中的一个对象,包括:字符串资源、加速键表、对话框、菜单、位图、光标、工具条、图标、版本信息和用户自定义资源等。
在Windows程序设计过程中,象菜单、对话框、位图等可视的对象被单独分离出来加以定义,并存放在资源源文件中,然后由资源编译程序编译为应用程序所能使用的对象的映象。资源编译使应用程序可以读取对象的二进制映像和具体数据结构,这样可以减轻为创建复杂对象所需要的程序设计工作。
程序员在资源文件中定义应用程序所需使用的资源,资源编译程序编译这些资源并将它们存储于应用程序的可执行文件或动态连接库中。
    下面以大家熟悉的文字处理软件Word为例,说明扩充应用程序菜单的几种具体方法。
3 扩充应用程序的几种方法
我们使用的软件多数是商品化的,开发单位很少开放其源代码,所以我们面对的只是一些二进制文件和几个配置文件,所以我们不可能做到用常规的菜单设计方法对这些商品化软件进行菜单扩充,因为我们没有办法直接得到可修改的资源描述文件。但经过对Windows消息机制、资源动态连接库、软件本身提供的扩充接口进行研究,得到了几种可行的扩充应用程序的方法,下面对这几种方法加以论述。
3.1利用Windows消息机制对应用程序菜单进行扩充
经过对Widows消息机制的分析,我们知道当用户进行了输入或是窗口的状态发生改变时系统都会发送消息到某一个窗口。例如当用户利用鼠标或键盘选中了应用程序的某一菜单项后,会有WM_COMMAND消息发送,WPARAM的高字中(HIWORD(wParam))是命令的ID号,对菜单来讲就是菜单ID。这个消息必须由一个窗口接收。在窗口的过程(WNDPROC)中可以对消息进行分析,对自己感兴趣的消息进行处理。自己不感兴趣的消息交由默认的窗口过程去处理(MS为窗口编写了默认的窗口过程)。系统通过窗口句柄在整个系统中唯一标识一个窗口,发送一个消息时必须指定一个窗口句柄表明该消息由那个窗口接收。而每个窗口都会有自己的窗口过程,所以用户的输入就会被正确的处理。
因此我们很容易想到用下面的方法实现菜单的改变,见图2。

图2  修改应用程序菜单的流程图

我们可以使用几个API函数实现上述任务。例如:
EnumWindows(EnumWinProc,(LPARAM)(GetCurrentProcessId()));
//列举屏幕上所有的顶层窗口、查找当前的进程
GetWindowThreadProcessId(hwnd,&PID);  //获得创建这个窗口的线程标识
GetSystemMenu(hwnd,FALSE);  //获得当前窗口中菜单的句柄
InsertMenu(SysMenu,ItemCount-1, MF_BYPOSITION|MF_STRING,1234,"Reverse...");
//插入新的菜单项
SetWindowLong(hwnd,GWL_WNDPROC,(LONG)WinProc);
//改变目标窗口的处理过程为自定义过程函数Winproc。
用SetWindowLong,可以改变窗口的窗口过程,使其在收到窗口消息时首先进入你的处理函数。这样,就可以在没有源码的情况下改变某些功能。但是有一点要特别注意,这个函数不能跨进程操作,它只能改变函数所在进程的窗口的处理函数。因此,要让这个函数起作用,必须将它注入到目标进程。

从上述方法中我们看到,实现修改菜单的关键是用我们自己定义的窗口函数替换应用程序系统的窗口函数,在上面的方法中,我们使用API函数SetWindowLong实现了这个过程。实际上我们还可以用其它的方法实现这种替换。例如,利用HOOK函数。
钩子(HOOK)是Windows中消息处理机制的一个要点,通过安装各种钩子,应用程序能够设置相应的子例程来监视系统里的消息传递,以及在这些消息到达目的地之前截获它们并根据用户要求做出相应处理。 
3.2  利用Windows消息机制和应用程序资源连接库对应用程序菜单进行扩充
从3.1节的扩充方法中我们看到,其中很重要的一步是得到当前进程的窗口,找到其菜单标识,然后修改菜单。在给出的方法中,使用API完成了这些工作。我们还可以用一种很直观的方法,即利用应用程序的资源动态连接库。
例如,Rose2000是Windows系统下的应用程序,Rational公司并没有开放它的源代码,所以我们没有办法得到可修改的资源描述文件,经过分析我们知道Rose所用到的菜单、图标、对话框等资源都存放在一个外带的动态连接库roseres.dll中,可以利用VC++6.0的资源打开功能(File->Open)打开文件roseres.dll(Open as框选择Resources),这样就可以直接看到资源连接库中的所有资源了,选择要修改的菜单,直接在这个菜单上修改菜单项,如添加菜单项、添加子菜单项、修改菜单项的名称等,还可以直接得到窗口句柄和菜单的标识。最后用这个修改后的资源库替代原来的即可。接着利用API函数改变窗口的处理过程为用户定义的窗口处理过程,便实现了对Rose的菜单修改。如图2所示。

图3  修改应用程序菜单的流程图2
在Word中我们也可以找到包含一部分资源的动态联结库。

值得一提的是,我们还可以利用一些工具直接得到窗口句柄和菜单标识,而不用打开应用程序资源动态连接库。这样的工具有VC++6.0的Spy++、ExeSope、ResourceHake等。
3.3  利用应用程序的菜单配置文件或预留接口对应用程序菜单进行扩充
为了方面用户扩充应用程序,很多软件都为用户预留了扩充接口。例如我们可以使用下面的方法将第三方软件WMF_Saver添加到Word中。WMF_Saver是专为Microsoft Office 2000设计的,目前可用于Powerpoint和Word,可将其中的各种图形对象(如图形、公式、地图、图表、组织结构图、艺术字和文本等)保存为图元文件(WMF文件),它以动态联结库WMF_Saver.dll的形式存在。
扩充步骤:
    1、将WMF_Saver.dll复制到Windows\Application Data\Microsoft\AddIns文件夹内。
    2、启动Powerpoint或Word,单击[工具]菜单>[COM加载项]命令>[COM加载项]对话框>[添加]按钮,在弹出的[添加加载项]对话框内选中“WMF_Saver.dll”,然后一路按[确定]按钮。如图4。扩充的结果如图5所示。
  如果[工具]菜单下无[COM加载项]命令,可在[视图]菜单>[工具栏]>[自定义]命令>[自定义]对话框>[命令]选项卡>[工具]类别内选中“COM加载项”,添加到[工具]菜单下。
  另外,还可可以用以下几种编程语言:Word Basic、VBA(Visual Basic for Applications)和Word API扩充Word。

图4. 扩充Word的过程

图5. Word的扩充结果(菜单中添加了项WMF_Saver)

对于Excel,我们可以将用户的扩充部分(如自己开发的多排表工具)涉及成一个宏文件,让Excel运行时加载。可以将这个宏文件拷贝到Excel的启动目录“C:\Program Files\Microsoft Office\Office\XLStart\”中,也可以拷贝到其他目录,通过“工具(T)”菜单的“加载宏(I)”子菜单进行浏览并选择来实现加载。加载后在“工具(T)”菜单内新增一子菜单(如:多排表工具)。
又如,为了实现菜单扩充,Rose2000将与窗口相关的菜单以一定的语法和语义结构写入到菜单文件(.mnu)中,并将其存放到固定的相关目录下。Rose2000在启动时会自动解析这些存放于某些目录下的菜单文件,并将其与应用程序窗口相关联,从而那些对菜单文件的合法修改都会在工具的界面上得到体现。我们可以通过修改这个菜单文件扩充Rose。我们在项目中采用了这种方法。
  4  三种扩充方法的比较
前面我们介绍了三种扩充应用程序菜单的方法,其中第一种方法适用于一般的应用程序,可以增加、删除、修改主菜单项和子菜单项及其它们的行为,能很好的适应用户的要求。缺点是不够直观。
第二种方法也适用于一般的应用程序,但前提是资源动态连接库中含有需要扩充的菜单窗口。有时应用程序的资源动态连接库没有包含全部的资源。这种方法的优点是比较直观,所以很容易控制菜单的布局。缺点是改变了原系统的资源动态连接库,扩充部分与原系统耦合性太强。
最后一种方法适合于提供扩充接口的系统,如Rational Rose,Word,Excel。这种方法简单易行,虽然它不支持主菜单的扩充,但基本上满足了需要。
5.结束语
从讨论Windows的消息机制入手,提出了扩充应用程序的几种方法,并对这几种方法进行了比较。这几种方法有较强的应用价值。

参考文献:
[1] 侯俊杰 . 深入浅出MFC . 第二版 . 武汉:华中科技大学出版社 . 2001年
[2] David J.Kruglinski,Scot Wingo,George Shepherd . Programming VC++6.0技术内幕(第五版)(修订本).  北京:北京希望电子出版社 . 1999
[3] Rational Software Corp.Online Help Rational Rose 2000
[4] ohn Hsia .Common Questions from Experienced REI Users . Rose Architect . Spring Issue . April 2000 .
[5] John Hsia . Using COM in Your Rose Extensibility Solution Rose Architect . Winter  Issue. January 2000 . Rose Archtect .

[课程]Android-CTF解题方法汇总!

收藏
免费 0
支持
分享
最新回复 (1)
雪    币: 40
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
不知道 为什么 贴不上图
想看图可以到我的博客看
博客地址自己搜吧
只有我的博客有图
2010-10-1 10:09
0
游客
登录 | 注册 方可回帖
返回
//