PctGL SERIES  
http://pctgl.cnblogs.com

跨进程共享数据,常用的方法是共享内存,消息交换等方式

近日研究了一个以采用 DLL 共享节区方式达到目的的方法

以 M$ Link.exe 6.0 为基础测试了 Masm32,VB6 均达到预想效果,公布方法方便大家使用


1. VB 编译的 PE 文件中的节区

节区是 PE 文件储存数据的地方,段是编程时数据及代码等存储的空间,VB编程 根本就接触不到这些

VB 编译的 PE 文件通常包括这几个 .data .text .rsrc .reloc

其中 .data 保存着有初值的公共变量; .text 保存着代码; .rsrc 是PE文件资源节

.reloc 一般在 DLL 中存在,是重定位信息


节包含代码或数据。与段不同,节是连续内存的块,没有大小限制。

有些节包含程序声明和直接使用的代码或数据,而有些数据节是由链接器和库管理器 (lib.exe) 创建的,

包含了对操作系统来说至关重要的信息。



2. 节区的属性

节区都是有属性的,包括 7 个属性:

字符

    属性              

     含意

 E

   Execute

节是可执行的

 R

   Read

允许对数据进行读取操作

 W

   Write

允许对数据进行写操作

 S

   Shared

在所有加载图像的进程中共享节

 D

   Discardable

将节标记为可放弃

 K

   Cacheable

将节标记为不可缓存

 P

   Pageable

将节标记为不可分页


Shared( S ) 属性是我们需要的,在编译时添加这个编译参数就可以达到将指定节共享的目的


3.  操作方法

M$ 的 Link.exe 6.0↑ 有这样一个编译参数,可以达到修改节区属性的功能:
/SECTION:name,[[!]{DEKPRSW}][,ALIGN=#]
   
/SECTION:节名,可选的属性列表,对齐方式



我们需要做的是,在编译参数中添加:

                 /SECTION:.BSS,S                  


/SECTION: 编译参数关键字

.BSS      .data? 节的别名,在编译器内部有一些保留(默认)的节名,
           一般情况下 .data? 这个节会被识别成.BSS并且被编译到 PE 文件中
           但在大多数的情况下,VB的编译器会忽略此节,并将此节与其他节合并,如 .data

,S        设置为共享属性, .BSS 的默认属性即有可读/写属性,这里只是添加了一个共享属性


VB6 的实现方法:

在VB编译 DLL 的时候,拦截连接动作,添加这个参数就可以了

你可以预先编译一个程序取名为 Link.exe 保存在 VB6 程序目录中,把原 Link.exe 改名为 Link32.exe

自己编译的 Link.exe 在代码中获取 启动参数( Command$ ),再完成修改后 Shell Link32.exe + 参数

如果觉得我说了半天你没看懂,那就把 VB6 目录里面的 Link.exe 改名为 Link32.exe ,然后
下载下面的

 Link.exe 程序, 放到你的 VB6 目录中, 当点击编译时会弹出一个对话框, TextBox 里面的字符串就是

本次的连接参数, 添加上面说的参数,然后关闭这个程序即可


4.  使用方法

首先: ...

我发现我应该按照操作顺序来写这篇文章, 但事以至此也就这么着了...

用实例来测试 + 应用:

新建一个 DLL 工程, 添加 1 个标准模块, 1 个类 (默认的类属性即可,不要修改)

在模块中:

Public TestGlobalVariable As Long ' 添加一个 测试用的全局变量

类模块中:

Function cGetValue() As Long
cGetValue =
TestGlobalVariable
End Function


Function cSetValue( AnyValue As Long ) As Long
TestGlobalVariable = AnyValue
End Function

用上面介绍的连接方法编译为一个 DLL, 注意将工程改个名,别用默认的 工程1

否则,可能因为你系统中注册过这个名,导致这个 DLL 不能用, 比如改成  TestSharedField



新建一个标准 Exe 工程: 添加 1 个 TextBox , 2 个 CommandButton(分别命名为 SetValue/GetValue)

引用刚才编译完的 DLL

Dim i As New
TestSharedField.Class1

Private Sub SetValue_Click()
MsgBox i.cGetValue
End Sub

Private Sub GetValue_Click()
i.cSetValue Text1
End Sub

编译这个 Exe 为 A.exe 的时候,就不要添加那个 编译参数了,直接编译就行了



都弄完了,现在就可以测试了...

测试部分就不多说了, 打开 2 次 A.exe ,分别给 TextBox 赋值后,点 SetValue 按钮给全局变量赋值

然后再点击另外窗口的 GetValue 按钮看看 Msgbox 显示的数字是不是刚才再另外一个窗口里面赋的值


.....

不行了.... 写太多了,我就先不传附件了,有兴趣的大家自己试试吧....



5.  应用

最主要,也是这个功能的最根本的出发点就是跨进程的通信了.

1. 只能运行程序的一个副本的功能,如果使用这个方法实现, 那简直无敌了....(别真以为无敌)

不过相对的比其他方法真是方便,简单,安全多了,但这适合大工程,那些挂了几个 DLL 的工程


2. 全局钩子也可以用这个功能实现跨进程通信, 比起共享内存简单多了吧.有的钩子因为必须挂 DLL

那正好设置一个共享节,来通信.


3. 其他.... 有待开发


4. (未完不续) ...
posted on 2009-08-06 17:00  PctGL  阅读(1883)  评论(2编辑  收藏  举报