Создание начального образа с файлами / Модуль

файл
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2024, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Область ОбработчикиСобытийФормы

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	
	МетаданныеУзла = Параметры.Узел.Метаданные(); // ОбъектМетаданныхПланОбмена
	Менеджер = ПланыОбмена[МетаданныеУзла.Имя];
	
	Если Параметры.Узел = Менеджер.ЭтотУзел() Тогда
		ВызватьИсключение
			НСтр("ru = 'Создание начального образа для данного узла невозможно.'");
	Иначе
		ВидБазы = 0; // файловая база
		ТипСУБД = "";
		Узел = Параметры.Узел;
		МожноСоздатьФайловуюБазу = Истина;
		Если ОбщегоНазначения.ЭтоLinuxСервер() Тогда
			МожноСоздатьФайловуюБазу = Ложь;
		КонецЕсли;
		
		КодыЛокализации = ПолучитьДопустимыеКодыЛокализации();
		ЯзыкФайловойБазы = Элементы.Найти("ЯзыкФайловойБазы");
		ЯзыкБазыСервера = Элементы.Найти("ЯзыкБазыСервера");
		
		ЯзыкиФайловойБазы = ЯзыкФайловойБазы.СписокВыбора; // СписокЗначений
		ЯзыкиБазыСервера = ЯзыкБазыСервера.СписокВыбора; // СписокЗначений
		Для Каждого Код Из КодыЛокализации Цикл
			Представление = ПредставлениеКодаЛокализации(Код);
			ЯзыкиФайловойБазы.Добавить(Код, Представление);
			ЯзыкиБазыСервера.Добавить(Код, Представление);
		КонецЦикла;
		
		Язык = КодЛокализацииИнформационнойБазы();
		
	КонецЕсли;
	
	ЕстьФайлыВТомах = Ложь;
	
	Если РаботаСФайлами.ЕстьТомаХраненияФайлов() Тогда
		ЕстьФайлыВТомах = РаботаСФайламиСлужебный.ЕстьФайлыВТомах();
	КонецЕсли;
	
	ОССервераWindows = ОбщегоНазначения.ЭтоWindowsСервер();
	Если ОбщегоНазначения.ИнформационнаяБазаФайловая() Тогда
		Элементы.ПолноеИмяФайловойБазыLinux.Видимость = НЕ ОССервераWindows;
		Элементы.ПолноеИмяФайловойБазы.Видимость = ОССервераWindows;
	КонецЕсли;
	
	Если ЕстьФайлыВТомах Тогда
		Если ОССервераWindows Тогда
			Элементы.ПолноеИмяФайловойБазы.АвтоОтметкаНезаполненного = Истина;
			Элементы.ПутьКАрхивуСФайламиТомов.АвтоОтметкаНезаполненного = Истина;
		Иначе
			Элементы.ПолноеИмяФайловойБазыLinux.АвтоОтметкаНезаполненного = Истина;
			Элементы.ПутьКАрхивуСФайламиТомовLinux.АвтоОтметкаНезаполненного = Истина;
		КонецЕсли;
	Иначе
		Элементы.ГруппаПутьКАрхивуСФайламиТомов.Видимость = Ложь;
	КонецЕсли;
	
	Если Не ОбщегоНазначения.ИнформационнаяБазаФайловая() Тогда
		Элементы.ПутьКАрхивуСФайламиТомов.ПодсказкаВвода = НСтр("ru = '\\имя сервера\resource\files.zip'");
		Элементы.ПутьКАрхивуСФайламиТомов.КнопкаВыбора = Ложь;
	КонецЕсли;
	
	Если ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
		ПоложениеКоманднойПанели = ПоложениеКоманднойПанелиФормы.Авто;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПриОткрытии(Отказ)
	
	Элементы.СтраницыФормы.ТекущаяСтраница = Элементы.ИсходныеДанные;
	Элементы.СоздатьНачальныйОбраз.Видимость = Истина;
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиСобытийЭлементовШапкиФормы

&НаКлиенте
Процедура ВидБазыПриИзменении(Элемент)
	
	// Переключить страницу параметров.
	Страницы = Элементы.Найти("Страницы");
	Страницы.ТекущаяСтраница = Страницы.ПодчиненныеЭлементы[ВидБазы];
	
	Если ВидБазы = 0 Тогда
		Элементы.ПутьКАрхивуСФайламиТомов.ПодсказкаВвода = "";
		Элементы.ПутьКАрхивуСФайламиТомов.КнопкаВыбора = Истина;
	Иначе
		Элементы.ПутьКАрхивуСФайламиТомов.ПодсказкаВвода = НСтр("ru = '\\имя сервера\resource\files.zip'");
		Элементы.ПутьКАрхивуСФайламиТомов.КнопкаВыбора = Ложь;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ПутьКАрхивуСФайламиТомовНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	
	ОбработчикСохраненияФайла(
		Элемент,
		"ПутьКАрхивуСФайламиТомовWindows",
		СтандартнаяОбработка,
		"files.zip",
		"Архивы zip(*.zip)|*.zip");
	
КонецПроцедуры

&НаКлиенте
Процедура ПолноеИмяФайловойБазыНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
	
	ОбработчикСохраненияФайла(
		Элемент,
		"ПолноеИмяФайловойБазыWindows",
		СтандартнаяОбработка,
		"1Cv8.1CD",
		"Любой файл(*.*)|*.*");
	
КонецПроцедуры

&НаКлиенте
Процедура ПолноеИмяФайловойБазыПриИзменении(Элемент)
	
	Если ПустаяСтрока(ПолноеИмяФайловойБазыWindows) Тогда
		Возврат;
	КонецЕсли;
	
	СообщениеОбОшибке = "";
	Если Не ПроверкаПолногоИмениФайловойБазыНаСервере(ПолноеИмяФайловойБазыWindows, СообщениеОбОшибке) Тогда
		ПолноеИмяФайловойБазыWindows = "";
		Если Не ПустаяСтрока(СообщениеОбОшибке) Тогда
			ПоказатьПредупреждение(, СообщениеОбОшибке);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ТипСУБДПриИзменении(Элемент)
	
	СмещениеДат = ?(ТипСУБД = "MSSQLServer", 2000, 0);
	
КонецПроцедуры

#КонецОбласти

#Область ОбработчикиКомандФормы

&НаКлиенте
Процедура СоздатьНачальныйОбраз(Команда)
	
	ОчиститьСообщения();
	Если ВидБазы = 0 И НЕ МожноСоздатьФайловуюБазу Тогда
		
		ВызватьИсключение
			НСтр("ru = 'Создание начального образа файловой информационной базы
			           |на данной платформе не поддерживается.'");
	Иначе
		ПроцентВыполнения = 0;
		ДопИнформацияВыполнение = "";
		ПараметрыЗадания = Новый Структура;
		ПараметрыЗадания.Вставить("Узел", Узел);
		ПараметрыЗадания.Вставить("ПутьКАрхивуСФайламиТомовWindows", ПутьКАрхивуСФайламиТомовWindows);
		ПараметрыЗадания.Вставить("ПутьКАрхивуСФайламиТомовLinux", ПутьКАрхивуСФайламиТомовLinux);
		
		Если ВидБазы = 0 Тогда
			// Файловый начальный образ.
			ПараметрыЗадания.Вставить("УникальныйИдентификаторФормы", УникальныйИдентификатор);
			ПараметрыЗадания.Вставить("Язык", Язык);
			ПараметрыЗадания.Вставить("ПолноеИмяФайловойБазыWindows", ПолноеИмяФайловойБазыWindows);
			ПараметрыЗадания.Вставить("ПолноеИмяФайловойБазыLinux", ПолноеИмяФайловойБазыLinux);
			ПараметрыЗадания.Вставить("НаименованиеЗадания", НСтр("ru = 'Создание файлового начального образа'"));
			ПараметрыЗадания.Вставить("НаименованиеПроцедуры", "РаботаСФайламиСлужебный.СоздатьФайловыйНачальныйОбразНаСервере");
		Иначе
			// Серверный начальный образ.
			СтрокаСоединения =
				"Srvr="""       + Сервер + """;"
				+ ?(ЗначениеЗаполнено(ИмяАдминистратораКластера), "SUsr=""" + ИмяАдминистратораКластера + """;", "")
				+ ?(ЗначениеЗаполнено(ПарольАдминистратораКластера), "SPwd=""" + ПарольАдминистратораКластера + """;", "")
				+ "Ref="""      + ИмяБазы + """;"
				+ "DBMS="""     + ТипСУБД + """;"
				+ "DBSrvr="""   + СерверБазыДанных + """;"
				+ "DB="""       + ИмяБазыДанных + """;"
				+ "DBUID="""    + ПользовательБазыДанных + """;"
				+ "DBPwd="""    + ПарольПользователя + """;"
				+ "SQLYOffs=""" + Формат(СмещениеДат, "ЧГ=") + """;"
				+ "Locale="""   + Язык + """;"
				+ "SchJobDn=""" + ?(УстановитьБлокировкуРегламентныхЗаданий, "Y", "N") + """;";
			
			ПараметрыЗадания.Вставить("СтрокаСоединения", СтрокаСоединения);
			ПараметрыЗадания.Вставить("НаименованиеЗадания", НСтр("ru = 'Создание серверного начального образа'"));
			ПараметрыЗадания.Вставить("НаименованиеПроцедуры", "РаботаСФайламиСлужебный.СоздатьСерверныйНачальныйОбразНаСервере");
		КонецЕсли;
		Результат = ПодготовитьДанныеДляСозданияНачальногоОбраза(ПараметрыЗадания, ВидБазы);
		Если ТипЗнч(Результат) = Тип("Структура") Тогда
			Если Результат.ДанныеПодготовлены Тогда
				АдресПараметровЗадания = ПоместитьВоВременноеХранилище(ПараметрыЗадания, УникальныйИдентификатор);
				ОписаниеОповещения = Новый ОписаниеОповещения("ВыполнитьСозданиеНачальногоОбраза", ЭтотОбъект);
				Если Результат.ТребуетсяПодтверждение Тогда
					ПоказатьВопрос(ОписаниеОповещения, Результат.ТекстВопроса, РежимДиалогаВопрос.ДаНет);
				Иначе
					ВыполнитьОбработкуОповещения(ОписаниеОповещения, КодВозвратаДиалога.Да);
				КонецЕсли;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура Назад(Команда)
	
	Элементы.СтатусОшибка.Видимость = Ложь;
	Элементы.Назад.Видимость = Ложь;
	
	Элементы.СтатусГотово.Видимость = Истина;
	Элементы.СоздатьНачальныйОбраз.Видимость = Истина;
	Элементы.СтраницыФормы.ТекущаяСтраница = Элементы.ИсходныеДанные;
	
КонецПроцедуры

#КонецОбласти

#Область СлужебныеПроцедурыИФункции

&НаСервереБезКонтекста
Функция ПроверкаПолногоИмениФайловойБазыНаСервере(ПолноеИмяФайловойБазы, СообщениеОбОшибке = "")
	
	ПолноеИмяФайловойБазы = СокрЛП(ПолноеИмяФайловойБазы);
	
	СтруктураПути = ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла(ПолноеИмяФайловойБазы);
	Если Не ПустаяСтрока(СтруктураПути.Путь) Тогда
		ПутьКФайлу = СтруктураПути.Путь;
		
		Если ПустаяСтрока(СтруктураПути.Расширение) Тогда
			ПутьКФайлу = СтруктураПути.ПолноеИмя; 
			ПолноеИмяФайловойБазы = ОбщегоНазначенияКлиентСервер.ПолучитьПолноеИмяФайла(СтруктураПути.ПолноеИмя, "1Cv8.1CD");
		КонецЕсли;
		
		Если НайтиФайлы(ПутьКФайлу).Количество() = 0 Тогда
			СообщениеОбОшибке = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
				НСтр("ru = 'Папка ""%1"" не существует или не доступна.
				|Проверьте правильность указания пути.'"),
				ПутьКФайлу);
			Возврат Ложь;
		КонецЕсли;
	Иначе
		СообщениеОбОшибке = НСтр("ru = 'Укажите полный путь к файлу информационной базы.'");
		Возврат Ложь;
	КонецЕсли;
	
	Возврат Истина;
	
КонецФункции

&НаКлиенте
Процедура ОбработчикСохраненияФайла(
		Элемент,
		ИмяСвойства,
		СтандартнаяОбработка,
		ИмяФайла,
		Фильтр = "")
	
	СтандартнаяОбработка = Ложь;
	
	Контекст = Новый Структура;
	Контекст.Вставить("Элемент",     Элемент);
	Контекст.Вставить("ИмяСвойства", ИмяСвойства);
	Контекст.Вставить("ИмяФайла",    ИмяФайла);
	Контекст.Вставить("Фильтр",      Фильтр);
	
	Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
	
	Диалог.Заголовок = НСтр("ru = 'Выберите файл для сохранения'");
	Диалог.МножественныйВыбор = Ложь;
	Диалог.ПредварительныйПросмотр = Ложь;
	Диалог.Фильтр = Контекст.Фильтр;
	Диалог.ПолноеИмяФайла =
		?(ЭтотОбъект[Контекст.ИмяСвойства] = "",
			Контекст.ИмяФайла,
			ЭтотОбъект[Контекст.ИмяСвойства]);
	
	ОписаниеОповещенияДиалогаВыбора = Новый ОписаниеОповещения(
		"ОбработчикСохраненияФайлаПослеВыбораВДиалоге", ЭтотОбъект, Контекст);
	ФайловаяСистемаКлиент.ПоказатьДиалогВыбора(ОписаниеОповещенияДиалогаВыбора, Диалог);
	
КонецПроцедуры

// Параметры:
//   ВыбранныеФайлы - Массив
//                  - Неопределено
//   Контекст - Структура
//
&НаКлиенте
Процедура ОбработчикСохраненияФайлаПослеВыбораВДиалоге(ВыбранныеФайлы, Контекст) Экспорт
	
	Если ВыбранныеФайлы <> Неопределено
		И ВыбранныеФайлы.Количество() = 1 Тогда
		
		ЭтотОбъект[Контекст.ИмяСвойства] = ВыбранныеФайлы[0];
		Если Контекст.Элемент = Элементы.ПолноеИмяФайловойБазы Тогда
			ПолноеИмяФайловойБазыПриИзменении(Контекст.Элемент);
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

&НаСервереБезКонтекста
Функция ПодготовитьДанныеДляСозданияНачальногоОбраза(ПараметрыЗадания, ВидБазы)
	
	// Запись параметров подключения узла в константу.
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными") Тогда
		
		Отказ = Ложь;
		
		МодульПомощникСозданияОбменаДанными = ОбщегоНазначения.ОбщийМодуль("Обработки.ПомощникСозданияОбменаДанными");
		ПомощникСозданияОбменаДанными = МодульПомощникСозданияОбменаДанными.Создать();
		ПомощникСозданияОбменаДанными.Инициализация(ПараметрыЗадания.Узел);
		
		Попытка
			МодульПомощникСозданияОбменаДанными.ВыгрузитьНастройкиПодключенияДляПодчиненногоУзлаРИБ(
				ПомощникСозданияОбменаДанными);
		Исключение
			Отказ = Истина;
			ЗаписьЖурналаРегистрации(НСтр("ru = 'Обмен данными'", ОбщегоНазначения.КодОсновногоЯзыка()),
				УровеньЖурналаРегистрации.Ошибка, , , ОбработкаОшибок.ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
		КонецПопытки;
		
		Если Отказ Тогда
			Возврат Неопределено;
		КонецЕсли;
		
	КонецЕсли;
	
	Если ВидБазы = 0 Тогда
		// Файловый начальный образ.
		// Функция обработки, проверки и подготовки параметров.
		Результат = РаботаСФайламиСлужебный.ПодготовитьДанныеДляСозданияФайловогоНачальногоОбраза(ПараметрыЗадания);
	Иначе
		// Серверный начальный образ.
		// Функция обработки, проверки и подготовки параметров.
		Результат = РаботаСФайламиСлужебный.ПодготовитьДанныеДляСозданияСерверногоНачальногоОбраза(ПараметрыЗадания);
	КонецЕсли;
	
	Возврат Результат;
	
КонецФункции

&НаКлиенте
Процедура ВыполнитьСозданиеНачальногоОбраза(Результат, Контекст) Экспорт
	
	Если Результат = КодВозвратаДиалога.Да Тогда
		ПроцентВыполнения = 0;
		ДопИнформацияВыполнение = "";
		ПерейтиКСтраницеОжидания();
		ПодключитьОбработчикОжидания("ЗапуститьСозданиеНачальногоОбраза", 1, Истина);
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ЗапуститьСозданиеНачальногоОбраза()
	
	Результат = СоздатьНачальныйОбразНаСервере(ВидБазы);
	Если Результат = Неопределено Тогда
		Возврат;
	КонецЕсли;
	
	ОповещениеОЗавершении = Новый ОписаниеОповещения("СоздатьНачальныйОбразНаСервереЗавершение", ЭтотОбъект);
	ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
	ПараметрыОжидания.ВыводитьОкноОжидания = Ложь;
	ПараметрыОжидания.ВыводитьПрогрессВыполнения = Истина;
	ПараметрыОжидания.ОповещениеОПрогрессеВыполнения = Новый ОписаниеОповещения("СоздатьНачальныйОбразНаСервереПрогресс", ЭтотОбъект);
	ДлительныеОперацииКлиент.ОжидатьЗавершение(Результат, ОповещениеОЗавершении, ПараметрыОжидания);

КонецПроцедуры

&НаКлиенте
Процедура ПерейтиКСтраницеОжидания()
	Элементы.СтраницыФормы.ТекущаяСтраница = Элементы.ОжиданиеСозданияНачальногоОбраза;
	Элементы.СоздатьНачальныйОбраз.Видимость = Ложь;
КонецПроцедуры

&НаСервере
Функция СоздатьНачальныйОбразНаСервере(Знач Действие)
	
	Если ЭтоАдресВременногоХранилища(АдресПараметровЗадания) Тогда
		ПараметрыЗадания = ПолучитьИзВременногоХранилища(АдресПараметровЗадания);
		Если ТипЗнч(ПараметрыЗадания) = Тип("Структура") Тогда
			// Запуск фонового задания.
			ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
			ПараметрыВыполнения.НаименованиеФоновогоЗадания = ПараметрыЗадания.НаименованиеЗадания;
			
			Возврат ДлительныеОперации.ВыполнитьВФоне(ПараметрыЗадания.НаименованиеПроцедуры, ПараметрыЗадания, ПараметрыВыполнения);
		КонецЕсли;
	КонецЕсли;
	
КонецФункции

// Параметры:
//  Результат - см. ДлительныеОперацииКлиент.НовыйРезультатДлительнойОперации
//  ДополнительныеПараметры - Неопределено
//
&НаКлиенте
Процедура СоздатьНачальныйОбразНаСервереЗавершение(Результат, ДополнительныеПараметры) Экспорт
	
	ДопИнформацияВыполнение = "";
	
	Если Результат = Неопределено Тогда
		ПроцентВыполнения = 0;
		Элементы.СтатусОшибка.Заголовок = НСтр("ru = 'Действие отменено администратором.'");
		ЗапуститьПереходРезультат();
		Возврат;
	КонецЕсли;
	
	Если Результат.Статус = "Ошибка" Тогда
		ПроцентВыполнения = 0;
		Элементы.СтатусОшибка.Заголовок = НСтр("ru = 'Не удалось создать начальный образ по причине:'") + "
			|" + Результат.КраткоеПредставлениеОшибки;
		ЗапуститьПереходРезультат();
		СтандартныеПодсистемыКлиент.ВывестиИнформациюОбОшибке(
			Результат.ИнформацияОбОшибке);
		Возврат;
	КонецЕсли;
	
	ПроцентВыполнения = 100;
	ЗапуститьПереходРезультат();
	
КонецПроцедуры

// Параметры:
//  Результат - см. ДлительныеОперацииКлиент.НовоеСостояниеДлительнойОперации
//  ДополнительныеПараметры - Неопределено
//
&НаКлиенте
Процедура СоздатьНачальныйОбразНаСервереПрогресс(Результат, ДополнительныеПараметры) Экспорт
	
	Если Результат.Статус = "Выполняется"
	   И Результат.Прогресс <> Неопределено Тогда
		
		ПроцентВыполнения = Результат.Прогресс.Процент;
		ДопИнформацияВыполнение = Результат.Прогресс.Текст;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиенте
Процедура ЗапуститьПереходРезультат()
	Элементы.СтраницыФормы.ТекущаяСтраница = Элементы.Результат;
	Элементы.СоздатьНачальныйОбраз.Видимость = Ложь;
	
	Если ПроцентВыполнения = 100 Тогда
		ЗавершитьСозданиеНачальногоОбраза(Узел);
	Иначе
		Элементы.СтатусГотово.Видимость = Ложь;
		Элементы.СтатусОшибка.Видимость = Истина;
		Элементы.Назад.Видимость = Истина;
	КонецЕсли;
	
КонецПроцедуры

&НаСервереБезКонтекста
Процедура ЗавершитьСозданиеНачальногоОбраза(УзелОбмена)
	
	Если ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ОбменДанными") Тогда
		МодульОбменДаннымиСервер = ОбщегоНазначения.ОбщийМодуль("ОбменДаннымиСервер");
		МодульОбменДаннымиСервер.ЗавершитьСозданиеНачальногоОбраза(УзелОбмена);
	КонецЕсли;
	
КонецПроцедуры

#КонецОбласти

Связанные материалы