Как с уверенностью определить, запущено ли приложение до выполнения сценария установки InnoSetup

У меня есть установочный скрипт с кодом Pascal, чтобы определить, запущено ли в настоящее время устанавливаемое приложение:

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

[Setup]
AppName=MyApp
AppVerName=MyApp v1.0
DiskSpanning=no
AppPublisher=me
AppPublisherURL=http://www.example.com
AppSupportURL=http://www.example.com
AppUpdatesURL=http://www.example.com
DefaultDirName={pf}\MyApp
UsePreviousAppDir=yes
DefaultGroupName=MyApp
OutputBaseFilename=Setup
OutputDir=.\MyAppSetup
MinVersion=5.0

[Tasks]
Name: desktopicon; Description: Create a &desktop icon; GroupDescription: Additional icons:; MinVersion: 4,4

[Files]
Source: .\Release\MyApp.exe; DestDir: {app}; Flags: ignoreversion

[Icons]
Name: {group}\EasyCash&Tax; Filename: {app}\MyApp.exe
Name: {userdesktop}\EasyCash&Tax; Filename: {app}\MyApp.exe; MinVersion: 4,4; Tasks: desktopicon

[Run]
Filename: {app}\MyApp.exe; Description: Launch MyApp; Flags: nowait postinstall skipifsilent

[Code]

function CheckProcessRunning( aProcName,
                              aProcDesc: string ): boolean;
var
  ShellResult: boolean;
  ResultCode: integer;
  cmd: string;
  sl: TStringList;
  f: string;
  d: string;
begin
  cmd := 'for /f "delims=," %%i ' + 
         'in (''tasklist /FI "IMAGENAME eq ' + aProcName + '" /FO CSV'') ' + 
         'do if "%%~i"=="' + aProcName + '" exit 1'; 
  f := 'CheckProc.cmd';
  d := AddBackSlash( ExpandConstant( '{tmp}' ));
  sl := TStringList.Create;
  sl.Add( cmd );
  sl.Add( 'exit /0' );
  sl.SaveToFile( d + f );
  sl.Free;
  Result := true;
  while ( Result ) do
  begin
    ResultCode := 1;
    ShellResult := Exec( f,
                         '',
                         d, 
                         SW_HIDE, 
                         ewWaitUntilTerminated, 
                         ResultCode );
    Result := ResultCode > 0;
    if Result and 
       ( MsgBox( aProcDesc + ' is active and must be closed to proceed', 
                 mbConfirmation, 
                 MB_OKCANCEL ) <> IDOK ) then
      Break;
  end;
  DeleteFile( d + f );
end;

// Perform some initializations.  Return False to abort setup
function InitializeSetup: Boolean;
begin
  // Do not use any user defined vars in here such as {app}
  Result := not ( CheckProcessRunning( 'MyApp.exe',      'MyApp' ));
end;


function InitializeUninstall: Boolean;
begin
  Result := not ( CheckProcessRunning( 'MyApp.exe',      'MyApp' ));
end;

Это работает в 99% случаев, но время от времени пользователи сообщают о ложных срабатываниях и не могут продолжить установку.

Пользователи сообщают, что в командной строке tasklist /FI "IMAGENAME eq MyApp.exe" /FO CSV (которая используется сценарием Pascal) ничего не возвращает.

Есть ли в сценарии ошибка, которая может давать ложные срабатывания, или есть лучший способ определить, запущено ли приложение, чем tasklist?


person thomiel    schedule 03.06.2015    source источник
comment
Также см. Мой вопрос stackoverflow.com/questions/30617253, если вы являетесь взломщиком Inno-Setup!   -  person thomiel    schedule 03.06.2015
comment
Лично я бы не предлагал использовать этот подход, если вы контролируете устанавливаемое приложение. Вы можете заставить приложение создать именованный мьютекс для обнаружения установщиком, а затем установщик может транслировать настраиваемое сообщение, чтобы приложение обнаружило, что оно закрывается, прежде чем установщик продолжит работу.   -  person Remy Lebeau    schedule 06.06.2015
comment
Просто чтобы расширить идею @Remy. Когда ваше приложение может создать именованный мьютекс, вы можете просто установить AppMutex к имени этого мьютекса и позволить Inno Setup делать то, что обычно делают установщики, они проверяют, есть ли мьютекс с таким именем, и просят пользователя выйти из приложения (они не завершают его принудительно за спиной пользователя).   -  person TLama    schedule 16.06.2015


Ответы (1)


Есть ли в скрипте ошибка, которая может давать ложные срабатывания?

Нет ошибки.

Вы знаете, что tasklist может быть недоступен? Подумайте о "XP Home" (да, он исчезает), но все еще используется, и ваше решение там не будет работать, потому что tasklist просто недоступно.

Или есть лучший способ определить, запущено ли приложение, чем список задач?

Да, есть другие, возможно, более надежные способы сделать это. Например, довольно часто включают psvince в установщик и используют его для обнаружения процессов. Неплохо также решение на основе WMI.

Вот несколько подходов к «обнаружению процесса» с помощью InnoSetup:

person Jens A. Koch    schedule 15.06.2015
comment
Дальнейшее изучение того, как проверить запущенные приложения, можно найти в этом ответе: stackoverflow.com/a/1577129/550712. - person Mark Berry; 06.01.2016