Проверка наличия программы.

307cwam

Новичок
Проверка наличия программы.

Здравствуйте!
---------------
Подскажите как мне сделать так.

Установлена одна версия программы.
Появилось обновление программы.
Хочу сделать, чтобы при запуске инсталлятора обновления (новая версия),
1. Если программа не установлена.
Инсталлятор устанавливал новую версию.

2. Если программа установлена и есть на компьютере.
Инсталлятор отменял свой запуск и/или выдавал сообщение
(о том, что нужно удалить старую версию программы прежде чем,
установливать новую).

------------------------------------------
Что нужно добавить/прописать в скрипт?
 

SBalykov

Старожил
Проверка наличия программы.

Здравствуйте!
---------------
Подскажите как мне сделать так.

Установлена одна версия программы.
Появилось обновление программы.
Хочу сделать, чтобы при запуске инсталлятора обновления (новая версия),
1. Если программа не установлена.
Инсталлятор устанавливал новую версию.

2. Если программа установлена и есть на компьютере.
Инсталлятор отменял свой запуск и/или выдавал сообщение
(о том, что нужно удалить старую версию программы прежде чем,
установливать новую).

------------------------------------------
Что нужно добавить/прописать в скрипт?
Можно через реестр. Примерно так
Код:
[Setup]
AppName=Opera
AppVerName=Opera v16.0
DefaultDirName={pf}\Opera
OutputDir=.

[Code]
function InitializeSetup: Boolean;
begin
if RegKeyExists(HKLM,'SOFTWARE\Opera Software') or RegKeyExists(HKLM64,'SOFTWARE\Opera Software') then begin
MsgBox('Обнаружена установленная программ Opera'+#13#10+'для обновления необходимо удалить предыдущую версию', mbInformation, MB_OK);
Result:=false;
end else
Result:=true;
end;
 
Последнее редактирование:

Awalder

Новичок
Можно через реестр. Примерно так
Код:
[Setup]
AppName=Opera
AppVerName=Opera v16.0
DefaultDirName={pf}\Opera
OutputDir=.

[Code]
function InitializeSetup: Boolean;
begin
if RegKeyExists(HKLM,'SOFTWARE\Opera Software') or RegKeyExists(HKLM64,'SOFTWARE\Opera Software') then begin
MsgBox('Обнаружена установленная программ Opera'+#13#10+'для обновления необходимо удалить предыдущую версию', mbInformation, MB_OK);
Result:=false;
end else
Result:=true;
end;
Автообновление возможно реализовать? Если например запускаешь приложение и появляется сообщение типа "доступна более новая версия, обновить?"
 
Последнее редактирование:

SBalykov

Старожил
Автообновление возможно реализовать? Если например запускаешь приложение и появляется сообщение типа "доступна более новая версия, обновить?"
Почему бы и нет. Самый простой, на мой взгляд, способ:
Код:
[Setup]
AppName=Opera
AppVerName=Opera v16.0
AppVersion=16.5
DefaultDirName={pf}\Opera
OutputDir=.

[Code]
function InitializeSetup: Boolean;
var Ver: String;
begin
if RegQueryStringValue(HKLM,'SOFTWARE\Opera', 'Version', Ver) or RegQueryStringValue(HKLM64,'SOFTWARE\Opera', 'Version', Ver)then begin
if Ver < ('{#SetupSetting("AppVersion")}') then
if MsgBox('Версия установленной программы устарела.'+#13#10+'Нажмите "Да" для обновления программы.', mbInformation, MB_YESNO)= IDNO then
Result:=false else Result:=true;
end else
Result:=true;
end;
 

Егор1988-00

Новичок
Есть два кода, один из них ваш, другой мой. По отдельности эти два кода работают без проблем.
Мой код позволяет запускать программу без установки, возможно в этом нестыковка.


Код:
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif
type
  HINSTANCE = THandle;

function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
  lpParameters: string; lpDirectory: string; nShowCmd: Integer): HINSTANCE;
  external 'ShellExecute{#AW}@shell32.dll stdcall';

function InitializeSetup: Boolean;
begin

  Result := WizardSilent;

  if not Result then
  begin
  
    if ShellExecute(0, '', ExpandConstant('{srcexe}'), '/VERYSILENT', '',
      SW_SHOW) <= 32
    then
    
      Result := True;
  end;
end;
Это ваш код работает, как положено, если программа есть, то уведомление вылазит и потом его закрываю. Если программы нет на пк, то начинается установка моей программы.

Код:
[Code]
function InitializeSetup: Boolean;
begin
if RegKeyExists(HKLM,'SOFTWARE\WinRAR') or RegKeyExists(HKLM64,'SOFTWARE\WinRAR') then begin
MsgBox('Обнаружена установленная программ Opera'+#13#10+'для обновления необходимо удалить предыдущую версию', mbInformation, MB_OK);
Result:=false;
end else
Result:=true;
end;
Это то что у меня получилось слепить из двух кодов.

Код:
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif
type
  HINSTANCE = THandle;
function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
  lpParameters: string; lpDirectory: string; nShowCmd: Integer): HINSTANCE;
  external 'ShellExecute{#AW}@shell32.dll stdcall';

function InitializeSetup: Boolean;

   begin
if RegKeyExists(HKLM,'SOFTWARE\WinRAR') or RegKeyExists(HKLM64,'SOFTWARE\WinRAR') then begin
MsgBox('Обнаружена установленная программ WinRAR'+#13#10+'для обновления необходимо удалить предыдущую версию', mbInformation, MB_OK);
Result:=false;
end else
Result:=true;
begin
  Result := WizardSilent;
  if not Result then
  begin
    if ShellExecute(0, '', ExpandConstant('{srcexe}'), '/VERYSILENT', '',
      SW_SHOW) <= 32
    then
      Result := True;
  end;
 end;
end;
Код который получился в итоге, работает на половину, то есть он находит нужную программу на пк и выдает уведомление, о том что такая есть, и окно закрывается. Но когда я удаляю ту программу с пк, и запускаю свою программу, уведомление уже не выскакивает, но и моя программа не запускается.

Надеюсь понятно описал проблему) весь день голову ломаю.
 

Andreo Fadio

Старожил
@Егор1988-00,
Код:
[Code]
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif
type
  HINSTANCE = THandle;

function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
  lpParameters: string; lpDirectory: string; nShowCmd: Integer): HINSTANCE;
  external 'ShellExecute{#AW}@shell32.dll stdcall';

function InitializeSetup: Boolean;
begin
 if RegKeyExists(HKLM,'SOFTWARE\WinRAR22') or RegKeyExists(HKLM64,'SOFTWARE\WinRAR22') then begin
  MsgBox('Обнаружена установленная программ Opera'+#13#10+'для обновления необходимо удалить предыдущую версию', mbInformation, MB_OK);
  Result:=false;
 end else begin
  Result := WizardSilent;
  if not Result then
  begin
    if ShellExecute(0, '', ExpandConstant('{srcexe}'), '/VERYSILENT', '', SW_SHOW) <= 32 then
    Result := True;
  end;
 end;
end;
 

Егор1988-00

Новичок
@Егор1988-00,
Код:
[Code]
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif
type
  HINSTANCE = THandle;

function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
  lpParameters: string; lpDirectory: string; nShowCmd: Integer): HINSTANCE;
  external 'ShellExecute{#AW}@shell32.dll stdcall';

function InitializeSetup: Boolean;
begin
if RegKeyExists(HKLM,'SOFTWARE\WinRAR22') or RegKeyExists(HKLM64,'SOFTWARE\WinRAR22') then begin
  MsgBox('Обнаружена установленная программ WinRAR22'+#13#10+'для обновления необходимо удалить предыдущую версию', mbInformation, MB_OK);
  Result:=false;
end else begin
  Result := WizardSilent;
  if not Result then
  begin
    if ShellExecute(0, '', ExpandConstant('{srcexe}'), '/VERYSILENT', '', SW_SHOW) <= 32 then
    Result := True;
  end;
end;
end;
а можно сделать так что бы, вместо сообщения с информацией, устанавливалась программа , допустим ЗИП архиватор?
К примеру, проверил на наличие винрара, если он есть, то ставим зип архиватор, а если нету то ставим винрар.
 

Andreo Fadio

Старожил
@Егор1988-00,
Код:
function InitializeSetup: Boolean;
var
 Res: Integer;
begin
 if RegKeyExists(HKLM,'SOFTWARE\WinRAR') or RegKeyExists(HKLM64,'SOFTWARE\WinRAR') then
  Exec(ExpandConstant('{src}\ZipInstall.exe'),'/SILENT','', SW_HIDE, ewWaitUntilTerminated, Res)
 else Exec(ExpandConstant('{src}\WinRarInstall.exe'),'/SILENT','', SW_HIDE, ewWaitUntilTerminated, Res);
end;
Но функция Exec будет не корректно работать в InitializeSetup, в данном случае лучше к себе в скрипт встроить ExecAndWait (Ссылка на скрипт) для корректной работы.
 

Егор1988-00

Новичок
@Егор1988-00,
Код:
function InitializeSetup: Boolean;
var
Res: Integer;
begin
if RegKeyExists(HKLM,'SOFTWARE\WinRAR') or RegKeyExists(HKLM64,'SOFTWARE\WinRAR') then
  Exec(ExpandConstant('{src}\ZipInstall.exe'),'/SILENT','', SW_HIDE, ewWaitUntilTerminated, Res)
else Exec(ExpandConstant('{src}\WinRarInstall.exe'),'/SILENT','', SW_HIDE, ewWaitUntilTerminated, Res);
end;
Но функция Exec будет не корректно работать в InitializeSetup, в данном случае лучше к себе в скрипт встроить ExecAndWait (Ссылка на скрипт) для корректной работы.
Здравствуйте

по вашему совету, взял в помощь скрипт ExecAndWait , попробовал подружить со своим кодом.
получилось нечто такое, но не соображу как полноценно внести свои условия.

Код:
/////===== Начало - ExecAndWait =====\\\\\
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif
type
  HINSTANCE = THandle;

var
  lastproc: cardinal;

const
  NORMAL_PRIORITY_CLASS           = $00000020;
  REALTIME_PRIORITY_CLASS         = $00000100;

type
  _TStartupInfo = record
  cb: DWORD;
  lpReserved, lpDesktop: Longint;
  lpTitle: PAnsiChar;
  dwX, dwY, dwXSize, dwYSize, dwXCountChars, dwYCountChars, dwFillAttribute, dwFlags: DWORD;
  wShowWindow, cbReserved2: Word;
  lpReserved2: Byte;
  hStdInput, hStdOutput, hStdError: Longint;
end;
  _TProcessInformation = record
  hProcess, hThread: Longint;
  dwProcessId, dwThreadId: DWORD;
end;
  _TMsg = record
  hWnd: HWND;
  msg, wParam: Word;
  lParam: LongWord;
  Time: TFileTime;
  pt: TPoint;
end;

function OpenProcess(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; external 'OpenProcess@kernel32.dll stdcall';
function CloseHandle(hObject: THandle): BOOL; external 'CloseHandle@kernel32.dll stdcall';
procedure GetStartupInfo(var lpStartupInfo: _TStartupInfo); external 'GetStartupInfoA@kernel32.dll stdcall';
function CreateProcess(lpApplicationName: PAnsiChar; lpCommandLine: PAnsiChar; lpProcessAttributes, lpThreadAttributes: DWORD; bInheritHandles: BOOL; dwCreationFlags: DWORD; lpEnvironment: PAnsiChar; lpCurrentDirectory: PAnsiChar; const lpStartupInfo: _TStartupInfo; var lpProcessInformation: _TProcessInformation): BOOL; external 'CreateProcessA@kernel32.dll stdcall';
function WaitForSingleObject(hHandle: Longint; dwMilliseconds: DWORD): DWORD; external 'WaitForSingleObject@kernel32.dll stdcall';
function PeekMessage(var lpMsg: _TMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax, wRemoveMsg: UINT): BOOL; external 'PeekMessageA@user32.dll stdcall';
function TranslateMessage(const lpMsg: _TMsg): BOOL; external 'TranslateMessage@user32.dll stdcall';
function DispatchMessage(const lpMsg: _TMsg): Longint; external 'DispatchMessageA@user32.dll stdcall';
function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string; lpParameters: string; lpDirectory: string; nShowCmd: Integer): HINSTANCE; external 'ShellExecute{#AW}@shell32.dll stdcall';

procedure Application_ProcessMessages;
var
  Msg: _TMsg;
  begin
  while PeekMessage(Msg, 0, 0, 0, 1) do begin
    TranslateMessage(Msg);
    DispatchMessage(Msg);
  end;
end;

function ExecAndWait(filename, params: pansichar; showcmd: integer; Wait: boolean; Priority: Smallint): Boolean;
var
  SI : _TStartupInfo;
  PI : _TProcessInformation;
  CMD: string;
  prt: DWORD;
  begin
if RegKeyExists(HKLM,'SOFTWARE\WinRAR') or RegKeyExists(HKLM64,'SOFTWARE\WinRAR') then
  begin
    Result:=false;
    CMD:='{app}\WinRarInstall.exe' + filename + '"' + params;
    GetStartupInfo(SI);
    SI.wShowWindow := showcmd;
    SI.dwFlags := 1;
  if Priority = 0  then prt:= NORMAL_PRIORITY_CLASS else
  if Priority = 1  then prt:= REALTIME_PRIORITY_CLASS;
    Result:=CreateProcess('', PansiChar(CMD), 0, 0, false, prt,'', pansichar(ExtractFilePath(filename)), SI, PI);
    lastproc:=PI.dwProcessId;
  if wait then
  while WaitforSingleObject(PI.hProcess, 50) = $00000102 do
  CloseHandle(PI.hProcess);
end;
end;
/////===== Конец - ExecAndWait =====\\\\\
 

Andreo Fadio

Старожил
@Егор1988-00, а зачем вы саму функцию меняли, когда должны были просто вызвать ее у себя в скрипте с проверкой и нужными вам параметрами?
Нужно было с помощью #include добавить скрипт и вызывать функцию execandwait, где уже будете прописывать параметры обработки и проверять условия перед ее исполнением, а не менять сам предоставляемый скрипт.
 

Егор1988-00

Новичок
@Егор1988-00, а зачем вы саму функцию меняли, когда должны были просто вызвать ее у себя в скрипте с проверкой и нужными вам параметрами?
Нужно было с помощью #include добавить скрипт и вызывать функцию execandwait, где уже будете прописывать параметры обработки и проверять условия перед ее исполнением, а не менять сам предоставляемый скрипт.
Сглупил по не знанию), сейчас вроде разобрался. Добавил скрипт execandwait с помощью #include, но получаю вот такую ошибку теперь:

Preprocessing
Reading file: C:\Program Files (x86)\Inno Setup 6\ISPPBuiltins.iss
Line 78: Including file: D:\Work\INNO шаблоны\разное\ExecAndWait.iss
Reading file: D:\Work\INNO шаблоны\разное\ExecAndWait.iss

File: D:\Work\INNO шаблоны\разное\ExecAndWait.iss Line 69: Column 3: Unknown identifier 'Application'
 

Andreo Fadio

Старожил
@Егор1988-00, поменяйте в этом участке:
Код:
if wait then
  while WaitforSingleObject(PI.hProcess, 50) = $00000102 do
  Application.ProcessMessages;
//  Application_ProcessMessages;
  CloseHandle(PI.hProcess);
end;
на такое:
Код:
if wait then
  while WaitforSingleObject(PI.hProcess, 50) = $00000102 do
#ifdef IS_ENHANCED
  Application.ProcessMessages;
#else
  Application_ProcessMessages;
#endif
  CloseHandle(PI.hProcess);
end;
 

Егор1988-00

Новичок
начал собирать код заново, сейчас он выглядит так, но не компилируется, выдает ошибку Type mismatch на строку
ExecAndWait(ExpandConstant('{app}\winzip28-pp.exe'), '', '', SW_SHOW, True);


Код:
#ifdef UNICODE
  #define AW "W"
#else
  #define AW "A"
#endif
#include "ExecAndWait.iss"

type
  HINSTANCE = THandle;

function ShellExecute(hwnd: HWND; lpOperation: string; lpFile: string;
  lpParameters: string; lpDirectory: string; nShowCmd: Integer): HINSTANCE;
  external 'ShellExecute{#AW}@shell32.dll stdcall';

function InitializeSetup: Boolean;
var
Res: Integer;
begin
if RegKeyExists(HKLM,'SOFTWARE\WinRAR') or RegKeyExists(HKLM64,'SOFTWARE\WinRAR') then
ExecAndWait(ExpandConstant('{app}\winzip28-pp.exe'), '', '', SW_SHOW, True);
end;
 

HandyMan

Новичок
ExecAndWait(ExpandConstant('{app}\winzip28-pp.exe'), '', '', SW_SHOW, True);

Заменить на
ExecAndWait(ExpandConstant('{app}\winzip28-pp.exe'), '', SW_SHOW, True, 0)
 
Сверху