我已阅读以下帖子。我的代码看起来完全一样,但不起作用:
Inno Setup 检查正在运行的进程
我从 http://www.vincenzo.net/isxkb/index.php?title=PSVince
复制了示例但是即使我像这样更改代码,该示例也不起作用:
[Code]
function IsModuleLoaded(modulename: AnsiString): Boolean;
external 'IsModuleLoaded@files:psvince.dll stdcall';
代码总是返回
false
(程序没有运行,即使它正在运行)。
在 Windows 2008 R2 和 Windows 7 上进行了测试。
事实上我想检查
tomcat5.exe
是否正在运行。所以我想我不能和AppMutex
一起工作。
我也看到了https://code.google.com/p/psvince/source/detail?r=5
但我找不到任何有关该 DLL 兼容性的事实。
完整代码:
[Files]
Source: psvince.dll; Flags: dontcopy
[Code]
function IsModuleLoaded(modulename: AnsiString ): Boolean;
external 'IsModuleLoaded@files:psvince.dll stdcall';
function InitializeSetup(): Boolean;
begin
if(IsModuleLoaded( 'notepad.exe' )) then
begin
MsgBox('Running', mbInformation, MB_OK);
Result := false;
end
else
begin
MsgBox('Not running', mbInformation, MB_OK);
Result := true;
end
end;
Win32_Process
。
尝试将此函数添加到您的 Inno Setup 脚本中。
function IsAppRunning(const FileName : string): Boolean;
var
FSWbemLocator: Variant;
FWMIService : Variant;
FWbemObjectSet: Variant;
begin
Result := false;
FSWbemLocator := CreateOleObject('WBEMScripting.SWBEMLocator');
FWMIService := FSWbemLocator.ConnectServer('', 'root\CIMV2', '', '');
FWbemObjectSet :=
FWMIService.ExecQuery(
Format('SELECT Name FROM Win32_Process Where Name="%s"', [FileName]));
Result := (FWbemObjectSet.Count > 0);
FWbemObjectSet := Unassigned;
FWMIService := Unassigned;
FSWbemLocator := Unassigned;
end;
我没有足够的代表点来为 RRUZ 的出色答案添加评论,所以我将在此处添加此内容。 确保捕获异常,否则安装程序将为无法访问该服务的用户失败。
try
FSWbemLocator := CreateOleObject('WBEMScripting.SWBEMLocator');
FWMIService := FSWbemLocator.ConnectServer('', 'root\CIMV2', '', '');
FWbemObjectSet := FWMIService.ExecQuery(Format('SELECT Name FROM Win32_Process Where Name="%s"',[FileName]));
Result := (FWbemObjectSet.Count > 0);
except
end;
对此有一个更简单的解决方案;使用 RRUZ 建议的代码取决于您是否知道安装路径,如果您在安装程序初始化时运行该路径,则您不知道这一点。
最好的解决方案是使用FindWindowByClassName。它确实有一个小小的先决条件,即您有一个始终打开的主表单,但如果您有多种可以打开的表单,您始终可以运行多个检查。不言而喻,您需要使类名尽可能唯一!
示例功能:
function IsAppRunning(): Boolean;
begin
Result := (FindWindowByClassName( '{#AppWndClassName}') <> 0) or (FindWindowByClassName( '{#AltAppWndClassName}') <> 0);
end;
# 预编译引用是在安装脚本之前定义的...
#define AppWndClassName "TMySplashScreen"
#define AltAppWndClassName "TMyMainForm"
然后在代码部分,如下调用:
function InitializeUninstall(): Boolean;
begin
// check if application is running
if IsAppRunning() then
begin
MsgBox( 'An Instance of MyFantasticApp is already running. - Please close it and run the uninstall again.', mbError, MB_OK );
Result := false;
end
else
Result := true;
End;
如果您需要比这更复杂的东西,那么您需要研究互斥体,但上述代码的优点在于它简单、快速,并且只要您有相当独特的类名,就和其他代码一样好。
(尽管不可否认,如果您在多用户系统上运行,那么如果它在另一个用户的会话中,则可能找不到该窗口。但正如我所说,对于大多数简单的情况,这会很好。)
不幸的是,根据我的观察,psvince.dll 无法查询 64 位正在运行的进程,并且由于我不是它的开发人员,我不知道如何修复它以在 Windows x64 上工作。
我的解决方法是使用自制的命令行实用程序,processviewer.exe,
http://github.com/lextm/processviewer
这已在 Windows 7 x64 的 Touch Mouse Mate
中进行了测试一个简单的解决方案可能是尝试删除 exe 文件。我假设您无论如何都会更换或卸载它。如果文件存在并且删除失败,那么它可能正在运行。
我意识到我参加这个聚会有点晚了,但我还编写了一个可能有用的开源 DLL: