15

我已阅读以下帖子。我的代码看起来完全一样,但不起作用:
Inno Setup Checking for running process

我从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;
4

5 回答 5

54

您可以使用 WMI 和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;
于 2012-03-30T21:37:22.003 回答
8

我没有足够的代表点来为 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;
于 2014-08-27T02:30:31.840 回答
2

有一个更简单的解决方案;使用 RRUZ 建议的代码取决于您知道安装路径,如果您在安装程序初始化时运行该安装路径,您将不知道这一点。

最好的解决方案是使用 FindWindowByClassName。它确实有一个先决条件,即您有一个始终打开的主表单,但如果您有多种可以打开的表单,您始终可以运行多个检查。不用说,您需要使类名尽可能唯一!

示例函数:

function IsAppRunning(): Boolean;
begin                                                                
  Result := (FindWindowByClassName( '{#AppWndClassName}') <> 0) or (FindWindowByClassName( '{#AltAppWndClassName}') <> 0);
end;

# precompile 引用是在安装脚本之前定义的...

#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;

如果您需要比这更复杂的东西,那么您需要研究互斥锁,但上述代码的美妙之处在于它简单、快速并且只要您有合理唯一的类名,就和其他任何东西一样好。

(尽管诚然,如果您在多用户系统上运行,那么如果它在另一个用户的会话中,这可能不会找到窗口。但正如我所说,对于大多数简单的情况,这会很好。)

于 2013-09-06T07:47:32.650 回答
1

不幸的是 psvince.dll 无法根据我的观察查询 64 位运行进程,而且由于我不是它的开发人员,我不知道如何修复它以在 Windows x64 上工作。

我的解决方法是使用自制的命令行实用程序 processviewer.exe,

http://github.com/lextm/processviewer

这已经在 Windows 7 x64 的Touch Mouse Mate上进行了测试

http://www.lextm.com/2012/03/new-inno-setup-installer-script-samples-version-compare-running-processes/

于 2012-03-30T11:48:23.530 回答
1

一个简单的解决方案可能是尝试删除 exe 文件。我假设您无论如何都要替换或卸载它。如果文件存在并且删除它失败,那么它可能正在运行。

于 2014-05-21T13:29:06.327 回答