如何防止外部程序或系統被多次執行(50分)

  • 主题发起人 主题发起人 dfeng_shen
  • 开始时间 开始时间
D

dfeng_shen

Unregistered / Unconfirmed
GUEST, unregistred user!
請教各位, 我在delphi用winexec()調用外部程序(如word),
但每次調用都會再次重新開啟外部程序或系統,不知如何判
斷系統已被開啟.若外部系統已被開啟,又如何調至桌面.
 
看看行吗??
<span class="font2"><strong>检测程序是否运行</strong></span></a></p>
<p align="left"><span class="font2">  在某些情况下,我们编写的应用程序同时只能有一个实例在内存中运行,例如服务器程序、需要独占某设备的程序,甚至我们仅仅是让程序同时只有一个实例运行(如UltraEdit就是这样做的,让你不能同时运行多个UltraEdit)。要实现此功能,需要在程序中加一点判断的代码,在Windows
95或Win32环境下的Delphi版本中实现的程序如下:<br>
按Ctrl+F12键,选择Project1,加入下列语句<br>
program Project1;<br>
<br>
uses<br>
windows, {加入该句才能调用函数}<br>
Forms,<br>
Unit1 in 'Unit1.pas'{Form1};<br>
<br>
{$R *.RES}<br>
const classname='TForm1';
{声明为主窗体的类名}<br>
var handle:integer;
{变量}<br>
<br>
begin
<br>
{-----------------主要为该判断部分----------------------}<br>
handle:=findwindow(classname,nil);{查找是否有此类的窗体}<br>
if handle&amp;lt;&amp;gt;0 then
{不为0则程序已运行}<br>
begin
<br>
messagebox(0,'该程序已经有一个在运行中!','运行',0);{提示程序已运行}<br>
halt;
{退出程序}<br>
end;
<br>
{------------------------------------------------------}<br>
Application.Initialize;<br>
Application.CreateForm(TForm1, Form1);<br>
Application.Run;<br>
end.
<br>
  该程序在测试时由于Delphi也生成了此类实例窗体,所以会出现提示框,只有关闭Delphi后单独运行程序才能实现。</span></p>
 
此方法一定可以,但還要請問wjiachun,
handle:=findwindow(classname,nil);{查找是否有此类的窗体}
那如何得到此類窗體的classname 呢.
 
const classname='TForm1';
{声明为主窗体的类名}??
 
faint
you should know the windows have some different classes, for example
TForm, TRankForm..... you can also register your class...
so just try enumwindow , if you need example , tell me.
about you question, you can use shellexecute in the place of Winexec
shellexecute will return a Hinstance, if less than 32 means you have
already run this program.
 
应该这样:
首先枚举当前所有进程列表,从而得到每个process对应的exe文件名字,
你在winexec之前总知道exe名字吧? 那么看看进程列表里面是否已经有
此exe文件就知道乐.
 
yifeng,
我在delphi程序中,通過一button調用BDE或IE,每次按下Button
總會重新開啟BDE或IE,而不會先判斷BDE或IE是否已經被開啟,若
已經被開啟則bringtofront,否則開啟BDE或IE.請指教.
mail:dfeng_shen@netease.com
 
cAkk,
你的方法不錯,當我判斷外部程序在開啟後,把它開啟至桌面,我用的是
下面的方法.但我不知怎樣得到每个process对应的classname,請指教.
if SetForegroundWindow(findwindow(classname,nil)) then
SendMessage(Findwindow(classname,nil),wm_syscommand,SC_RESTORE,0)
 
GetClassInfo
如果你用shellexecute运行你的程序, 可以得到hinstance, 用getclassinfo可以
获得class name (or GetClassName)
 
你怎么枚举进程的? 为什么要得到classname? 你只要知道exe文件名就可以了:
var
FSnapshotHandle:THandle;
FProcessEntry32:TProcessEntry32;
Ret : BOOL;
lst:tstringlist;
begin
lst:=tstringlist.create;
FSnapshotHandle:=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
FProcessEntry32.dwSize:=Sizeof(FProcessEntry32);
Ret:=Process32First(FSnapshotHandle,FProcessEntry32);
while Retdo
begin
lst.add(FProcessEntry32.szExeFile);
//这就是exe文件名
Ret:=Process32Next(FSnapshotHandle,FProcessEntry32);
end;
CloseHandle(FSnapshotHandle);

最后lst保存乐所有的process所对应的exe文件名.你知道在winexec之前
看看该exe文件名是否在该列表里就可以了.
 

ShellExecute 文档名
就不会了
 
用向系统添加全局原子的方法,来防止多个程序实例的运行。全局原子由
Windows系统负责维持,它能保证其中的每个原子都是唯一的,管理其引用计数,
并且当该全局原子的引用计数为0时,从内存中清除。我们用GlobalAddAtom函数
向全局原子添加一个255个字节以内的字符串,用GlobalFindAtom来检查是否已
经存在该全局原子,最后在程序结束时用GlobalDeleteAtom函数删除添加的全局
原子。示例如下:
Uses Windows
const iAtom=‘SingleApp’;
begin

if GlobalFindAtom(iAtom)=0 then

begin

GlobalAddAtom(iAtom);
...... //需要单一实例的部分
GlobalDeleteAtom(GlobalFindAtom(iAtom));
end
else

MessageBox(0,‘You can not run a second copy of this
App’,‘’,mb_OK);
end.

 
msan的方法我很同意,在系统中注册一个原子。
也可以使用类似的方法在系统中创建一个互斥对象或信号量,在程序启动
的时候来检查这个信号量,就可以达到限制程序运行实例个数的目的。著
名的RXLib中使用的就是类似的机制。
 
时间太久,强制结束。 wjiachun
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
后退
顶部