gifts2017

Резервное копирование информационных баз 1С 8.2 (консольное приложение на DELPHI, Клиент-Сервер)

Опубликовал Мих Кор (qapex) в раздел Администрирование - Архивирование (backup)

Программа производит блокировку входа пользователей, отключает всех от базы, выгружает базу в .dt средствами 1с.
После окончания выгрузки снимает блокировку. В архиве имеются исходники.

 

Запускать можно без параметров тогда программа возьмет с файла "cfg.ini" раздел "default" если его нету то выйдет.

В  файле "cfg.ini" можно прописать несколько разделов и передавать их названия в качестве параметров.

Пример  файла "cfg.ini" :

[default]
DumpPath=C:\
ServerName=uppserver
InfoBaseName=test
ClasterPortNumber=1541
InfoBasesAdminName=admin
InfoBasesAdminPass=123
ClasterAdminName=
ClasterAdminPass=
LockPermissionCode=1234

[upp]
DumpPath=C:\
ServerName=server2
InfoBaseName=upp
ClasterPortNumber=1541
InfoBasesAdminName=admin
InfoBasesAdminPass=123
ClasterAdminName=
ClasterAdminPass=
LockPermissionCode=123455

Листинг кода на Delphi 7:

program backup;

//Не будем светить окном
//{$APPTYPE CONSOLE}

uses
Windows,
SysUtils,
Variants,
ComObj,
Registry,
inifiles,
ActiveX;

type
TdataZap = record
DumpPath : string;
ServerName : string;
InfoBaseName : string;
ClasterPortNumber : string;
InfoBasesAdminName : string;
InfoBasesAdminPass : string;
ClasterAdminName : string;
ClasterAdminPass : string;
LockPermissionCode : string;
end;

//Найдем путь до 1с (результат функции, пример: 'C:\Program Files\1cv82\8.2.19.76\bin\1cv8.exe')
function Path1C:string;
var reg : TRegistry;
begin
reg:=TRegistry.Create;
reg.RootKey:=HKEY_CLASSES_ROOT;
reg.OpenKey('\CLSID\{5CD98F13-1050-4b43-84F2-33AD97CFC287}\LocalServer32\', false);
result:=reg.ReadString('');
reg.CloseKey;
reg.Free;
end;

//выполнить запуск с ожиданием завершения процесса
function ExecAndWait(const FileName,
Params: ShortString;
const WinState: Word): boolean; export;
var
StartInfo: TStartupInfo;
ProcInfo: TProcessInformation;
CmdLine: ShortString;
begin
{ Помещаем имя файла между кавычками, с соблюдением всех пробелов в именах Win9x }
CmdLine := '"' + Filename + '" ' + Params;
FillChar(StartInfo, SizeOf(StartInfo), #0);
with StartInfo do
begin
cb := SizeOf(StartInfo);
dwFlags := STARTF_USESHOWWINDOW;
wShowWindow := WinState;
end;
Result := CreateProcess(nil, PChar( String( CmdLine ) ), nil, nil, false,
CREATE_NEW_CONSOLE or NORMAL_PRIORITY_CLASS, nil,
PChar(ExtractFilePath(Filename)),StartInfo,ProcInfo);
{ Ожидаем завершения приложения }
if Result then
begin
WaitForSingleObject(ProcInfo.hProcess, INFINITE);
{ Free the Handles }
CloseHandle(ProcInfo.hProcess);
CloseHandle(ProcInfo.hThread);
end;
end;

procedure Zapusk(dataR:TdataZap);
var
bin1c,LockMessageText,FullPathName,sDate1,sDate2:string;
FindInfoBase:boolean;
ComConnector,ServerAgent,Clasters,WorkingProcesses,
connecttoworkprocess,InfoBases,InfoBase,Connections:Variant;
lK,lW,lB,lC: LongWord;
begin
bin1c := Path1C; //прочитаем путь до 1с из реестра

LockMessageText := 'База закрыта на БЭКАП';
FindInfoBase:=false;
DateTimeToString(sDate1, 'yyyy-mm-dd', now());
DateTimeToString(sDate2, 'HH-NN', now());
FullPathName:=dataR.DumpPath+sdate1+'_'+sdate2+'_'+dataR.InfoBaseName+'.dt';

ComConnector :=UnAssigned;
ComConnector := CreateOLEObject('V82.ComConnector');
ServerAgent := ComConnector.ConnectAgent(dataR.ServerName);
//Получим массив кластеров сервера
Clasters := ServerAgent.GetClusters;
for lK := 0 to VarArrayHighBound(Clasters, 1) do
//проверка на нужный порт кластера(если больше одного)
If Clasters[lK].MainPort = dataR.ClasterPortNumber Then
begin
ServerAgent.Authenticate(Clasters[lK],dataR.ClasterAdminName,dataR.ClasterAdminPass);
//Получим список рабочих процессов
WorkingProcesses := ServerAgent.GetWorkingProcesses(Clasters[lK]);
for lW := 0 to VarArrayHighBound(WorkingProcesses, 1) do
If WorkingProcesses[lW].Running = 1 Then
begin
connecttoworkprocess := ComConnector.ConnectWorkingProcess('tcp://'+WorkingProcesses[lW].HostName + ':' + inttostr(WorkingProcesses[lW].MainPort));
connecttoworkprocess.AuthenticateAdmin(dataR.ClasterAdminName, dataR.ClasterAdminPass);
connecttoworkprocess.AddAuthentication(dataR.InfoBasesAdminName, dataR.InfoBasesAdminPass);
If Not FindInfoBase Then
begin
InfoBases := connecttoworkprocess.GetInfoBases;
for lB := 0 to VarArrayHighBound(InfoBases, 1) do
if LowerCase(InfoBases[lB].Name) = LowerCase(dataR.InfoBaseName) then
begin
InfoBase:=InfoBases[lB];
FindInfoBase:=true;
end;
end;
end;
end;

//Заблокируем базу
if FindInfoBase then
begin
InfoBase.ConnectDenied := True;
InfoBase.ScheduledJobsDenied := True;
InfoBase.DeniedFrom := now();
InfoBase.DeniedTo :=now()+300/86400; //Блокировка на 5 минут
InfoBase.DeniedMessage := 'Блокировка базы';
InfoBase.PermissionCode := dataR.LockPermissionCode;
connecttoworkprocess.UpdateInfoBase (InfoBase);
end;

//Отключим все соединения с базой
if FindInfoBase then
begin
Connections := connecttoworkprocess.GetInfoBaseConnections(InfoBase);
for lC := 0 to VarArrayHighBound(Connections, 1) do
If Connections[lC].AppId <> 'SrvrConsole' Then connecttoworkprocess.Disconnect(Connections[lC]);
//Запускаем архивацию с ожиданием выполнения
ExecAndWait( bin1c,
' CONFIG /S' + dataR.ServerName + '\' + dataR.InfoBaseName +
' /N' + dataR.InfoBasesAdminName + ' /P' + dataR.InfoBasesAdminPass +
' /UC' + dataR.LockPermissionCode + ' /DisableStartupMessages /DumpIB' +'"'+ FullPathName+'"', SW_SHOWNORMAL);
end;

//разблокируем базу
if FindInfoBase then
begin
InfoBase.ConnectDenied := False;
InfoBase.ScheduledJobsDenied := False;
connecttoworkprocess.UpdateInfoBase (InfoBase);
end;

end;

procedure Zagruzka(paramStrP,paramstr: string);
var dataR:TdataZap;
Ini: Tinifile;
begin
Ini := TiniFile.Create(extractfilepath(ParamStrP)+'cfg.ini');
dataR.DumpPath := Ini.ReadString(paramstr,'DumpPath','-');
dataR.ServerName := Ini.ReadString(paramstr,'ServerName','-');
dataR.InfoBaseName := Ini.ReadString(paramstr,'InfoBaseName','-');
dataR.ClasterPortNumber := Ini.ReadString(paramstr,'ClasterPortNumber','-');
dataR.InfoBasesAdminName := Ini.ReadString(paramstr,'InfoBasesAdminName','-');
dataR.InfoBasesAdminPass := Ini.ReadString(paramstr,'InfoBasesAdminPass','-');
dataR.ClasterAdminName := Ini.ReadString(paramstr,'ClasterAdminName','-');
dataR.ClasterAdminPass := Ini.ReadString(paramstr,'ClasterAdminPass','-');
dataR.LockPermissionCode := Ini.ReadString(paramstr,'LockPermissionCode','-');
Ini.Free;
if NOT(dataR.ServerName='-') then Zapusk(dataR);
end;

begin
CoInitialize(nil);
if ParamCount>0 then
Zagruzka(ParamStr(0),ParamStr(1))
else
Zagruzka(ParamStr(0),'default');
CoUnInitialize;
end.

 

Скачать файлы

Наименование Файл Версия Размер
backup.7z 35
.7z 55,38Kb
05.02.14
35
.7z 55,38Kb Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Сергей Куликов (ksvd) 05.02.14 13:21
Работает. Спасибо. Для себя узнал - что можно искать путь к 1cv8.exe по CLSID.

2. Александр Астафьев (Astafan) 05.02.14 21:19
Как во-время, сейчас стоит задача запуска резервного копирования баз в формате DT. Ознакомлюсь с возможностями.
3. ффф ыыы (zqzq) 06.02.14 08:54
Вообще-то сама 1С в документации рекомендует для клиент-сервера копии делать через СУБД. Тогда и выгонять никого не надо и проблем меньше. dt* это для загрузки в файловую и обратно, а не для резервного копирования.
4. Александр Лыткин (TrinitronOTV) 06.02.14 09:52
а я просто копирую папку базы в файловом варианте, наверное этого достаточно...
5. Артем Артеменко (dock) 12.02.14 08:11
нда... конечно информация полезная - автоматическая выгрузка в .dt
но практическое применение... под сомнением.
1) при sql-версии все прекрасно выгружается средствами СУБД.
2) при файловом варианте достаточно копировать папку (опять таки, есть средства БЕЗ отключения пользователей)...
6. Александр Астафьев (Astafan) 28.03.14 10:26
(5) dock,
Это идеальный вариант, когда на небольшом предприятии выходит из строя сервер и можно быстро восстановить базу на любом мощном рабочем компьютере не разворачивая SQL.
7. ressurect83 Tester (ressurect83) 06.02.15 20:48
Не стартует, выдало ошибку EOleSysError in module backup.exe at 00014B4D
Не допустимая строка с указанием класса.
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа