处理程序多重启动
   作者:AoGo 于2003-9-12上传 

  建议使用MASM for EditPlus进行测试。
  正如"防止程序多重启动"一文所说,当已经知道自己的实例在运行了,为了节省资源,下个实例需要退出,可是用户需要打开文件,如果不处理就退出,那用户不破口大骂才怪,所以,就需要退出之前进行处理。
  首先要讲一个小知识,当Windows程序退出的时候,Windows会自己清除当前进程所占用的所有资源,除了动态DLL(静态DLL也会自动释放,对于运行时动态加载的DLL,释放工作是由用户完成的,尽管Windows会检查它是否已经没有被使用,但是有时候由于特殊的原因它将不会被释放),这就是一个操作系统所谓的资源回收(忘了英文单词,好像是这么说吧),那么,问题就来了,当程序在退出的时候,尽管可以向其它程序(如自身的实例)发送消息,但是问题是如何传递资源,在这里是传递一个字符串,而传递的资源是又当前进程中的地址,按Windows的资源回收来说,当程序退出时传递的字符串地址已经不存在了,那如何才能传递一个正确的字符串给前一实例呢?
  我们可以使用API中的消息WM_SETTEXT与WM_GETTEXT,这两个消息发送后是立即返回的,这样当前进程能在发送完消息后立即退出,而SendMessage函数在发送消息时会判断当前消息是否是WM_SETTEXT与WM_GETTEXT,如果是,则SendMessage并不单单发送一个消息,而会创建一个内存映像(标准叫映射)文件,把需要传递的字符保存到这个内存映像中,然后再把内存映像的地址做为参数传给目标窗体,而内存映像是可以在程序之间共享的,这样就间接的做到了传递资源:
... ...
.DATA
   szClassName db "WinASM_Class",0
.data?
   lpCommandLine DD ?

.CODE
START:
   ... ...
   invoke GetCommandLine
   mov lpCommandLine, eax
   invoke FindWindow,offset szClassName,NULL   ;查找自身类
   cmp eax,0
   jnz @F
      invoke WinMain....
      invoke ExitProcess,0
   @@:
   invoke SendMessage,eax,WM_SETTEXT,0,lpCommandLine
   invoke ExitProcess,1      ;记得发生错误后返回非零值,尽管这个不是错误。
   ......


  因此,我们还需要自己来处理WM_SETTEXT消息:
... ...
.elseif uMsg==WM_SETTEXT
   invoke MessageBox,0,lParam,0,0

  在模板相关地方添加上述代码后,运行一下,你会发现第二个实例会马上退出,但是第一个实例会在第二个实例退出的那一瞬弹出一个信息框,如果第二个实例启动时你传递了参数,那么你对照一下,信息框中的信息就是第二个实例的尾部参数。
  这样你就可以在WM_SETTEXT消息中进行处理了,如打开实例传过来的文件。


欢迎访问AoGo汇编小站:http://www.aogosoft.com