|
.可以使用FindWindow查找程序的标题,此函数成功返回目标窗口句柄,失败为NULL. szWindowName db "Hello World!",0
... ...
invoke FindWindow,NULL,offset szWindowName
.if eax!=NULL
invoke WinMain....
.end if
invoke ExitProcess,0
这种方法不是很好,因为会有一些软件的窗口可能与你的窗口标题同名,注意看上面的FindWindow,参考API手册发现第一个参数是ClassName,窗口类名除自身实例一般是唯一的,这种方法一般完全可行:
2.使用FindWindow查找程序的窗口类名,函数成功返回目标窗口句柄,失败为NULL.
szClassName db "WINASM_CLASS!",0
... ...
invoke FindWindow,offset szClassName,NULL
.if eax!=NULL
invoke WinMain....
.end if
invoke ExitProcess,0
但是这种方法缺点就是,当程序没有标准的窗口或是以对话框为主窗口的程序就不适用了,没有标准窗口的程序当然没有类名,而以对话框为主窗口的程序的话也不行,因为默认对话框的类名都是#32768,这个当然无法依此来判断实例是否已运行.
3.创建一个Mutex(互斥)对象,这是一个系统全局标识,创建后所有的程序都可以访问到.此函数成功返回Mutex对象的句柄,失败返回NULL,但是一般都是通过GetLastError获得错误编号进行判断.
.data
szMutex db "_Me?",0
.data?
hMutex dd ?
hInstance dd ?
.CODE
START:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke
CreateMutex,NULL,TRUE,offset szMutex
mov hMutex,eax
invoke GetLastError 获得最后发生的错误编号
cmp eax,ERROR_ALREADY_EXISTS 已经存在
jz @F
invoke WinMain...
invoke ReleaseMutex,hMutex 只有在正常运行后才释放Mutex对象
@@:
invoke ExitProcess,0
4.还有其它方法,如在程序启动时在同目录或Windows临时目录下创建一个文件,退出删除它,那么第二个以上的实例运行后首先判断是否存在这个文件,存在则退出,不存在则启动,如果一个程序使用到了INI则更方便,和上面说的一样,在启动时设置某个键,退出时再设为0,第二个以上的实例则以此键为"互斥对象"。还有往注册表中写一个键,方法和上面是一样的。
|
|