Последняя версия DataExpress 3 beta от 1 сентября 2019 года.
Изображение Скачать | Изображение Что нового?
См. также: Энциклопедия DX | Форум на develop-soft | Песочница
ИзображениеИзображениеИзображение

Резервное копирование базы

Расширение функционала и существующих возможностей программы с помощью модулей расширений и плагинов от сторонних разработчиков.

Модератор: Разработчики расширений

Аватара пользователя
admin
Разработчик
Сообщения: 4551
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская
Благодарил (а): 19 раз
Поблагодарили: 80 раз

Резервное копирование базы

Сообщение admin » Ср фев 06, 2019 9:08 pm

Расширение добавляет кнопку резервного копирования базы на панель инструментов. База архивируется при помощи утилиты 7zip, которая автоматически скачивается с сайта http://mydataexpress.ru. Базы архивируются в определенную папку. Имена архивов имеют вид: дата_время_база.7z. Тип действия: действие при запуске.

2.1 (актуальная)
1. Исправлена ошибка копирования шаблонов, если в пути есть символы кириллицы.

2.0
1. Резервное копирование , восстановление и сжатие сетевой базы данных утилитой gbak.
2. Резервное копирование при закрытии базы.
3. Добавление задачи в планировщик заданий.
Backups.7z
(7.54 КБ) 19 скачиваний

1.0
Backups 1.0.zip
(4.11 КБ) 154 скачивания
Вложения
Backups 2.1.7z
Актуальная версия расширения
(7.54 КБ) 31 скачивание
BACKUP_DEMO.7z
Демонстрационная база
(41.15 КБ) 15 скачиваний

Теги:

Аватара пользователя
rausNT
Специалист
Сообщения: 696
Зарегистрирован: Чт авг 24, 2017 9:23 am
Благодарил (а): 66 раз
Поблагодарили: 6 раз

Re: Резервное копирование базы

Сообщение rausNT » Чт фев 07, 2019 8:42 am

admin писал(а): База архивируется при помощи утилиты 7zip


а почему не gbak? Кажется копирование БД с подключением может привести к ошибкам. Или это не так?

Аватара пользователя
admin
Разработчик
Сообщения: 4551
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская
Благодарил (а): 19 раз
Поблагодарили: 80 раз

Re: Резервное копирование базы

Сообщение admin » Чт фев 07, 2019 10:27 am

gbak не может получить доступ к файлу, занятому другим процессом.
rausNT писал(а):Кажется копирование БД с подключением может привести к ошибкам. Или это не так?
Вряд ли могут быть какие-то ошибки, когда к базе подключен только один пользователь и нет никакой активности в базе.

Аватара пользователя
Гocть
Эксперт
Сообщения: 1583
Зарегистрирован: Пн ноя 27, 2017 8:02 am
Поблагодарили: 8 раз

Re: Резервное копирование базы

Сообщение Гocть » Пн фев 11, 2019 8:10 am

admin писал(а):База архивируется при помощи утилиты 7zip, которая автоматически скачивается с сайта http://mydataexpress.ru.

Вариант без тулзов:

Код: Выделить всё

{@module
author=DataExpress
version=1.0
description=Резервное копирование базы.
@}

{@action
id=12DE2332-F65D-48AA-88B2-98C1724D3914
target=main
origname=BackupDatabase
name=Резервное копирование базы
group=Инструменты
ui=
  <ui>
    <folder name="backup_folder" caption="Папка для резервных копий" required="1"/>
    <checkbox name="backup_templates" caption="Архивировать шаблоны"/>
    <text name="prompt" caption="Подтверждение перед резервным копированием"/>
  </ui>
description=Добавляет кнопку на панель инструментов для резервного копирования
базы. Расширение использует стандартные возможности архивирования zip в Windows для
сжатия текущей базы. Имя файла архива имеет следующий вид:
<i>Дата_Время_ИмяФайлаБД.zip</i>. Папка для резервных копий создается автоматически.
Резервное копирование работает только при локальном подключении к базе, т. е.
когда база открыта командой "Файл-Открыть" или в настройках подключения нет флажка
"Удаленная база". Также при наличии в базе работающих в фоне скриптов (таймеры, циклы)
возможны ошибки. <br><br>
Если поле подтверждения заполнено, то перед резервным копированием появится
окно подтверждение действия.
@}

procedure Sleep(Ms:Cardinal); external 'Sleep@kernel32 stdcall';

const
  ImageStr = 'iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuNWRHWFIAAAUbSURBVEhLtVRtTJNXFGZj8wM10RqjhIhMSTCZIESmidmonUyiJDInEr7mjwFmGuMPjXGOOXAZKgN0Ik6koAht+RaQThEUKEVrBWnth7agA90E005B8Csm73123relimEbLNlJnvT2vjnnuee557lu/3tMnz7dfd68eR97enp+8k+YM2eOrzNlYjFt2jRRcHAwt379evZ3WLt2LZs/f77UmTKx4AlCQkK4vXv3svT0dDgxar1161Z4e3v/NwIPDw/RypUrucbGRkYBJ/hwrQ8ePIhNmzZZVCpVgUajGRfUarU0Pj7eQyBYvnw5l5+fz3Q6nQt9fX2M4zg2ODjItm3bxrKzs9mrV6/GjZcvX3KxsbEit6lTp4qCgoK48PBwRgCPmJgYZrPZ8OLFC+zatUvYz8rKYk1NTTh06BAjCNJR1ygoKIBWq2WVlZX8N2Gf3xsYGOCojoNgyZIlnEQiYSOor6/nT8Dkcrlr78CBA0yv17PS0lKWlpbGVq9ezZRKJUtMTGQlJSVs3759bMeOHUwmk7HIyEgmlUq56OhoB4Gfnx+3YsUKRkBcXByePXvGS4OwsDCM7KempjK+I166devWgSd5/vw5SAbwRXfv3o3k5GTw8kZFRfEdOwimTJkiWrhwIefv788IKCwshN1uZw3UfnpGBqQFpyBTlOCc8lfc0OtRcOo0Uvfvh81mFwgiIiL4HLZ9+3bQuGPNmjUsKSkJPT09Dol4AhpBztfXly1atAitajXKKs9CUVGF6rrzuNB4CZdaWqG6osFVbTu0HZ3o6NRDo72OTp0OoaGh4AckISEBKSkpQvcEDA8POzqYPHmyiJzKeXl5MZomlnfqDIoUZaioroWyvgGXW9S4QoXbO3Xo1BugN5pgNN+C+bZVICJJmUKhYDt37mSZmZns6dOnAoaGhl4T0DPAzZ49mwUELEVhsRwldPoa5Xk0XG6GWqOl4nrcNJlhum3BbWsXrN130H33N6ELi9UKKsYX5H9d6ydPnrwmoOBmzJjBFizwQWlZOerOX0CTSg1V21Vc67gBncFIJ7bAeucu7vb0ovfefehuGvDLyTyYTCa+mItgZE1DwpE5RW6TJk1ynzlz5rJZs2YFh4jFW06fKYKivAL9NjseDwzARHK0tKpRT5duNJsxNDyMnt5eXKS7OZqTg6SkLUnklU/HgIT8857zwXBE/ObN4h9+TGNFcgXuP3hApxmCgU5YWV2NE3lSNKtUsNntgiz1DTRlpHn8l5uXOtPHDgAuREVHi3Op7YzDh1FTVwcdjaX2ejvKq84KcpytqYW67Qpq6dtpGuefyN0RG75Y+maNtzHqT2xcvPhMsQyy0jJYurvR3tEh3MnxE7k4cjQbZeXlMBgMJJsZFy424OdjOYiMiho/wVcJieL0jExWRMb6va9f0NtI0zMikYru4s9Hj2Dt6hIkOpJ9jFHO+Ak+CwtbdTJPyo7nnkRzayt6e+/RrHe6JOLdbDAa0dTcgoqqKr4rJpZIAt+s8TZGhY/PB58Xy+WQkyxmiwWaa9cEvYtkcuTTE3GO1vTgwXzrltABL9HcuXNXOdP/PWhk/b77PuVhcUkp/uh/CHKkoHdldQ1OSKVobWsTRreLjMYT7Pk2+d677u7ezvRxxTtkvKANGzeWN15uetzX348b9N5UOCVSkgFJf1ZTW2uPjokppgN9yOc4UicW7xO86AkJDQwM/HpZ8Eff+AcE7PFbvHgLGVJC3zwJo000Zri5/QXpsKQg3B++lgAAAABJRU5ErkJggg==';

var
  BackupFolder, Prompt: String;
  BackupTemplates: Boolean;

function AddToImageList(IL: TCustomImageList; const S: String): Integer;
var
  SS: TStringStream;
  Img: TdxImage;
begin
  SS := TStringStream.Create(DecodeBase64(S, False));
  Img := TdxImage.Create(nil);
  try
    Img.LoadFromStream(SS);
    Result := IL.Add(Img.Bitmap, nil);
  finally
    Img.Free;
    SS.Free;
  end;
end;

function DateTime2Str: String;
var
  DT: TDateTime;
begin
  DT := Now;
  Result := Format('%d.%s.%s_%s-%s-%s', [YearOf(DT), FillZeros(MonthOf(DT), 2),
    FillZeros(DayOf(DT), 2), FillZeros(HourOf(DT), 2),
    FillZeros(MinuteOf(DT), 2),FillZeros(SecondOf(DT), 2)]);
end;


function CheckDatabase: Boolean;
begin
  Result := FileExists(GetCurrentDatabase);
  if not Result then
  MsgBox('Внимание', 'Резервное копирование работает только с локальными базами.');
end;

function CreateZipArchive(FilesToAdd:array of string;ZipName:string):boolean;
var Ss:TstringStream; Sl:TStringList;
    objShell:variant;
    i:integer;
begin
  Ss:=TStringStream.Create(#80#75#5#6+StringOfChar(#0,18));
  Ss.Position:=0;
  Sl:=TStringlist.Create;
  Sl.LoadFromStream(ss);
  try
    Sl.SaveToFile(ZipName);
    objShell := CreateOleObject('Shell.Application');
    for i:=0 to GetArrayLength(FilesToAdd)-1 do if Trim(FilesToAdd[i])<>'' then
    begin
    Sleep(100);
    objShell.NameSpace(ZipName).CopyHere(FilesToAdd[i]);
    end;
    result:=true;
  except
    MsgBox('Ошибка создания архива',ExceptionParam);
    result:=false;
  finally
   Sl.Free;
   Ss.Free;
   objShell := Unassigned;
  end;
end;

procedure RunBackup;
var
  BackFile, Templates: String;
begin
  if Prompt <> '' then
    if MessageDlg('Внимание', Prompt, mtConfirmation, [mbYes, mbNo]) = mrNo then Exit;
  if not CheckDatabase then Exit;
  BackFile := IncludeTrailingPathDelimiter(BackupFolder) + DateTime2Str + '_' +
    ExtractFileNameOnly(GetCurrentDatabase) + '.zip';
  if BackupTemplates then
    Templates := GetTemplatesDir
  else
    Templates := '';
    if CreateZipArchive([GetCurrentDatabase,Templates],BackFile) then
    MsgBox('Успешно!','Резервная копия БД создана в архиве:'+#13#10+BackFile)
end;

procedure ToolButtonClick(Sender: TObject);
begin
  RunBackup;
end;

procedure MenuItemClick(Semder: TObject);
begin
  ShellExecute('explore', BackupFolder, '', '', 1);
end;

procedure AddButton;
var
  Bn: TToolButton;
  TB: TToolBar;
  MI: TMenuItem;
begin
  TB := MainWindow.ToolBar;
  Bn := TToolButton.Create(TB);
  Bn.Left := TB.Buttons[TB.ButtonCount - 1].Left + TB.ButtonWidth;
  Bn.Parent := TB;
  Bn.OnClick := @ToolButtonClick;
  Bn.ImageIndex := AddToImageList(TB.Images, ImageStr);
  Bn.Hint := 'Сделать резервную копию базы';
  Bn.Style := tbsDropDown;
  Bn.DropDownMenu := TPopupMenu.Create(Bn);
  MI := TMenuItem.Create(Bn.DropDownMenu);
  MI.Caption := 'Открыть папку резервных копий';
  MI.OnClick := @MenuItemClick;
  Bn.DropDownMenu.Items.Add(MI);
end;

procedure BackupDatabase(const ABackupFolder: String; ABackupTemplates: Boolean;
  const APrompt: String);
begin
  if BackupFolder <> '' then
  begin
    MsgBox('Внимание!', 'Действие "Резервное копирование базы" уже используется.')
    Exit;
  end;
  BackupFolder := ABackupFolder;
  BackupTemplates := ABackupTemplates;
  Prompt := APrompt;
  AddButton;
end;
Фрилансер. Разработка на заказ. Консультирование.

Аватара пользователя
admin
Разработчик
Сообщения: 4551
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская
Благодарил (а): 19 раз
Поблагодарили: 80 раз

Re: Резервное копирование базы

Сообщение admin » Пн фев 11, 2019 8:59 am

Интересное решение, не знал о такой возможности.

Аватара пользователя
Гocть
Эксперт
Сообщения: 1583
Зарегистрирован: Пн ноя 27, 2017 8:02 am
Поблагодарили: 8 раз

Re: Резервное копирование базы

Сообщение Гocть » Пн фев 11, 2019 10:36 pm

В windows есть еще много способов (expand, makecab, RtlCompressBuffer в ядре, набор функций из cabinet.dll), но с ole проще.
Фрилансер. Разработка на заказ. Консультирование.

Nikxdrummer
Интересующийся
Сообщения: 236
Зарегистрирован: Чт фев 16, 2017 10:56 am
Откуда: Новосибирск
Благодарил (а): 2 раза

Re: Резервное копирование базы

Сообщение Nikxdrummer » Вт фев 12, 2019 10:22 am

А для копирования удаленной базы будет доработано расширение или такой возможности нет?

Аватара пользователя
Гocть
Эксперт
Сообщения: 1583
Зарегистрирован: Пн ноя 27, 2017 8:02 am
Поблагодарили: 8 раз

Re: Резервное копирование базы

Сообщение Гocть » Вт фев 12, 2019 10:45 am

Кое чего не хватает в составе сборки для реализации.
Ну а вообще бэкапить серверную бд это задача самого сервера. На нем это реализуется с присутствующим в составе firebird gbak и планировщика (windows) или cron (linux).
Фрилансер. Разработка на заказ. Консультирование.

Аватара пользователя
admin
Разработчик
Сообщения: 4551
Зарегистрирован: Пн мар 14, 2016 11:32 am
Откуда: Ленинградская
Благодарил (а): 19 раз
Поблагодарили: 80 раз

Re: Резервное копирование базы

Сообщение admin » Вт фев 12, 2019 11:22 am

Nikxdrummer писал(а):А для копирования удаленной базы будет доработано расширение или такой возможности нет?

Сделать можно, по возможности.

Nikxdrummer
Интересующийся
Сообщения: 236
Зарегистрирован: Чт фев 16, 2017 10:56 am
Откуда: Новосибирск
Благодарил (а): 2 раза

Re: Резервное копирование базы

Сообщение Nikxdrummer » Чт фев 14, 2019 7:26 am

admin писал(а):
Nikxdrummer писал(а):А для копирования удаленной базы будет доработано расширение или такой возможности нет?

Сделать можно, по возможности.

Было бы здорово, буду ждать обновления, спасибо!


Вернуться в «Расширения и плагины»