【问题标题】:Inno Setup Checking for running processInno Setup 检查正在运行的进程
【发布时间】:2019-08-27 19:35:23
【问题描述】:

我有一个 Inno Setup 项目,我想在卸载它之前检查应用程序是否实际运行。我尝试了很多方法,但在 Windows 7 中运行时,它们都以静默方式失败。例如,使用psvince.dll 检查notepad.exe 进程的以下脚本始终返回false,无论记事本是否正在运行。

我在 C# 应用程序中使用psvince.dll 来检查它是否在 Windows 7 下工作并且没有任何问题。所以我最好的猜测是安装程序无法在启用 UAC 的情况下正确运行。

[Code]
function IsModuleLoaded(modulename: String): Boolean;
external 'IsModuleLoaded@files:psvince.dll stdcall';

function InitializeSetup(): Boolean;
begin
   if(Not IsModuleLoaded('ePub.exe')) then
   begin
       MsgBox('Application is not running.', mbInformation, MB_OK);
       Result := true;
   end
   else
   begin
       MsgBox('Application is already running. Close it before uninstalling.', mbInformation, MB_OK);
       Result := false;
   end
end;

【问题讨论】:

  • 我有同样的问题,但 AnsiString 没有帮助我。

标签: inno-setup


【解决方案1】:

您使用的是 Unicode Inno 设置吗?如果你是,它应该说

function IsModuleLoaded(modulename: AnsiString): Boolean;

因为 psvince.dll 不是 Unicode dll。

该示例还检查 epub.exe,而不是 notepad.exe。

【讨论】:

  • 我有同样的问题,但 AnsiString 没有帮助我。
【解决方案2】:

你也可以尝试使用WMIService:

procedure FindApp(const AppName: String);
var
  WMIService: Variant;
  WbemLocator: Variant;
  WbemObjectSet: Variant;
begin
  WbemLocator := CreateOleObject('WbemScripting.SWbemLocator');
  WMIService := WbemLocator.ConnectServer('localhost', 'root\CIMV2');
  WbemObjectSet :=
    WMIService.ExecQuery('SELECT * FROM Win32_Process Where Name="' + AppName + '"');
  if not VarIsNull(WbemObjectSet) and (WbemObjectSet.Count > 0) then
  begin
    Log(AppName + ' is up and running');
  end;
end;

【讨论】:

    【解决方案3】:

    Inno Setup 实际上有一个 AppMutex 指令,它记录在帮助中。实现它需要 2 行代码。

    在您的 iss 文件的 [Setup] 部分中添加:

    AppMutex=MyProgramsMutexName
    

    然后在您的应用程序启动期间添加这行代码:

    CreateMutex(NULL, FALSE, "MyProgramsMutexName");
    

    【讨论】:

    • Official doc 说,您需要两个互斥锁来检测由其他用户启动的实例。
    【解决方案4】:

    您可以使用此代码检查 notepad.exe 是否正在运行。

    [Code]
    function IsAppRunning(const FileName: string): Boolean;
    var
      FWMIService: Variant;
      FSWbemLocator: 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;
    
    function InitializeSetup: boolean;
    begin
      Result := not IsAppRunning('notepad.exe');
      if not Result then
      MsgBox('notepad.exe is running. Please close the application before running the installer ', mbError, MB_OK);
    end;
    

    【讨论】:

    • 这与this post 有何不同?嗯,是的。您不需要将Unassigned 分配给对象,因为当它们超出函数范围时,它们将被释放。您应该在运行查询后检查分配(另一篇文章中的VarIsNull)。所以,另一篇文章更短更精确。
    • 我已经成功使用此代码很长时间了,直到今天,一位之前没有看到任何错误消息的用户突然开始看到两条错误消息“ShellExecuteEx 失败;代码 299。只有部分 oif a ReadProcessMemory或 WriteProcessMemory 请求已完成。”和“运行时错误(在 1:321);SWbemlocator:访问被拒绝。”
    猜你喜欢
    • 2010-12-07
    • 1970-01-01
    • 2011-10-18
    • 2016-03-24
    • 2015-09-21
    • 2022-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多