Синтаксис и применение ЧтениеJSON.По умолчанию в платформе 1С:Предприятие. Описание и примеры кода.
Синтаксис
Новый ЧтениеJSONПолное описание, параметры и ограничения
ЧтениеJSON.По умолчанию
ЧтениеJSON (JSONReader)
По умолчанию
Синтаксис:
Новый ЧтениеJSON
Методическая информация
Практические примеры
Создать собственное адресное запрещающее требование, частично применить и отдельно удалить
CreateAssignmentRule/RegAssignmentRule/ApplyAssignmentRules/UnregAssignmentRule на своем вторичном UUID-сервере; исходное автоматическое запрещающее требование сохраняется.
Где и как запускать
Полный серверный общий модуль УчебныйCOM85 и полный модуль управляемой формы в отдельной файловой учебной ИБ. Свой Windows-агент/RAS, точная платформа8.5.1.1343; перечисленные записи являются только авторским учебным кодом, фактических запусков0.
Подготовка
Работайте только в новой отдельной Windows-VM без рабочих процессов/кластеров. Установленная платформа и заранее зарегистрированный V85.COMConnector должны быть8.5.1.1343 соответствующей разрядности. Регистрацию COM и запуск служб этот BSL не выполняет.
Создайте отдельную файловую ИБ с именем конфигурации УчебныйЖизненныйЦиклCOM85: без данных, каталогов, документов, регистров, подписок, фоновых заданий и расширений. В ней создайте общий модуль УчебныйCOM85: Сервер=Истина, ВызовСервера=Истина, Глобальный=Ложь, Клиент/ВнешнееСоединение=Ложь. Вставьте полностью код одного урока, не смешивайте одинаковые функции разных уроков.
Создайте обработку и управляемую форму с командой Выполнить и полным модулем формы из дополнительного блока. Строковые реквизиты: Операция, ИмяАгента, ПарольАгента, ИмяАдминистратора, ПарольАдминистратора, UUIDОпыта, UUIDКластера, Дополнительно; числовые ПортАгента, ПортRAS, ПортКластера; булевый ПодтвержденСвойСтенд. Поля всех паролей и Дополнительно переведите в режим пароля, значения не сохраняйте в настройках.
В своей VM вручную поднимите один отдельный ragent и один ras с отдельным новым каталогом реестров. RAS должен обслуживать именно этот агент, а не другой локальный сервис. Из реально выбранных администратором свободных портов впишите три разные величины: agent-port для ConnectAgent, ras-port для АдминистрированиеСервера, manager-port для своего кластера. Не подставляйте1545 в ConnectAgent.
До первого создания кластера вручную удалите только автоматически созданный пустой кластер своей новой VM, если он появился. Консоль должна показывать0кластеров; никакие чужие кластеры не допускаются. Первый урок также проверяет нулевой список обоими интерфейсами до RegCluster.
Заведите постоянного своего администратора агента и после создания кластера постоянного своего администратора кластера через консоль. Их реальные новые учебные пароли передавайте форме; учебные временные администраторы в уроке никогда не заменяют постоянных.
Один раз самостоятельно получите UUIDОпыта в своей файловой ИБ выражением Строка(Новый УникальныйИдентификатор), сохраните текст в собственном журнале опыта. Имя кластера: own-com85-cluster-<UUIDОпыта>. После создания сохраните фактический RAS UUIDКластера из результата; имя не заменяет UUID.
Читающая команда Каталог85 не равна доказательству отсутствия production. Изоляция VM и новый реестр обязательны до любого подключения. COM не предоставляет UUID в интерфейсе IClusterInfo: пример сопоставляет его с прочитанным UUID RAS по sole-кластеру, точным loopback/имени/порту.
Запись/применение/отмена регистрации выполняются только отдельной явно выбранной строкой Операция. Не добавляйте автоматические повторы, очистку при исключении или откат чужого состояния. В случае частичного выполнения сохраните UUID и сначала прочитайте фактическое состояние.
Пароли очищаются из реквизитов и локальной структуры, но это не гарантирует стирания строк из памяти. Не выводите ОписаниеОшибки, строки подключения, Password или аргументы операций. Код статически проверяется здесь, но COM/RAS/1С, сеть и процессы не запускались.
На той же новой VM вручную поднимите второй отдельный ragent8.5.1.1343 с отдельным новым каталогом реестров и другой парой agent/ras-портов. Ни один агент не должен обслуживать production. В его новом реестре0кластеров и нет администраторов; нулевой вход разрешен только на этом отдельно подготовленном учебном вторичном агенте.
Для вторичного сервера заранее выберите и зарезервируйте свободную собственную полосу TCP-портов, не пересекающую служебные порты обоих агентов/RAS/manager и фактические диапазоны главного сервера. Проверку свободных портов/межсетевого экрана выполняет человек; BSL никакие порты ОС не резервирует.
В Дополнительно введите JSON-объект с числовыми ПортВторогоАгента, ПортВторогоRAS, НижнийПорт, ВерхнийПорт и строковым UUIDСервера. Перед первым созданием UUIDСервера=""; остальные числа реальные, а не копируемые примерные. После создания впишите фактический UUID из ответа.
Свой вторичный сервер создается MainServer=Ложь и RegWorkingServer(...,Истина), чтобы автоматически запретить назначение любой функциональности. Основной сервер, его диапазоны и процессы не изменяются.
Сначала полностью подготовьте собственный вторичный UUID-сервер предыдущим уроком и впишите его фактический UUIDСервера в JSON. ИБ в кластере0. Единственное исходное требование автоматически добавленоRegWorkingServer(...,Истина).
Учебная задача: заранее запретить прямые тонкие клиентские соединения будущей собственной ИБ own-com85-base-<UUIDОпыта> на этом вторичном сервере; сама ИБ пока отсутствует. Это будущая адресная политика, а не вымышленный активный сеанс.
Команды: СоздатьТребование85, Каталог85, Применить85, УдалитьТребование85. Удаление собственной записи отдельно от ее применения; после проверки отмены примените изменение своей консолью вручную.
Функция Выполнить85(Операция, Данные, Подтверждение) Экспорт
Если СтрРазделить("СоздатьТребование85,Каталог85,Применить85,УдалитьТребование85", ",").Найти(Операция) = Неопределено Тогда
ВызватьИсключение "Неизвестная отдельная команда требования назначения";
КонецЕсли;
Связь = СоединитьсяСоСвоимАгентом85(Данные, Подтверждение);
Стенд = ПолучитьСвойКластер85(Связь, Данные);
Паспорт = ПрочитатьСвойJSON85(Данные.Дополнительно);
ПроверитьПаспортРабочего85(Паспорт, Данные);
Если ПустаяСтрока(Паспорт.UUIDСервера) Тогда
ВызватьИсключение "Нужен сохраненный фактический UUID вторичного own-сервера";
КонецЕсли;
Рабочий = НайтиСвойРабочийСервер85(Связь, Стенд, Данные, Паспорт);
Если Рабочий.COM = Неопределено Тогда
ВызватьИсключение "Сначала подготовьте собственный вторичный рабочий сервер полным уроком";
КонецЕсли;
Требования = Связь.Агент.GetAssignmentRules(Стенд.COM, Рабочий.COM);
Свое = Неопределено;
Для Каждого Кандидат Из Требования Цикл
Если Кандидат.ObjectType = "Connection" И Кандидат.InfoBaseName = "own-com85-base-" + Данные.UUIDОпыта
И Кандидат.ApplicationExt = "1CV8CDirect" И Кандидат.RuleType = 2 И Кандидат.Priority = 101 Тогда
Если Свое <> Неопределено Тогда
ВызватьИсключение "Собственное требование неоднозначно";
КонецЕсли;
Свое = Кандидат;
ИначеЕсли Кандидат.ObjectType <> "" Или Кандидат.InfoBaseName <> "" Или Кандидат.ApplicationExt <> ""
Или Кандидат.RuleType <> 2 Или Кандидат.Priority <> 0 Тогда
ВызватьИсключение "Разрешены только автоматически запрещающее требование и наше точное учебное";
КонецЕсли;
КонецЦикла;
Если Операция = "СоздатьТребование85" Тогда
Если Свое <> Неопределено Или Требования.Количество() <> 1 Тогда
ВызватьИсключение "До создания ожидается только одно автоматическое запрещающее требование";
КонецЕсли;
Новое = Связь.Агент.CreateAssignmentRule();
Новое.ObjectType = "Connection";
Новое.InfoBaseName = "own-com85-base-" + Данные.UUIDОпыта;
Новое.ApplicationExt = "1CV8CDirect";
Новое.RuleType = 2;
Новое.Priority = 101;
Связь.Агент.RegAssignmentRule(Стенд.COM, Рабочий.COM, Новое, Требования.Количество());
После = Связь.Агент.GetAssignmentRules(Стенд.COM, Рабочий.COM);
Если После.Количество() <> 2 Тогда
ВызватьИсключение "Добавление требования не подтверждено";
КонецЕсли;
Последнее = После.Получить(1);
Если Последнее.ObjectType <> Новое.ObjectType Или Последнее.InfoBaseName <> Новое.InfoBaseName
Или Последнее.ApplicationExt <> Новое.ApplicationExt Или Последнее.RuleType <> 2 Или Последнее.Priority <> 101 Тогда
ВызватьИсключение "Последнее требование не совпало с нашим точным собственным";
КонецЕсли;
Возврат "Своё требование зарегистрировано в позиции1, режимНеНазначать. Применить85 выбирается отдельно";
ИначеЕсли Операция = "Применить85" Тогда
Если Свое = Неопределено Тогда
ВызватьИсключение "Сначала зарегистрируйте только собственное требование";
КонецЕсли;
Связь.Агент.ApplyAssignmentRules(Стенд.COM, 0);
Возврат "Частичное применение выполнено без переназначения файловых сервисов; ИБ=0, работающий пользователь не перемещался";
ИначеЕсли Операция = "УдалитьТребование85" Тогда
Если Свое = Неопределено Тогда
Возврат "Собственное требование отсутствует; автоматическое запретительное не менялось";
КонецЕсли;
Связь.Агент.UnregAssignmentRule(Стенд.COM, Рабочий.COM, Свое);
Если Связь.Агент.GetAssignmentRules(Стенд.COM, Рабочий.COM).Количество() <> 1 Тогда
ВызватьИсключение "Снятие только собственного требования не подтверждено";
КонецЕсли;
Возврат "Удалено только собственное требование; отдельное частичное применение выполните своей консолью после проверки";
КонецЕсли;
Возврат СтрШаблон("Требований=%1; собственное=%2; ИБ=0", Требования.Количество(), Свое <> Неопределено);
КонецФункции
Функция СоединитьсяСоСвоимАгентом85(Данные, Подтверждение)
ПроверитьСвойПустойСтенд();
Если ТипЗнч(Подтверждение) <> Тип("Булево") Или Не Подтверждение Тогда
ВызватьИсключение "Подтвердите отдельную собственную VM без рабочих кластеров";
КонецЕсли;
Для Каждого Поле Из СтрРазделить("ПортАгента,ПортRAS,ПортКластера", ",") Цикл
Порт = Данные[Поле];
Если ТипЗнч(Порт) <> Тип("Число") Тогда
ВызватьИсключение "Порт своего процесса должен быть числом";
КонецЕсли;
Если Порт < 1 Или Порт > 65535 Или Порт <> Цел(Порт) Тогда
ВызватьИсключение "Недопустимый фактический порт";
КонецЕсли;
КонецЦикла;
Если Данные.ПортАгента = Данные.ПортRAS Или Данные.ПортАгента = Данные.ПортКластера
Или Данные.ПортRAS = Данные.ПортКластера Тогда
ВызватьИсключение "Порты агента, менеджера кластера и ras различаются";
КонецЕсли;
Для Каждого Поле Из СтрРазделить("ИмяАгента,ПарольАгента,ИмяАдминистратора,ПарольАдминистратора,UUIDОпыта,UUIDКластера,Дополнительно", ",") Цикл
Если ТипЗнч(Данные[Поле]) <> Тип("Строка") Тогда
ВызватьИсключение "Имена, пароли и UUID должны быть строками";
КонецЕсли;
КонецЦикла;
ПроверитьUUID85(Данные.UUIDОпыта);
СерверRAS = Новый АдминистрированиеСервера("127.0.0.1", Данные.ПортRAS);
СерверRAS.ВыполнитьАутентификацию(Данные.ПарольАгента, Данные.ИмяАгента);
Если СерверRAS.ПолучитьВерсию() <> "8.5.1.1343" Тогда
ВызватьИсключение "RAS обязан обслуживать ровно собственный агент8.5.1.1343";
КонецЕсли;
Соединитель = Новый COMОбъект("V85.COMConnector");
Агент = Соединитель.ConnectAgent("127.0.0.1:" + Формат(Данные.ПортАгента, "ЧГ=0"));
Агент.AuthenticateAgent(Данные.ИмяАгента, Данные.ПарольАгента);
Возврат Новый Структура("Агент,RAS,Соединитель", Агент, СерверRAS, Соединитель);
КонецФункции
Процедура ПроверитьUUID85(UUID)
Проверенный = Новый УникальныйИдентификатор(UUID);
Если UUID <> Строка(Проверенный) Или UUID = "00000000-0000-0000-0000-000000000000" Тогда
ВызватьИсключение "Введите канонический собственный ненулевой UUID";
КонецЕсли;
КонецПроцедуры
Функция ПолучитьСвойКластер85(Связь, Данные, РазрешенаСвояБаза = Ложь)
ПроверитьUUID85(Данные.UUIDКластера);
КластерыRAS = Связь.RAS.ПолучитьКластеры();
Если КластерыRAS.Количество() <> 1 Тогда
ВызватьИсключение "В агенте должен быть только один собственный кластер";
КонецЕсли;
КластерRAS = КластерыRAS[0];
ИмяКластера = "own-com85-cluster-" + Данные.UUIDОпыта;
Если Строка(КластерRAS.ИдентификаторКластера) <> Данные.UUIDКластера
Или КластерRAS.Имя <> ИмяКластера Или КластерRAS.Порт <> Данные.ПортКластера
Или КластерRAS.ИмяКомпьютера <> "127.0.0.1" Тогда
ВызватьИсключение "RAS UUID, имя, loopback или порт своего кластера не совпали";
КонецЕсли;
КластерRAS.ВыполнитьАутентификацию(Данные.ИмяАдминистратора, Данные.ПарольАдминистратора);
БазыRAS = КластерRAS.ПолучитьИнформационныеБазы();
Если Не РазрешенаСвояБаза И БазыRAS.Количество() <> 0 Тогда
ВызватьИсключение "Этот урок требует полностью пустой кластер";
КонецЕсли;
Если РазрешенаСвояБаза Тогда
Если БазыRAS.Количество() <> 1 Тогда
ВызватьИсключение "Разрешена только одна специально подготовленная собственная ИБ";
КонецЕсли;
Если БазыRAS[0].Имя <> "own-com85-base-" + Данные.UUIDОпыта
Или (БазыRAS[0].Описание <> "owned-com85-lifecycle:" + Данные.UUIDОпыта
И БазыRAS[0].Описание <> "owned-com85-lifecycle:" + Данные.UUIDОпыта + ":checked") Тогда
ВызватьИсключение "Чужая ИБ или неверный маркер собственного стенда";
КонецЕсли;
КонецЕсли;
КластерыCOM = Связь.Агент.GetClusters();
Если КластерыCOM.Количество() <> 1 Тогда
ВызватьИсключение "COM и RAS должны видеть один и тот же sole кластер";
КонецЕсли;
Кластер = КластерыCOM.Получить(0);
Если Кластер.ClusterName <> КластерRAS.Имя Или Кластер.HostName <> КластерRAS.ИмяКомпьютера
Или Кластер.MainPort <> КластерRAS.Порт Тогда
ВызватьИсключение "Нельзя сопоставить COM-описание с собственным RAS UUID";
КонецЕсли;
Связь.Агент.Authenticate(Кластер, Данные.ИмяАдминистратора, Данные.ПарольАдминистратора);
БазыCOM = Связь.Агент.GetInfoBases(Кластер);
Если БазыCOM.Количество() <> БазыRAS.Количество() Тогда
ВызватьИсключение "Состояние собственных ИБ изменилось между чтениями";
КонецЕсли;
Основных = 0;
Вторичных = 0;
Для Каждого Рабочий Из КластерRAS.ПолучитьРабочиеСерверы() Цикл
Если Рабочий.ИмяКомпьютера <> "127.0.0.1" Тогда
ВызватьИсключение "В своём UUID-кластере появился нелокальный рабочий сервер";
КонецЕсли;
Если Рабочий.ЦентральныйСервер И Рабочий.Порт = Данные.ПортАгента Тогда
Основных = Основных + 1;
ИначеЕсли Не Рабочий.ЦентральныйСервер И Рабочий.Имя = "own-com85-worker-" + Данные.UUIDОпыта
И Рабочий.Порт <> Данные.ПортАгента Тогда
Вторичных = Вторичных + 1;
Иначе
ВызватьИсключение "Разрешены только собственные основной и UUID-вторичный рабочие серверы";
КонецЕсли;
КонецЦикла;
Если Основных <> 1 Или Вторичных > 1 Тогда
ВызватьИсключение "Own-топология рабочего стенда изменилась";
КонецЕсли;
Возврат Новый Структура("COM,RAS,БазыCOM,БазыRAS", Кластер, КластерRAS, БазыCOM, БазыRAS);
КонецФункции
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедуры
Функция ПрочитатьСвойJSON85(Текст)
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Текст);
Попытка
Значение = ПрочитатьJSON(Чтение);
Исключение
Чтение.Закрыть();
ВызватьИсключение "Некорректный собственный JSON-паспорт";
КонецПопытки;
Чтение.Закрыть();
Если ТипЗнч(Значение) <> Тип("Структура") Тогда
ВызватьИсключение "Собственный JSON должен содержать объект";
КонецЕсли;
Возврат Значение;
КонецФункции
Процедура ПроверитьПоля85(Данные, Поля)
Для Каждого Поле Из СтрРазделить(Поля, ",") Цикл
Если Не Данные.Свойство(Поле) Тогда
ВызватьИсключение "Заполните фактическое собственное поле " + Поле;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция НайтиСвойРабочийСервер85(Связь, Стенд, Данные, Паспорт)
НайденныйRAS = Неопределено;
Для Каждого Кандидат Из Стенд.RAS.ПолучитьРабочиеСерверы() Цикл
Если Кандидат.Имя = "own-com85-worker-" + Данные.UUIDОпыта Тогда
Если НайденныйRAS <> Неопределено Или Кандидат.ИмяКомпьютера <> "127.0.0.1"
Или Кандидат.Порт <> Паспорт.ПортВторогоАгента Или Кандидат.ЦентральныйСервер Тогда
ВызватьИсключение "Нельзя воздействовать на чужой или центральный рабочий сервер";
КонецЕсли;
НайденныйRAS = Кандидат;
КонецЕсли;
КонецЦикла;
НайденныйCOM = Неопределено;
Для Каждого Кандидат Из Связь.Агент.GetWorkingServers(Стенд.COM) Цикл
Если Кандидат.Name = "own-com85-worker-" + Данные.UUIDОпыта Тогда
Если НайденныйCOM <> Неопределено Или Кандидат.HostName <> "127.0.0.1"
Или Кандидат.MainPort <> Паспорт.ПортВторогоАгента Или Кандидат.MainServer Тогда
ВызватьИсключение "COM-паспорт собственного вторичного сервера не совпал";
КонецЕсли;
НайденныйCOM = Кандидат;
КонецЕсли;
КонецЦикла;
Если (НайденныйRAS = Неопределено) <> (НайденныйCOM = Неопределено) Тогда
ВызватьИсключение "Состояние рабочего сервера различается между RAS и COM";
КонецЕсли;
Если НайденныйRAS <> Неопределено И Не ПустаяСтрока(Паспорт.UUIDСервера) Тогда
ПроверитьUUID85(Паспорт.UUIDСервера);
Если Строка(НайденныйRAS.ИдентификаторРабочегоСервера) <> Паспорт.UUIDСервера Тогда
ВызватьИсключение "Новый экземпляр сервера не совпадает с ранее сохраненным own-UUID";
КонецЕсли;
КонецЕсли;
Возврат Новый Структура("COM,RAS", НайденныйCOM, НайденныйRAS);
КонецФункции
Процедура ПроверитьПаспортРабочего85(Паспорт, Данные)
ПроверитьПоля85(Паспорт, "ПортВторогоАгента,ПортВторогоRAS,НижнийПорт,ВерхнийПорт,UUIDСервера");
Для Каждого ИмяПоля Из СтрРазделить("ПортВторогоАгента,ПортВторогоRAS,НижнийПорт,ВерхнийПорт", ",") Цикл
Порт = Паспорт[ИмяПоля];
Если ТипЗнч(Порт) <> Тип("Число") Или Порт < 1 Или Порт > 65535 Или Порт <> Цел(Порт) Тогда
ВызватьИсключение "Недопустимый фактический порт второго собственного агента или диапазона";
КонецЕсли;
КонецЦикла;
Если Паспорт.ПортВторогоАгента = Данные.ПортАгента Или Паспорт.ПортВторогоRAS = Данные.ПортRAS
Или Паспорт.ПортВторогоАгента = Паспорт.ПортВторогоRAS Или Паспорт.НижнийПорт > Паспорт.ВерхнийПорт
Или ТипЗнч(Паспорт.UUIDСервера) <> Тип("Строка") Тогда
ВызватьИсключение "Нужны отдельные реальные own-порты и корректный диапазон";
КонецЕсли;
ЗанятыеПорты = Новый Массив;
ЗанятыеПорты.Добавить(Данные.ПортАгента);
ЗанятыеПорты.Добавить(Данные.ПортRAS);
ЗанятыеПорты.Добавить(Данные.ПортКластера);
ЗанятыеПорты.Добавить(Паспорт.ПортВторогоАгента);
ЗанятыеПорты.Добавить(Паспорт.ПортВторогоRAS);
Уникальные = Новый Соответствие;
Для Каждого Порт Из ЗанятыеПорты Цикл
Если Уникальные.Получить(Порт) <> Неопределено Тогда
ВызватьИсключение "Порты обоих собственных агентов, RAS и менеджера должны различаться";
КонецЕсли;
Уникальные.Вставить(Порт, Истина);
Если Порт >= Паспорт.НижнийПорт И Порт <= Паспорт.ВерхнийПорт Тогда
ВызватьИсключение "Своя полоса динамических портов пересекает служебный порт";
КонецЕсли;
КонецЦикла;
КонецПроцедурыМодуль управляемой формы обработки: команда Выполнить
Обработка.УчебныйCOM85.Форма.Форма: полный модуль формы
Клиентский/серверный модуль управляемой формы отдельной файловой ИБ; процедуры уже содержат директивы. Поля созданы согласно подготовке.
&НаКлиенте
Процедура Выполнить(Команда)
Данные = Новый Структура;
Данные.Вставить("ПортАгента", ПортАгента);
Данные.Вставить("ПортRAS", ПортRAS);
Данные.Вставить("ПортКластера", ПортКластера);
Данные.Вставить("ИмяАгента", ИмяАгента);
Данные.Вставить("ПарольАгента", ПарольАгента);
Данные.Вставить("ИмяАдминистратора", ИмяАдминистратора);
Данные.Вставить("ПарольАдминистратора", ПарольАдминистратора);
Данные.Вставить("UUIDОпыта", UUIDОпыта);
Данные.Вставить("UUIDКластера", UUIDКластера);
Данные.Вставить("Дополнительно", Дополнительно);
ПарольАгента = "";
ПарольАдминистратора = "";
Дополнительно = "";
Попытка
Ответ = ВыполнитьНаСервере(Операция, Данные, ПодтвержденСвойСтенд);
Исключение
Данные.ПарольАгента = "";
Данные.ПарольАдминистратора = "";
Данные.Дополнительно = "";
Сообщить("Операция не подтверждена. Не повторяйте запись автоматически. Проверьте только свой изолированный стенд и ранее записанные UUID.");
Возврат;
КонецПопытки;
Данные.ПарольАгента = "";
Данные.ПарольАдминистратора = "";
Данные.Дополнительно = "";
Сообщить(Ответ);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ВыполнитьНаСервере(Операция, Данные, ПодтвержденСвойСтенд)
Возврат УчебныйCOM85.Выполнить85(Операция, Данные, ПодтвержденСвойСтенд);
КонецФункцииРазбор по шагам
СоединитьсяСоСвоимАгентом85 проверяет точную платформу, новую пустую конфигурацию и явное подтверждение VM; только затем создает свои два административных подключения.
RAS выполняет проверку точной версии обслуживаемого агента. COM и RAS получают разные порты; COM AuthenticateAgent принимает имя, затем пароль, тогда как RAS ВыполнитьАутентификацию принимает пароль, затем имя.
ПолучитьСвойКластер85 принимает только один кластер: собственный UUID, имя с UUIDОпыта, loopback127.0.0.1 и фактический порт. UUID берется из RAS, не выдумывается как свойство COM-кластера.
До операции повторно проверяется допустимый набор ИБ; по умолчанию0. Постоянная кластерная аутентификация отделена от агентской и не заменяется учетными данными временного создаваемого объекта.
Входной список допускает ровно исходное автоматическое0/2/пустые поля и наше точное адресное требование. Любые иные требования запрещают изменение.
НовоеConnection-требование имеет InfoBaseName собственного будущего UUID-имени, ApplicationExt=1CV8CDirect, RuleType=2(не назначать), Priority=101. Эти значения определяют конкретную подготовительную политику, не подставной объект.
RegAssignmentRule принимает позицию с0: при одном исходном требованииappend-позиция1 равна фактическомуКоличество. Повторное чтение проверяет все5полей последнего элемента.
ApplyAssignmentRules(...,0) — частичное применение: файловые сервисы журналов/полнотекстового поиска/настроек не переназначаются. В пустом стенде пользовательский сеанс не перемещался.
UnregAssignmentRule получает оригинальный собственный объект изGetAssignmentRules. Чужой/автоматический не удаляется; повторный список должен содержать только исходную запись.
Как проверить результат
До создания1исходное требование, после2; собственное в позиции1 сточными полями.
При появлении другого требования запись/применение/удаление отклоняются.
После отдельной отмены регистрации остается только исходное автоматическое запрещающее; физические данные не переносились.
Ожидаемый результат
Освоены реальные список/порядок/адресный запрет/регистрация/частичное применение без фиктивной демонстрации пользовательского перераспределения.
На что обратить внимание
Это будущий ручной учебный запуск на собственной VM, а не уже выполненная операция. runtimeVerifiedScenarios остается0; статические проверки не гарантируют COM-регистрацию, лицензии или успешный ответ агента.
Проверки выполняются перед вызовами, но не образуют распределенную транзакцию и не исключают гонку. Только один оператор может менять стенд; при любом несоответствии остановитесь.
Не используйте production, копию рабочего реестра или имена чужих пользователей. Нельзя расширять разрешения рабочей базы ради COM-подключения.
0-позиция иPriority — разные величины. Порядок массива не равен относительному приоритету объекта между серверами.
Полное применение1 может переназначать файловые сервисы: этот собственный урок использует0и ничего не переносит.
COM-требование не предоставляетUUID; выбирается уникальный состав собственных5полей сUUIDвимени будущейИБ, не неизвестный входной объект.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.
Сопоставить свой рабочий процесс по UUID/PID/порту/времени и явно выключить только пустой экземпляр
GetServerWorkingProcesses дает оригинальные COM-описания своего основного сервера. TurnOffWorkingProcess получает только повторно сверенный собственный процесс без ИБ/сеансов/соединений.
Где и как запускать
Полный серверный общий модуль УчебныйCOM85 и полный модуль управляемой формы в отдельной файловой учебной ИБ. Свой Windows-агент/RAS, точная платформа8.5.1.1343; перечисленные записи являются только авторским учебным кодом, фактических запусков0.
Подготовка
Работайте только в новой отдельной Windows-VM без рабочих процессов/кластеров. Установленная платформа и заранее зарегистрированный V85.COMConnector должны быть8.5.1.1343 соответствующей разрядности. Регистрацию COM и запуск служб этот BSL не выполняет.
Создайте отдельную файловую ИБ с именем конфигурации УчебныйЖизненныйЦиклCOM85: без данных, каталогов, документов, регистров, подписок, фоновых заданий и расширений. В ней создайте общий модуль УчебныйCOM85: Сервер=Истина, ВызовСервера=Истина, Глобальный=Ложь, Клиент/ВнешнееСоединение=Ложь. Вставьте полностью код одного урока, не смешивайте одинаковые функции разных уроков.
Создайте обработку и управляемую форму с командой Выполнить и полным модулем формы из дополнительного блока. Строковые реквизиты: Операция, ИмяАгента, ПарольАгента, ИмяАдминистратора, ПарольАдминистратора, UUIDОпыта, UUIDКластера, Дополнительно; числовые ПортАгента, ПортRAS, ПортКластера; булевый ПодтвержденСвойСтенд. Поля всех паролей и Дополнительно переведите в режим пароля, значения не сохраняйте в настройках.
В своей VM вручную поднимите один отдельный ragent и один ras с отдельным новым каталогом реестров. RAS должен обслуживать именно этот агент, а не другой локальный сервис. Из реально выбранных администратором свободных портов впишите три разные величины: agent-port для ConnectAgent, ras-port для АдминистрированиеСервера, manager-port для своего кластера. Не подставляйте1545 в ConnectAgent.
До первого создания кластера вручную удалите только автоматически созданный пустой кластер своей новой VM, если он появился. Консоль должна показывать0кластеров; никакие чужие кластеры не допускаются. Первый урок также проверяет нулевой список обоими интерфейсами до RegCluster.
Заведите постоянного своего администратора агента и после создания кластера постоянного своего администратора кластера через консоль. Их реальные новые учебные пароли передавайте форме; учебные временные администраторы в уроке никогда не заменяют постоянных.
Один раз самостоятельно получите UUIDОпыта в своей файловой ИБ выражением Строка(Новый УникальныйИдентификатор), сохраните текст в собственном журнале опыта. Имя кластера: own-com85-cluster-<UUIDОпыта>. После создания сохраните фактический RAS UUIDКластера из результата; имя не заменяет UUID.
Читающая команда Каталог85 не равна доказательству отсутствия production. Изоляция VM и новый реестр обязательны до любого подключения. COM не предоставляет UUID в интерфейсе IClusterInfo: пример сопоставляет его с прочитанным UUID RAS по sole-кластеру, точным loopback/имени/порту.
Запись/применение/отмена регистрации выполняются только отдельной явно выбранной строкой Операция. Не добавляйте автоматические повторы, очистку при исключении или откат чужого состояния. В случае частичного выполнения сохраните UUID и сначала прочитайте фактическое состояние.
Пароли очищаются из реквизитов и локальной структуры, но это не гарантирует стирания строк из памяти. Не выводите ОписаниеОшибки, строки подключения, Password или аргументы операций. Код статически проверяется здесь, но COM/RAS/1С, сеть и процессы не запускались.
Сначала используйте свой единственный UUID-кластер после bootstrap;0ИБ,0сеансов,0соединений. Вторичные рабочие серверы для этого урока не нужны. Через консоль своей VM можно вручную включить один учебный rphost; если список пуст, это допустимый реальный результат, не создавайте фиктивный процесс.
Для первого Каталог85 Дополнительно="{}". Полученные фактические UUID/PID/порт/время собственного процесса вручную перенесите в JSON поля UUIDПроцесса, PID, Порт, ВремяЗапуска. UUID/PID/время — строки, Порт — число. Время ровноXMLСтрока из ответа, не часы компьютера.
Команда ВыключитьСвойПроцесс85 отдельно и добровольно. После нее пользовательские приложения в целевом процессе не должны существовать. Не завершается процессWindows поPID.
Функция Выполнить85(Операция, Данные, Подтверждение) Экспорт
Если Операция <> "Каталог85" И Операция <> "ВыключитьСвойПроцесс85" Тогда
ВызватьИсключение "Выберите отдельное чтение или явное выключение своего пустого процесса";
КонецЕсли;
Связь = СоединитьсяСоСвоимАгентом85(Данные, Подтверждение);
Стенд = ПолучитьСвойКластер85(Связь, Данные);
Если Связь.Агент.GetSessions(Стенд.COM).Количество() <> 0 Или Связь.Агент.GetConnections(Стенд.COM).Количество() <> 0 Тогда
ВызватьИсключение "Нельзя выключать процесс при любых сеансах или соединениях";
КонецЕсли;
Рабочий = Неопределено;
Для Каждого Кандидат Из Связь.Агент.GetWorkingServers(Стенд.COM) Цикл
Если Кандидат.HostName = "127.0.0.1" И Кандидат.MainPort = Данные.ПортАгента И Кандидат.MainServer Тогда
Если Рабочий <> Неопределено Тогда
ВызватьИсключение "Свой основной сервер не выбран однозначно";
КонецЕсли;
Рабочий = Кандидат;
КонецЕсли;
КонецЦикла;
Если Рабочий = Неопределено Тогда
ВызватьИсключение "Нужен фактический основной loopback-сервер своего UUID-кластера";
КонецЕсли;
Процессы = Связь.Агент.GetServerWorkingProcesses(Стенд.COM, Рабочий);
Паспорт = ПрочитатьСвойJSON85(Данные.Дополнительно);
Если Операция = "Каталог85" Тогда
Строки = Новый Массив;
Для Каждого ПроцессRAS Из Стенд.RAS.ПолучитьРабочиеПроцессы() Цикл
Для Каждого ПроцессCOM Из Процессы Цикл
Если ПроцессCOM.PID = ПроцессRAS.ИдентификаторПроцесса И ПроцессCOM.MainPort = ПроцессRAS.Порт
И ПроцессCOM.HostName = "127.0.0.1" И ПроцессRAS.ИмяКомпьютера = "127.0.0.1"
И ПроцессCOM.StartedAt = ПроцессRAS.ВремяЗапуска Тогда
Строки.Добавить(СтрШаблон("UUID=%1; PID=%2; порт=%3; время=%4; connections=%5; enabled=%6",
Строка(ПроцессRAS.ИдентификаторРабочегоПроцесса), ПроцессCOM.PID, ПроцессCOM.MainPort,
XMLСтрока(ПроцессCOM.StartedAt), ПроцессCOM.Connections, ПроцессCOM.IsEnable));
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат "Фактически сопоставленные собственные процессы=" + Формат(Строки.Количество(), "ЧГ=0")
+ Символы.ПС + СтрСоединить(Строки, Символы.ПС);
КонецЕсли;
ПроверитьПоля85(Паспорт, "UUIDПроцесса,PID,Порт,ВремяЗапуска");
ПроверитьUUID85(Паспорт.UUIDПроцесса);
НайденныйRAS = Неопределено;
Для Каждого Кандидат Из Стенд.RAS.ПолучитьРабочиеПроцессы() Цикл
Если Строка(Кандидат.ИдентификаторРабочегоПроцесса) = Паспорт.UUIDПроцесса Тогда
Если НайденныйRAS <> Неопределено Или Кандидат.ИдентификаторПроцесса <> Паспорт.PID
Или Кандидат.Порт <> Паспорт.Порт Или XMLСтрока(Кандидат.ВремяЗапуска) <> Паспорт.ВремяЗапуска
Или Кандидат.ИмяКомпьютера <> "127.0.0.1" Тогда
ВызватьИсключение "UUID/PID/порт/время собственного процесса не совпали";
КонецЕсли;
НайденныйRAS = Кандидат;
КонецЕсли;
КонецЦикла;
Выбранный = Неопределено;
Для Каждого Кандидат Из Процессы Цикл
Если Кандидат.PID = Паспорт.PID И Кандидат.MainPort = Паспорт.Порт
И XMLСтрока(Кандидат.StartedAt) = Паспорт.ВремяЗапуска Тогда
Если Выбранный <> Неопределено Или Кандидат.HostName <> "127.0.0.1" Или Кандидат.Connections <> 0 Тогда
ВызватьИсключение "COM-процесс неоднозначен или обслуживает соединения";
КонецЕсли;
Выбранный = Кандидат;
КонецЕсли;
КонецЦикла;
Если НайденныйRAS = Неопределено Или Выбранный = Неопределено Тогда
ВызватьИсключение "Обновите каталог: старый own-процесс исчез или был заменен";
КонецЕсли;
ПолучитьСвойКластер85(Связь, Данные);
Если Связь.Агент.GetSessions(Стенд.COM).Количество() <> 0 Или Связь.Агент.GetConnections(Стенд.COM).Количество() <> 0 Тогда
ВызватьИсключение "Перед выключением появились сеансы или соединения";
КонецЕсли;
Связь.Агент.TurnOffWorkingProcess(Стенд.COM, Выбранный);
Для Каждого После Из Связь.Агент.GetServerWorkingProcesses(Стенд.COM, Рабочий) Цикл
Если После.PID = Паспорт.PID И После.MainPort = Паспорт.Порт
И XMLСтрока(После.StartedAt) = Паспорт.ВремяЗапуска И После.IsEnable Тогда
ВызватьИсключение "Выключение собственного процесса не подтверждено";
КонецЕсли;
КонецЦикла;
Возврат "Собственный процесс отсутствует либо IsEnable=Ложь; немедленное завершение ОС и PID-запрещение не обещаются";
КонецФункции
Функция СоединитьсяСоСвоимАгентом85(Данные, Подтверждение)
ПроверитьСвойПустойСтенд();
Если ТипЗнч(Подтверждение) <> Тип("Булево") Или Не Подтверждение Тогда
ВызватьИсключение "Подтвердите отдельную собственную VM без рабочих кластеров";
КонецЕсли;
Для Каждого Поле Из СтрРазделить("ПортАгента,ПортRAS,ПортКластера", ",") Цикл
Порт = Данные[Поле];
Если ТипЗнч(Порт) <> Тип("Число") Тогда
ВызватьИсключение "Порт своего процесса должен быть числом";
КонецЕсли;
Если Порт < 1 Или Порт > 65535 Или Порт <> Цел(Порт) Тогда
ВызватьИсключение "Недопустимый фактический порт";
КонецЕсли;
КонецЦикла;
Если Данные.ПортАгента = Данные.ПортRAS Или Данные.ПортАгента = Данные.ПортКластера
Или Данные.ПортRAS = Данные.ПортКластера Тогда
ВызватьИсключение "Порты агента, менеджера кластера и ras различаются";
КонецЕсли;
Для Каждого Поле Из СтрРазделить("ИмяАгента,ПарольАгента,ИмяАдминистратора,ПарольАдминистратора,UUIDОпыта,UUIDКластера,Дополнительно", ",") Цикл
Если ТипЗнч(Данные[Поле]) <> Тип("Строка") Тогда
ВызватьИсключение "Имена, пароли и UUID должны быть строками";
КонецЕсли;
КонецЦикла;
ПроверитьUUID85(Данные.UUIDОпыта);
СерверRAS = Новый АдминистрированиеСервера("127.0.0.1", Данные.ПортRAS);
СерверRAS.ВыполнитьАутентификацию(Данные.ПарольАгента, Данные.ИмяАгента);
Если СерверRAS.ПолучитьВерсию() <> "8.5.1.1343" Тогда
ВызватьИсключение "RAS обязан обслуживать ровно собственный агент8.5.1.1343";
КонецЕсли;
Соединитель = Новый COMОбъект("V85.COMConnector");
Агент = Соединитель.ConnectAgent("127.0.0.1:" + Формат(Данные.ПортАгента, "ЧГ=0"));
Агент.AuthenticateAgent(Данные.ИмяАгента, Данные.ПарольАгента);
Возврат Новый Структура("Агент,RAS,Соединитель", Агент, СерверRAS, Соединитель);
КонецФункции
Процедура ПроверитьUUID85(UUID)
Проверенный = Новый УникальныйИдентификатор(UUID);
Если UUID <> Строка(Проверенный) Или UUID = "00000000-0000-0000-0000-000000000000" Тогда
ВызватьИсключение "Введите канонический собственный ненулевой UUID";
КонецЕсли;
КонецПроцедуры
Функция ПолучитьСвойКластер85(Связь, Данные, РазрешенаСвояБаза = Ложь)
ПроверитьUUID85(Данные.UUIDКластера);
КластерыRAS = Связь.RAS.ПолучитьКластеры();
Если КластерыRAS.Количество() <> 1 Тогда
ВызватьИсключение "В агенте должен быть только один собственный кластер";
КонецЕсли;
КластерRAS = КластерыRAS[0];
ИмяКластера = "own-com85-cluster-" + Данные.UUIDОпыта;
Если Строка(КластерRAS.ИдентификаторКластера) <> Данные.UUIDКластера
Или КластерRAS.Имя <> ИмяКластера Или КластерRAS.Порт <> Данные.ПортКластера
Или КластерRAS.ИмяКомпьютера <> "127.0.0.1" Тогда
ВызватьИсключение "RAS UUID, имя, loopback или порт своего кластера не совпали";
КонецЕсли;
КластерRAS.ВыполнитьАутентификацию(Данные.ИмяАдминистратора, Данные.ПарольАдминистратора);
БазыRAS = КластерRAS.ПолучитьИнформационныеБазы();
Если Не РазрешенаСвояБаза И БазыRAS.Количество() <> 0 Тогда
ВызватьИсключение "Этот урок требует полностью пустой кластер";
КонецЕсли;
Если РазрешенаСвояБаза Тогда
Если БазыRAS.Количество() <> 1 Тогда
ВызватьИсключение "Разрешена только одна специально подготовленная собственная ИБ";
КонецЕсли;
Если БазыRAS[0].Имя <> "own-com85-base-" + Данные.UUIDОпыта
Или (БазыRAS[0].Описание <> "owned-com85-lifecycle:" + Данные.UUIDОпыта
И БазыRAS[0].Описание <> "owned-com85-lifecycle:" + Данные.UUIDОпыта + ":checked") Тогда
ВызватьИсключение "Чужая ИБ или неверный маркер собственного стенда";
КонецЕсли;
КонецЕсли;
КластерыCOM = Связь.Агент.GetClusters();
Если КластерыCOM.Количество() <> 1 Тогда
ВызватьИсключение "COM и RAS должны видеть один и тот же sole кластер";
КонецЕсли;
Кластер = КластерыCOM.Получить(0);
Если Кластер.ClusterName <> КластерRAS.Имя Или Кластер.HostName <> КластерRAS.ИмяКомпьютера
Или Кластер.MainPort <> КластерRAS.Порт Тогда
ВызватьИсключение "Нельзя сопоставить COM-описание с собственным RAS UUID";
КонецЕсли;
Связь.Агент.Authenticate(Кластер, Данные.ИмяАдминистратора, Данные.ПарольАдминистратора);
БазыCOM = Связь.Агент.GetInfoBases(Кластер);
Если БазыCOM.Количество() <> БазыRAS.Количество() Тогда
ВызватьИсключение "Состояние собственных ИБ изменилось между чтениями";
КонецЕсли;
Основных = 0;
Вторичных = 0;
Для Каждого Рабочий Из КластерRAS.ПолучитьРабочиеСерверы() Цикл
Если Рабочий.ИмяКомпьютера <> "127.0.0.1" Тогда
ВызватьИсключение "В своём UUID-кластере появился нелокальный рабочий сервер";
КонецЕсли;
Если Рабочий.ЦентральныйСервер И Рабочий.Порт = Данные.ПортАгента Тогда
Основных = Основных + 1;
ИначеЕсли Не Рабочий.ЦентральныйСервер И Рабочий.Имя = "own-com85-worker-" + Данные.UUIDОпыта
И Рабочий.Порт <> Данные.ПортАгента Тогда
Вторичных = Вторичных + 1;
Иначе
ВызватьИсключение "Разрешены только собственные основной и UUID-вторичный рабочие серверы";
КонецЕсли;
КонецЦикла;
Если Основных <> 1 Или Вторичных > 1 Тогда
ВызватьИсключение "Own-топология рабочего стенда изменилась";
КонецЕсли;
Возврат Новый Структура("COM,RAS,БазыCOM,БазыRAS", Кластер, КластерRAS, БазыCOM, БазыRAS);
КонецФункции
Процедура ПроверитьСвойПустойСтенд()
Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
КонецЕсли;
Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
КонецЕсли;
Источники = Новый Массив;
Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
Для Каждого Источник Из Источники Цикл
Расширения = РасширенияКонфигурации.Получить(, Источник);
Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
ВызватьИсключение "Native список расширений должен иметь тип Массив";
КонецЕсли;
Если Расширения.Количество() <> 0 Тогда
ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
КонецЕсли;
КонецЦикла;
Если ТранзакцияАктивна() Тогда
ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
КонецЕсли;
КонецПроцедуры
Функция ПрочитатьСвойJSON85(Текст)
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Текст);
Попытка
Значение = ПрочитатьJSON(Чтение);
Исключение
Чтение.Закрыть();
ВызватьИсключение "Некорректный собственный JSON-паспорт";
КонецПопытки;
Чтение.Закрыть();
Если ТипЗнч(Значение) <> Тип("Структура") Тогда
ВызватьИсключение "Собственный JSON должен содержать объект";
КонецЕсли;
Возврат Значение;
КонецФункции
Процедура ПроверитьПоля85(Данные, Поля)
Для Каждого Поле Из СтрРазделить(Поля, ",") Цикл
Если Не Данные.Свойство(Поле) Тогда
ВызватьИсключение "Заполните фактическое собственное поле " + Поле;
КонецЕсли;
КонецЦикла;
КонецПроцедурыМодуль управляемой формы обработки: команда Выполнить
Обработка.УчебныйCOM85.Форма.Форма: полный модуль формы
Клиентский/серверный модуль управляемой формы отдельной файловой ИБ; процедуры уже содержат директивы. Поля созданы согласно подготовке.
&НаКлиенте
Процедура Выполнить(Команда)
Данные = Новый Структура;
Данные.Вставить("ПортАгента", ПортАгента);
Данные.Вставить("ПортRAS", ПортRAS);
Данные.Вставить("ПортКластера", ПортКластера);
Данные.Вставить("ИмяАгента", ИмяАгента);
Данные.Вставить("ПарольАгента", ПарольАгента);
Данные.Вставить("ИмяАдминистратора", ИмяАдминистратора);
Данные.Вставить("ПарольАдминистратора", ПарольАдминистратора);
Данные.Вставить("UUIDОпыта", UUIDОпыта);
Данные.Вставить("UUIDКластера", UUIDКластера);
Данные.Вставить("Дополнительно", Дополнительно);
ПарольАгента = "";
ПарольАдминистратора = "";
Дополнительно = "";
Попытка
Ответ = ВыполнитьНаСервере(Операция, Данные, ПодтвержденСвойСтенд);
Исключение
Данные.ПарольАгента = "";
Данные.ПарольАдминистратора = "";
Данные.Дополнительно = "";
Сообщить("Операция не подтверждена. Не повторяйте запись автоматически. Проверьте только свой изолированный стенд и ранее записанные UUID.");
Возврат;
КонецПопытки;
Данные.ПарольАгента = "";
Данные.ПарольАдминистратора = "";
Данные.Дополнительно = "";
Сообщить(Ответ);
КонецПроцедуры
&НаСервереБезКонтекста
Функция ВыполнитьНаСервере(Операция, Данные, ПодтвержденСвойСтенд)
Возврат УчебныйCOM85.Выполнить85(Операция, Данные, ПодтвержденСвойСтенд);
КонецФункцииРазбор по шагам
СоединитьсяСоСвоимАгентом85 проверяет точную платформу, новую пустую конфигурацию и явное подтверждение VM; только затем создает свои два административных подключения.
RAS выполняет проверку точной версии обслуживаемого агента. COM и RAS получают разные порты; COM AuthenticateAgent принимает имя, затем пароль, тогда как RAS ВыполнитьАутентификацию принимает пароль, затем имя.
ПолучитьСвойКластер85 принимает только один кластер: собственный UUID, имя с UUIDОпыта, loopback127.0.0.1 и фактический порт. UUID берется из RAS, не выдумывается как свойство COM-кластера.
До операции повторно проверяется допустимый набор ИБ; по умолчанию0. Постоянная кластерная аутентификация отделена от агентской и не заменяется учетными данными временного создаваемого объекта.
Основной собственный рабочий сервер выбран поloopback, фактическому агент-port и MainServer. Процессы получены именно для него, а не случайным общекластерным списком.
Каждый COM-процесс сопоставлен с RAS поPID, динамическому порту, времени запуска иloopback; только после этого показывается фактический UUIDРабочегоПроцесса.
Явная выключающая команда заново проверяет UUIDRAS и фактический оригинальный COM-объект. PID сам по себе не защищает от повторного использования; сохраненноеStartedAt иUUID обязательны.
Перед вызовом повторно подтвержден собственный UUID-кластер с0ИБ,0сеансов,0соединений и Connections=0 у выбранного процесса.
TurnOffWorkingProcess получает кластер и оригинальный процесс. Повторное чтение принимает отсутствие того же экземпляра или IsEnable=Ложь; немедленное завершениеWindows/исчезновениеPID не обещается.
Как проверить результат
Каталог с0процессов честно сообщает0, выключение при отсутствующем UUID отклоняется.
Измените любой UUID/PID/порт/время — отказ доTurnOffWorkingProcess.
После собственной явной операции тот же экземпляр отсутствует либоIsEnable=Ложь; другие процессы не выключались.
Ожидаемый результат
Ученик отличает UUIDRAS отPIDWindows, динамический порт отagent-port и выключение процесса кластера от принудительного завершенияОС.
На что обратить внимание
Это будущий ручной учебный запуск на собственной VM, а не уже выполненная операция. runtimeVerifiedScenarios остается0; статические проверки не гарантируют COM-регистрацию, лицензии или успешный ответ агента.
Проверки выполняются перед вызовами, но не образуют распределенную транзакцию и не исключают гонку. Только один оператор может менять стенд; при любом несоответствии остановитесь.
Не используйте production, копию рабочего реестра или имена чужих пользователей. Нельзя расширять разрешения рабочей базы ради COM-подключения.
Не используйтеKillProcess/завершениеОС и не выбирайте процесс сConnections>0.
GetServerWorkingProcesses возврат описывает РабочийПроцесс, хотя nativereturn-текст ошибочно называет каждое описание соединением; код следует указанному интерфейсу.
Снимки неатомарны. Повторно запущенный процесс имеет другой UUID/StartedAt; старые значения не применяются.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.