Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Автоматическая установка Windows » Автоматическая установка приложений » Скрипты Inno Setup. Помощь и советы [часть 9]

Ответить
Настройки темы
Скрипты Inno Setup. Помощь и советы [часть 9]

Аватара для El Sanchez

Ветеран


Contributor


Сообщения: 1264
Благодарности: 1024


Конфигурация

Профиль | Отправить PM | Цитировать


Изменения
Автор: El Sanchez
Дата: 06-06-2020
Внимание! Данная тема предназначена только для обсуждения написания скриптов!
Остальные вопросы, а также последние версии компилятора в теме
Inno Setup. Прочие вопросы.


Показать/скрыть: Справка, руководство, примеры:

Показать/скрыть: Ссылки на примеры скриптов:

Показать/скрыть: Дополнительные программы для Inno Setup:
  • ISTool - неплохой редактор скриптов Inno Setup.
    Последняя версия: 5.3.0.1 [29.09.2009] - Скачать | зеркало;

  • Inno Script Generator - генератор скриптов Inno Setup. Обладает некоторыми полезными функциями, которых нет ни у самого Inno Setup, ни у ISTool.
    Последняя версия: 1.0.3.1 [23.03.2008] - Скачать | зеркало на русифицированную программу;
    Примечание: Родной сайт www.hisoft2000.de более недоступен, поэтому здесь расположены сторонние ссылки.

  • Inno Setup Form Designer - редактор страниц Inno Setup, можно создавать свои страницы.
    Последняя версия: 2.0.8 [12.11.2006] - Скачать;
    Примечание: Родной сайт http://isfd.kaju74.de/index.php?isfd более недоступен, поэтому здесь расположены сторонние ссылки.

  • Inno Setup GameScript Generator - программа генерирует скрипты для Inno Setup . С помощью GameScript Generator и Inno Setup вы сможете быстро создать простенький инсталляционный пакет для любой игры. В инсталлятор можно встроить музыку, слайдшоу и фоновый рисунок. Для специалистов созданный скрипт, возможно, будет неплохой заготовкой для дальнейшей модернизации;

  • ISSkin - Программа для создания и добавления в инсталлятор скинов. Инструкция.
    Последняя версия: 3.0.0.0 [19.01.2010] - Скачать;

  • ISSJoiner - Программа для объединения нескольких скриптов InnoSetup в один.
    Последняя версия: 3.0 [23.07.2009]

  • Converter - Программа конвертирует reg-файлы в формат *.iss (формат скриптов Inno Setup).
    Последняя версия: 0.1.4 [13.03.2010] - Скачать;

  • RegExporter - Бесплатная утилита для экспорта реестра и конвертации файлов *.reg и *.ini в инсталляционные скрипты Inno Setup и NSIS.
    Последняя версия: 1.3.0 [17.01.2015] - Скачать;



Предыдущие ветки обсуждения по ссылкам ниже и в прикреплённых архивах:

Скрипты Inno Setup. Помощь и советы [часть 6] | Скрипты Inno Setup. Помощь и советы [часть 6].7z
Скрипты Inno Setup. Помощь и советы [часть 7] | Скрипты Inno Setup. Помощь и советы [часть 7].7z
Скрипты Inno Setup. Помощь и советы [часть 8] | Скрипты Inno Setup. Помощь и советы [часть 8].7z
Это сообщение посчитали полезным следующие участники:

Отправлено: 16:09, 04-04-2018

 

Пользователь


Сообщения: 91
Благодарности: 7

Профиль | Сайт | Отправить PM | Цитировать


Iska, ну а липовый индикатор установки во время создания архивов как тогда сделать, или просто в момент создания архива, стандартную надпись "Копирование файлов", заменить на "Создание файла и т.п."?

Отправлено: 20:38, 01-01-2019 | #191



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Ветеран


Сообщения: 27449
Благодарности: 8086

Профиль | Отправить PM | Цитировать


Не надо липовый. Нужны отдельные и реальные. Как — надеюсь, коллеги Вам помогут.

Отправлено: 00:04, 02-01-2019 | #192


Аватара для El Sanchez

Ветеран


Contributor


Сообщения: 1264
Благодарности: 1024

Профиль | Отправить PM | Цитировать


Вложения
Тип файла: 7z 7-zip32.7z
(288.4 Kb, 7 просмотров)

Цитата TROY Diamond:
во время упаковки всё замирает, кнопка Отмена НЕ активна, конечный пользователь может решить что всё зависло, а создание некоторых больших архивов может занимает до 5-7 минут! »
TROY Diamond, ясно, так и знал, что по-простому не выйдет.
Скрытый текст

Код: Выделить весь код
[Languages]
Name: ru; MessagesFile: compiler:Languages\russian.isl

[CustomMessages]
ru.SevenZipStatusPackFiles=Упаковка файлов из %1:
ru.SevenZipProgressCaptions=Прогресс:%nСкорость:%nПрошло:%nОсталось:
ru.SevenZipProgressInfo=%1%% (%2 из %3)%n%4%n%5%n%6
ru.SevenZipPackFailed=При создании архива %1 произошла ошибка. Код ошибки: %2
ru.UnableDeleteEmptyFolder=Не удалось удалить пустую папку %1. Код ошибки: %2 (%3)

[Files]
Source: 7-zip32.dll; Flags: dontcopy
#ifndef IS_ENHANCED
; http://restools.hanzify.org/inno/callbackctrl/InnoCallbackCtrl_V1.1.zip
Source: CallbackCtrl.dll; Flags: dontcopy
#endif
; {app}\data\test01
Source: {app}\test01\*; DestDir: {app}\data\test01; Flags: ignoreversion overwritereadonly recursesubdirs createallsubdirs sortfilesbyextension
Source: dummy; DestDir: {app}\data; AfterInstall: Pack(ExpandConstant('{app}\data\test01')); Flags: deleteafterinstall
; {app}\data\test02
Source: {app}\test02\*; DestDir: {app}\data\test02; Flags: ignoreversion overwritereadonly recursesubdirs createallsubdirs sortfilesbyextension
Source: dummy; DestDir: {app}\data; AfterInstall: Pack(ExpandConstant('{app}\data\test02')); Flags: deleteafterinstall

[Code]
#define A = (Defined UNICODE) ? "W" : "A"
const
  WM_GETFONT = $0031;
  WM_SETTEXT = $000C;
  WM_USER    = $0400;

  PBM_SETPOS     = WM_USER + 2;
  PBM_SETRANGE32 = WM_USER + 6;

  GWL_STYLE = -16;

  WS_CLIPSIBLINGS = $04000000;
  WS_VISIBLE      = $10000000;
  WS_CHILDWINDOW  = $40000000;
  SS_RIGHT = $2;

  CP_ACP  = 0;
  CP_UTF8 = 65001;

  FNAME_MAX32 = 512;
  MAX_PATH = 260;

  ARCEXTRACT_BEGIN     = 0;
  ARCEXTRACT_INPROCESS = 1;

type
  { 7-zip.dll. }
  TExtractingInfo = record
    szSourceFileName: PAnsiChar;
    szDestFileName: PAnsiChar;
    dwFileSize: DWORD;
    szFileSize: PAnsiChar;
    dwWriteSize: DWORD;
    szWriteSize: PAnsiChar;
    dwProgress: DWORD;
    szSpeed: PAnsiChar;
    szElapsed: PAnsiChar;
    szRemain: PAnsiChar;
  end;

  { User-defined data passed to callback. }
  TArcParam = array of HWND;

#ifndef IS_ENHANCED
  TPackCallbackProc = function (nState: UINT; var ExtInfo: TExtractingInfo; var ArcParam: TArcParam): BOOL;
#endif

// Unicode and Character Set Functions
function WideCharToMultiByte(CodePage: UINT; dwFlags: DWORD; lpWideCharStr: string; cchWideChar: Integer; lpMultiByteStr: AnsiString; cbMultiByte, lpDefaultChar: Integer; lpUsedDefaultChar: Longint): Integer; external 'WideCharToMultiByte@kernel32.dll stdcall';
function MultiByteToWideChar(CodePage: UINT; dwFlags: DWORD; lpMultiByteStr: AnsiString; cbMultiByte: Integer; lpWideCharStr: string; cchWideChar: Integer): Integer; external 'MultiByteToWideChar@kernel32.dll stdcall';
// Shell Lightweight Utility Functions
function PathCompactPath(hDC: THandle; lpszPath: string; dx: UINT): BOOL; external 'PathCompactPath{#A}@shlwapi.dll stdcall';
// Painting and Drawing Functions
function GetDC(hWnd: HWND): THandle; external 'GetDC@user32.dll stdcall';
// Device Context Functions
function ReleaseDC(hWnd: HWND; hDC: THandle): Integer; external 'ReleaseDC@user32.dll stdcall';
function SelectObject(hdc, hgdiobj: THandle): THandle; external 'SelectObject@gdi32.dll stdcall';
// Window Functions
function GetClientRect(hWnd: HWND; var lpRect: TRect): BOOL; external 'GetClientRect@user32.dll stdcall';
// Message Functions
function SendMessageString(hWnd: HWND; Msg: UINT; wParam: Longint; lParam: string): Longint; external 'SendMessage{#A}@user32.dll stdcall';
// Window Class Functions
function SetWindowLong(hWnd: HWND; nIndex: Integer; dwNewLong: Longint): Longint; external 'SetWindowLong{#A}@user32.dll stdcall';
// 7-zip.dll Functions
function SevenZip(const CmdLine: AnsiString; ArcProc: Longint; var LParam: TArcParam): Integer; external 'SevenZip@files:7-zip32.dll stdcall';
#ifndef IS_ENHANCED
// CallbackCtrl.dll Functions
function WrapPackProc(Callback: TPackCallbackProc; ParamCount: Integer): LongWord; external 'wrapcallbackaddr@files:callbackctrl.dll stdcall';
#endif

var
  ProgressInfoContainer, ProgressInfo: TNewStaticText;
  ArcProc: LongWord;

function UTF8Encode(const Value: string): AnsiString;
var
  Len: Integer;
  UTF16Buffer: string;
begin
  if Value = '' then Exit;
#ifndef UNICODE
  // на ANSI-версии компилятора сначала переводим строку в UTF-16LE (Unicode)
  Len := MultiByteToWideChar(CP_ACP, 0, Value, -1, '', 0);
  if Len = 0 then Exit;
  UTF16Buffer := StringOfChar(#0, Len shl 1);
  if MultiByteToWideChar(CP_ACP, 0, Value, -1, UTF16Buffer, Len) = 0 then Exit;
#else
  UTF16Buffer := Value;
#endif
  // перевод строки UTF-16LE (Unicode) в UTF-8
  Len := WideCharToMultiByte(CP_UTF8, 0, UTF16Buffer, -1, '', 0, 0, 0);
  if Len = 0 then Exit;
  Result := StringOfChar(#0, Len - 1);
  if WideCharToMultiByte(CP_UTF8, 0, UTF16Buffer, -1, Result, Len, 0, 0) = 0 then Exit;
end;

function UTF8Decode(const Value: AnsiString): string;
var
  Len: Integer;
#ifndef UNICODE
  UTF16Buffer: string;
#endif
begin
  if Value = '' then Exit;
#ifndef UNICODE
  // на ANSI-версии компилятора сначала переводим строку в UTF-16LE (Unicode)
  Len := MultiByteToWideChar(CP_UTF8, 0, Value, -1, '', 0);
  if Len = 0 then Exit;
  UTF16Buffer := StringOfChar(#0, Len shl 1);
  if MultiByteToWideChar(CP_UTF8, 0, Value, -1, UTF16Buffer, Len) = 0 then Exit;

  // перевод строки UTF-16 в ANSI
  Len := WideCharToMultiByte(CP_ACP, 0, UTF16Buffer, -1, '', 0, 0, 0);
  if Len = 0 then Exit;
  Result := StringOfChar(#0, Len - 1);
  if WideCharToMultiByte(CP_ACP, 0, UTF16Buffer, -1, Result, Len, 0, 0) = 0 then Exit;
#else
  // на Unicode-версии компилятора перевод строки UTF-8 в UTF-16LE (Unicode)
  Len := MultiByteToWideChar(CP_UTF8, 0, Value, -1, '', 0);
  if Len = 0 then Exit;
  Result := StringOfChar(#0, Len - 1);
  if MultiByteToWideChar(CP_UTF8, 0, Value, -1, Result, Len) = 0 then Exit;
#endif
end;

function PackCallbackProc(nState: UINT; var ExtInfo: TExtractingInfo; var ArcParam: TArcParam): BOOL;
var
  S: string;
  DC, SaveFont: THandle;
  H: HWND;
  R: TRect;
begin
  { Avoid call VCL methods or get/set properties. }
  Result := True;
  case nState of
    ARCEXTRACT_BEGIN:
      begin
        H := ArcParam[0];
        DC := GetDC(H);
        try
          SaveFont := SelectObject(DC, SendMessage(H, WM_GETFONT, 0, 0));
          GetClientRect(H, R);
          S := UTF8Decode(ExtInfo.szDestFileName);
          PathCompactPath(DC, S, R.Right - R.Left);
          SendMessageString(H, WM_SETTEXT, 0, S);
        finally
          if SaveFont <> 0 then
            SelectObject(DC, SaveFont);
          ReleaseDC(H, DC);
        end;
      end;
    ARCEXTRACT_INPROCESS:
      begin
        H := ArcParam[1];
        PostMessage(H, PBM_SETRANGE32, 0, 100);
        PostMessage(H, PBM_SETPOS, ExtInfo.dwProgress, 0);
        H := ArcParam[2];
        S := FmtMessage(CustomMessage('SevenZipProgressInfo'), [IntToStr(ExtInfo.dwProgress), ExtInfo.szWriteSize, ExtInfo.szFileSize, ExtInfo.szSpeed, ExtInfo.szElapsed, ExtInfo.szRemain]);
        SendMessageString(H, WM_SETTEXT, 0, S);
      end;
  end;
end;

procedure Pack(const APath: string);
var
  CmdLine: AnsiString;
  ArcParam: TArcParam;
  ResultCode: Integer;
begin
  { Pack files. }
  try
    WizardForm.StatusLabel.Caption := FmtMessage(CustomMessage('SevenZipStatusPackFiles'), [ExtractFileName(APath)]);
    ProgressInfoContainer.Show;
    CmdLine := UTF8Encode(Format('a -tzip -sdel -y "%0:s.pk3" "%0:s\*"', [APath]));
    SetLength(ArcParam, 3);
    ArcParam[0] := WizardForm.FilenameLabel.Handle;
    ArcParam[1] := WizardForm.ProgressGauge.Handle;
    ArcParam[2] := ProgressInfo.Handle;
    ResultCode := SevenZip(CmdLine, ArcProc, ArcParam);
    if ResultCode <> 0 then
      RaiseException(FmtMessage(CustomMessage('SevenZipPackFailed'), [ExtractFileName(APath), Format('0x%.8x', [ResultCode])]));
    if not RemoveDir(APath) then
    begin
      ResultCode := DLLGetLastError;
      RaiseException(FmtMessage(CustomMessage('UnableDeleteEmptyFolder'), [APath, ResultCode, SysErrorMessage(ResultCode)]));
    end;
  except
    ShowExceptionMessage;
    DelTree(ExtractFileDir(APath) + '\*.pk3', False, True, False);  // Rollback if error occured.
  finally
    ProgressInfoContainer.Hide;
    WizardForm.StatusLabel.Caption := SetupMessage(msgStatusExtractFiles);
    WizardForm.FilenameLabel.Caption := '';
  end;
end;

procedure CreateInstallingPage;
begin
  { ProgressInfoContainer. }
  ProgressInfoContainer := TNewStaticText.Create(WizardForm);
  with ProgressInfoContainer do
  begin
    Parent := WizardForm.InstallingPage;
    Align := alBottom;
    AutoSize := False;
    Caption := CustomMessage('SevenZipProgressCaptions');
    Height := Parent.ClientHeight - WizardForm.ProgressGauge.Top - WizardForm.ProgressGauge.Height - ScaleY(5);
  end;

  { ProgressInfo. }
  ProgressInfo := TNewStaticText.Create(WizardForm);
  with ProgressInfo do
  begin
    Parent := ProgressInfoContainer;
    Align := alRight;
    AutoSize := False;
    Width := Parent.ClientWidth div 2;
    SetWindowLong(Handle, GWL_STYLE, WS_CHILDWINDOW or WS_VISIBLE or WS_CLIPSIBLINGS or SS_RIGHT);
  end;
#ifdef IS_ENHANCED
  ArcProc := CallbackAddr('PackCallbackProc');
#else
  ArcProc := WrapPackProc(@PackCallbackProc, 3);
#endif
end;

procedure InitializeWizard;
begin
  CreateInstallingPage;
end;
Это сообщение посчитали полезным следующие участники:

Отправлено: 14:39, 04-01-2019 | #193


Новый участник


Сообщения: 1
Благодарности: 0

Профиль | Отправить PM | Цитировать


Кто платно поможет мне создать инсталлятор?


1) Выбор языка установщика;
2) Проверка на новую версию установщика;
3) Установки некоторых файлов;
4) Тихая установка дополнительных программ и утилит;
5) Установка ярлыков;
6) Показывать описание в отдельной окошке;
7) Интерфейс как на скриншоте.

Скрин я сильно фотошопил.

Последний раз редактировалось rashidzhan, 06-01-2019 в 06:46. Причина: уточнение про скрин


Отправлено: 06:44, 06-01-2019 | #194


Пользователь


Сообщения: 91
Благодарности: 7

Профиль | Сайт | Отправить PM | Цитировать


Цитата El Sanchez:
El Sanchez »
Цитата:
ясно, так и знал, что по-простому не выйдет.
1. El Sanchez, пожалуйста, будьте любезны, можно ПОЛНЫЙ скрипт, а также указать какую версию (и где взять) CallbackCtrl.dll и Inno Setip - вы использовали, что-то не получается! ((( То не пакует нормально, то архивы получаются битые, то папка не удаляется сразу после создания архива и перед распаковкой новой... Несколько раз компилировал, каждый раз по новому получалось...

2. Также подскажите, пожалуйста, как в этот скрипт добавить проверку ранее установленного приложения, например, по секции Uninstall, по названию и т.п., НО только с предупреждением, что приложение уже было установлено, БЕЗ запрета устанавливать "поверх"!
ПРОБЛЕМА В ТОМ, ЧТО ПРИЛОЖЕНИЕ МОЖЕТ НАЗЫВАТЬСЯ ПО РАЗНОМУ и в секции Uninstall, оно может быть в различных разделах! Я готов указать в скрипте ВСЕ ВОЗМОЖНЫЕ варианты, только скажите, куда и как это сделать?

Последний раз редактировалось TROY Diamond, 10-01-2019 в 15:29.


Отправлено: 15:20, 10-01-2019 | #195


Аватара для El Sanchez

Ветеран


Contributor


Сообщения: 1264
Благодарности: 1024

Профиль | Отправить PM | Цитировать


Цитата TROY Diamond:
можно ПОЛНЫЙ скрипт, а также указать какую версию (и где взять) CallbackCtrl.dll и Inno Setip - вы использовали, что-то не получается! »
TROY Diamond, пример и так полный, только без секции Setup и с тестовыми папками test01, test02 и файлом-пустышкой dummy в Files. Работает в обычной и в расширенной версиях. Ссылка на CallbackCtrl.dll приведена в Files.
Цитата TROY Diamond:
Также подскажите, пожалуйста, как в этот скрипт добавить проверку ранее установленного приложения, например, по секции Uninstall, по названию и т.п., НО только с предупреждением, что приложение уже было установлено, БЕЗ запрета устанавливать "поверх"!
ПРОБЛЕМА В ТОМ, ЧТО ПРИЛОЖЕНИЕ МОЖЕТ НАЗЫВАТЬСЯ ПО РАЗНОМУ и в секции Uninstall, оно может быть в различных разделах! Я готов указать в скрипте ВСЕ ВОЗМОЖНЫЕ варианты, только скажите, куда и как это сделать? »
TROY Diamond,
Скрытый текст

Код: Выделить весь код
function InitializeSetup: Boolean;
var
  UninstallSubKeyName: string;
begin
  UninstallSubKeyName := 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\';
  if RegKeyExists(HKLM, UninstallSubKeyName + 'AIMP') or
    RegKeyExists(HKLM, UninstallSubKeyName + '{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}') or
    RegKeyExists(HKLM, UninstallSubKeyName + 'Axialis IconWorkshop_is1') then
    MsgBox('Я никому не нужное информационное сообщение.', mbInformation, MB_OK);
end;
Это сообщение посчитали полезным следующие участники:

Отправлено: 11:12, 11-01-2019 | #196


Пользователь


Сообщения: 91
Благодарности: 7

Профиль | Сайт | Отправить PM | Цитировать


El Sanchez вместо "AIMP" и "{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}" - писать все возможные варианты?
А в MsgBox - написать что приложение уже было ранее установлено?

А как соединить с тем скриптом правильно?

Отправлено: 15:32, 11-01-2019 | #197


Аватара для El Sanchez

Ветеран


Contributor


Сообщения: 1264
Благодарности: 1024

Профиль | Отправить PM | Цитировать


Цитата TROY Diamond:
вместо "AIMP" и "{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}" - писать все возможные варианты? »
TROY Diamond, да. Я ж не знаю ваших вариантов.
Цитата TROY Diamond:
А в MsgBox - написать что приложение уже было ранее установлено? »
TROY Diamond, угу.
Цитата TROY Diamond:
А как соединить с тем скриптом правильно? »
TROY Diamond, копировать-вставить. Только я забыл в теле InitializeSetup строку Result := True; добавить, а то форму не увидите.

Отправлено: 17:34, 11-01-2019 | #198


Пользователь


Сообщения: 91
Благодарности: 7

Профиль | Сайт | Отправить PM | Цитировать


El Sanchez, так вот добавить?

Код: Выделить весь код
function InitializeSetup(): Boolean;
begin
Result:= True;
var
  UninstallSubKeyName: string;
begin
  UninstallSubKeyName := 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\';
  if RegKeyExists(HKLM, UninstallSubKeyName + 'AIMP') or
    RegKeyExists(HKLM, UninstallSubKeyName + '{FF66E9F6-83E7-3A3E-AF14-8DE9A809A6A4}') or
    RegKeyExists(HKLM, UninstallSubKeyName + 'Axialis IconWorkshop_is1') then
    MsgBox('Я никому не нужное информационное сообщение.', mbInformation, MB_OK);
end;
2. Соединить коды: 1-й со 2-м, сразу поле
Код: Выделить весь код
procedure InitializeWizard;
begin
  CreateInstallingPage;
end;
в первом коде вставить второй код?

3. Вы знали, наверное что будет это вопрос? ))) Как теперь подкорректировать размер свободного места на ЖД, который требует установщик? В нём ведь скомпилированы распакованные архивы и он считает их вес, а папки ведь поочередно удаляются после создания архивов, места нужно раза в 2 меньше, чем он хочет!

Отправлено: 18:49, 11-01-2019 | #199


Ветеран


Сообщения: 27449
Благодарности: 8086

Профиль | Отправить PM | Цитировать


Цитата TROY Diamond:
Как теперь подкорректировать размер свободного места на ЖД, который требует установщик? »
А куда он, простите, будет извлекать Ваши пока ещё не-архивы?!

Отправлено: 05:12, 12-01-2019 | #200



Компьютерный форум OSzone.net » Автоматическая установка Windows » Автоматическая установка приложений » Скрипты Inno Setup. Помощь и советы [часть 9]

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Скрипты Inno Setup. Помощь и советы [часть 7] El Sanchez Автоматическая установка приложений 2499 02-02-2015 08:59
Скрипты Inno Setup. Помощь и советы [часть 6] El Sanchez Автоматическая установка приложений 2494 10-03-2014 11:51
Скрипты Inno Setup. Помощь и советы [часть 5] El Sanchez Автоматическая установка приложений 1999 28-03-2013 19:09
Скрипты Inno Setup. Помощь и советы [часть 4] El Sanchez Автоматическая установка приложений 2099 22-05-2012 23:16
Скрипты Inno Setup. Помощь и советы [часть 3] Serega Автоматическая установка приложений 3755 26-10-2011 17:58




 
Переход