ХранилищеНастроекМенеджер.<Имя хранилища>.ПолучитьФорму

Методы · GetForm

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

Синтаксис

ПолучитьФорму(<Форма>, <Владелец>, <КлючУникальности>)
Полное описание, параметры и ограничения

ХранилищеНастроекМенеджер.<Имя хранилища>.ПолучитьФорму (SettingsStorageManager.<Storage name>.GetForm)

ХранилищеНастроекМенеджер.<Имя хранилища> (SettingsStorageManager.<Storage name>)

ПолучитьФорму (GetForm)

Доступен, начиная с версии 8.2.

Синтаксис:
ПолучитьФорму(<Форма>, <Владелец>, <КлючУникальности>)
Параметры:

<Форма> (необязательный)
Тип: Строка, ОбъектМетаданных: Форма.
Имя формы, как оно задано в конфигураторе, или объект описания метаданного требуемой формы. Если параметр не указан, то используется основная форма, заданная в конфигураторе.

<Владелец> (необязательный)
Тип: Форма; Элемент управления.
Объект, который будет являться владельцем открываемой формы.

<КлючУникальности> (необязательный)
Тип: Произвольный.
В данном параметре может быть задан некоторый ключ, значение которого будет использоваться для поиска уже открытых форм.
При поиске учитываются значения свойств открытых форм соответствующим значениям параметров метода. Если найдена открытая форма (по совпадению всех параметров), то она будет возвращена вместо новой формы.
Если из некой формы (один и тот же владелец) требуется открывать новые экземпляры другой формы, то при каждом вызове метода значение данного параметра должно быть уникально (в рамках соответствующих значений свойств открытых форм).
Значение параметра присваивается свойству открываемой формы КлючУникальности.
Следует учитывать, что при получении формы из "объекта" система получает форму для конкретного экземпляра объекта с учетом совокупности переданных параметров, в то время как для "ссылки" всегда существует только один объект в базе данных и форма получается одна (для одинаковой совокупности параметров).
Возвращаемое значение:
Тип: Форма, Неопределено.
Неопределено - если в обработчике ПриСозданииНаСервере установлен признак отказа от создания формы.
Описание:

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

Доступность:

Толстый клиент.

Использование в версии:

Доступен, начиная с версии 8.2.

Методическая информация

Практические примеры

Построить свое хранилище пресетов: три обычные формы и сохранение 3×250=750

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

Где и как запускать

Полный непривилегированный общий модуль, полный менеджер своего metadata хранилища,3ordinary forms иordinary launcher; отдельная собственная файловаяИБ8.5.1.1343, авторство/statictests безruntime.

Подготовка

  1. Только новая отдельная файловая ИБ 8.5.1.1343 с пустой конфигурацией УчебныеСвоиПресеты85. Режим совместимости НеИспользовать; основной режим запуска ОбычноеПриложение. Вход только толстым клиентом в обычном приложении, не управляемом. Рабочие КА2/УНФ/УТ/БП и стандартные хранилища здесь не используются.

  2. Создайте собственного единственного пользователя guide-own-presets с новой учебной ролью и полными правами только этого стенда: свой регистр, хранилище, его формы/общий модуль/стартовая форма. Не добавляйте роль/пользователя в рабочую базу. Физическую изоляцию, одного пользователя/сеанса обеспечивает человек, код не доказывает отсутствие конкуренции.

  3. Нет каталогов/документов/планов/бизнес-процессов, разделителей/общих реквизитов, расширений базы/сеанса, подписок, регламентных заданий, внешних сервисов. История данных и обмен не используются.

  4. Регистры сведений → УчебныеДанныеПресетов85: Независимый, Непериодический, история НеИспользовать. Измерения КлючОбъекта85: Строка 36, КлючНастроек85: Строка 32, Пользователь85: Строка 80, индексировать. Ресурсы Данные85: только ХранилищеЗначения; Подпись85: Строка 128. Реквизитов нет, модуль набора записей пустой.

  5. Общие → Хранилища настроек → УчебныеПресеты85. В его модуль менеджера вставьте целиком вспомогательный блок HANDLERS. Предопределенные процедуры совпадают с именами четырех native событий; самостоятельно вызывать обработчики нельзя. Это собственная реализация хранения, не копия BSP и не доступ к стандартному хранилищу.

  6. Общие модули → УчебныеПресетыМаршрут85: Сервер=Да, Клиент(обычное приложение)=Да; Клиент(управляемое приложение), Глобальный, Внешнее соединение, Вызов сервера и Привилегированный=Нет; повторное использование возвращаемых значений НеИспользовать. Вставьте целиком основной код. Три метода получения обычных форм внутри условия ТолстыйКлиентОбычноеПриложение и не компилируются как серверные вызовы.

  7. В УчебныеПресеты85 → Формы создайте ровно три ОБЫЧНЫЕ формы: Пульт, Сохранение, Загрузка. ОсновнаяФормаСохранения=Сохранение, ОсновнаяФормаЗагрузки=Загрузка. Пульт получается по явному имени через ПолучитьФорму; для него не выдумывайте отсутствующее свойство ОсновнаяФорма у metadata хранилища.

  8. Во всех трех формах создайте реквизиты UUID85: Строка36, Пользователь85: Строка80, Результат85: Строка2048. UUID/пользователь только для чтения. В Пульт добавьте Ошибка85: Булево(Ложь), ПодписьИзменена85: Булево(Ложь), Подтверждение85: Строка100; в Сохранение добавьте Подтверждение85: Строка100; в Загрузка добавьте ОжидаемаяПодпись85: Строка128 только для чтения.

  9. В модуль формы Пульт вставьте целиком PANEL; добавьте обычные кнопки ОткрытьСохранение85, ОткрытьЗагрузку85, СменитьПодпись85 и назначьте одноименные действия с одним аргументомКнопка. Выведите подтверждение/результат. События открытия/закрытия пустые, автоматического вызова Сохранить нет.

  10. В модуль Сохранение вставьте SAVE_FORM, кнопки Сохранить85 и Отмена85 с одноименными действиями. В модуль Загрузка вставьте LOAD_FORM, кнопки Прочитать85 и Отмена85. Не назначайте никакие обработчики ПриОткрытии/ПриЗакрытии, стандартные действия кнопкам не задавайте. Закрытие крестиком/Отмена не вызывает сохранение учебного пресета; возможное сохранение платформой положения окон/интерфейса здесь не исследуется и не объявляется отсутствующим.

  11. Общие формы → УчебныйСтартПресета85: одна обычная общая форма с кнопкой ОткрытьПульт85; модуль полностью LAUNCHER. Откройте ее через ВсеФункции/ФункцииДляТехническогоСпециалиста и нажмите кнопку. Кнопка получает реальный глобальный менеджер, считает его собственные элементы, создает UUID, проверяет0строк и получает собственный Пульт.

  12. Обновите конфигурацию базы данных. Изначально собственный регистр пуст. Не вводите UUID самостоятельно и не меняйте его между этапами: все три формы получают один настоящий UUID пульта и текущего пользователя, дочерние формы имеют реального пульта-владельца.

  13. Проверьте отмену: Пульт → ОткрытьСохранение → Отмена. Запись еще не выполнялась; затем снова откройте Сохранение. Введите СОХРАНИТЬ:вашUUID в Подтверждение85 и нажмите Сохранить85 ровно один раз. Пакет в коде фиксирован: BOOK,3,250,750. Подтверждение очищается до вызова, fresh whitelist и существование ключа проверяются внутри собственного native обработчика.

  14. Закройте форму Сохранение. Пульт → ОткрытьЗагрузку → Прочитать85: увидите BOOK/3/250/750 и Книга3×250=750. Отмена/закрытие Загрузка тоже не сохраняют данные. Независимые Load/GetDescription/raw-readback уже проверяют один и тот же собственный ключ.

  15. Закройте Загрузка. В пульте введите ПОДПИСЬ:вашUUID, нажмите СменитьПодпись85 ровно один раз. Свежие исходные ключ/подпись/пакет должны совпасть. Меняется только Подпись85, данные ХранилищеЗначения не переназначаются. Снова откройте Загрузка и Прочитать85: подпись Проверено:750, пакет по-прежнему3×250=750.

  16. Load отсутствующего ключа возвращает Неопределено именно потому, что так написан наш ОбработкаЗагрузки. Не выдавайте этот отрицательный контракт за правило всех пользовательских хранилищ. GetDescription отсутствующего собственного ключа в нашей реализации вызывает исключение; УстановитьОписание не генерирует новый ключ, UUID/book-cart/currentuser всегда заданы явно.

  17. Предопределенные обработчики пользовательского хранилища исполняются с автоматическим отключением безопасного режима по native справке. Мы этот режим не переключаем; поэтому допустим только свой новый изолированный стенд, строго заданные ключи/данные и полный код четырех обработчиков. Не применяйте их к чужому хранилищу.

  18. Raw-данные и payload читаются из регистра заново. Общий модуль не использует повторно используемые значения; GetDescription/Load не объявляются универсальным обходом любого кэширования платформы. Снимки не являются атомарной защитой от второго сеанса, изоляция обязательна.

  19. Любое исключение ставит Ошибка85 в реальном пульте; следующие команды/дочерние формы отказываются работать. Сохранение/смена подписи могли завершиться частично. Нет автоматического retry/rollback/удаления: вручную исследуйте только этот UUID/текущего пользователя в одноразовойИБ. Не закрывайте пульт для слепого повтора маршрута.

  20. Пресет и новая подпись намеренно остаются в собственнойИБ для просмотра. Удаление всей базы/настроек/пользователей/истории и резервные копии/архивы не входят в этот урок. Здесь приведено авторство и статические проверки; реальная1С/БД/формы не запускались.

Процедура ПроверитьСвойПресет85(UUID, Пользователь) Экспорт
    ПроверитьСвойПустойСтенд();
    Если ИмяПользователя() <> "guide-own-presets" Или Пользователь <> ИмяПользователя() Тогда
        ВызватьИсключение "Только текущий собственный пользователь guide-own-presets";
    КонецЕсли;
    Если ТипЗнч(UUID) <> Тип("Строка") Или СтрДлина(UUID) <> 36
        Или НРег(Строка(Новый УникальныйИдентификатор(UUID))) <> НРег(UUID) Тогда
        ВызватьИсключение "Нужен действительный собственный UUID";
    КонецЕсли;
    Если Метаданные.ОсновнойРежимЗапуска <> РежимЗапускаКлиентскогоПриложения.ОбычноеПриложение
        Или Метаданные.ХранилищаНастроек.Количество() <> 1
        Или Метаданные.ХранилищаНастроек.Найти("УчебныеПресеты85") = Неопределено
        Или Метаданные.ОбщиеМодули.Количество() <> 1 Или Метаданные.ОбщиеМодули.Найти("УчебныеПресетыМаршрут85") = Неопределено
        Или Метаданные.ОбщиеФормы.Количество() <> 1 Или Метаданные.ОбщиеФормы.Найти("УчебныйСтартПресета85") = Неопределено Тогда
        ВызватьИсключение "Только своя новая конфигурация обычного приложения с одним хранилищем/модулем/стартовой формой";
    КонецЕсли;
    Модуль = Метаданные.ОбщиеМодули.УчебныеПресетыМаршрут85;
    Если Не Модуль.Сервер Или Модуль.Привилегированный
        Или Модуль.ПовторноеИспользованиеВозвращаемыхЗначений <> Метаданные.СвойстваОбъектов.ПовторноеИспользованиеВозвращаемыхЗначений.НеИспользовать Тогда
        ВызватьИсключение "Свой модуль не должен быть привилегированным или кэшировать данные";
    КонецЕсли;
    Регистр = Метаданные.РегистрыСведений.Найти("УчебныеДанныеПресетов85");
    Если Регистр = Неопределено Или Регистр.РежимЗаписи <> Метаданные.СвойстваОбъектов.РежимЗаписиРегистра.Независимый
        Или Регистр.ПериодичностьРегистраСведений <> Метаданные.СвойстваОбъектов.ПериодичностьРегистраСведений.Непериодический
        Или Регистр.ИсторияДанных <> Метаданные.СвойстваОбъектов.ИспользованиеИсторииДанных.НеИспользовать
        Или Регистр.Измерения.Количество() <> 3 Или Регистр.Ресурсы.Количество() <> 2 Или Регистр.Реквизиты.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен точный собственный независимый регистр без истории";
    КонецЕсли;
    Имена = СтрРазделить("КлючОбъекта85,КлючНастроек85,Пользователь85", ",");
    Длины = Новый Массив;
    Длины.Добавить(36);
    Длины.Добавить(32);
    Длины.Добавить(80);
    Для Индекс = 0 По 2 Цикл
        Измерение = Регистр.Измерения.Найти(Имена[Индекс]);
        Если Измерение = Неопределено Или Измерение.Тип.Типы().Количество() <> 1
            Или Не Измерение.Тип.СодержитТип(Тип("Строка")) Или Измерение.Тип.КвалификаторыСтроки.Длина <> Длины[Индекс] Тогда
            ВызватьИсключение "Ключи только именованные строки36/32/80";
        КонецЕсли;
    КонецЦикла;
    Данные = Регистр.Ресурсы.Найти("Данные85");
    Подпись = Регистр.Ресурсы.Найти("Подпись85");
    Если Данные = Неопределено Или Подпись = Неопределено Или Данные.Тип.Типы().Количество() <> 1
        Или Не Данные.Тип.СодержитТип(Тип("ХранилищеЗначения")) Или Подпись.Тип.Типы().Количество() <> 1
        Или Не Подпись.Тип.СодержитТип(Тип("Строка")) Или Подпись.Тип.КвалификаторыСтроки.Длина <> 128 Тогда
        ВызватьИсключение "Только ресурсХранилищеЗначения и строковая подпись128";
    КонецЕсли;
    Формы = Метаданные.ХранилищаНастроек.УчебныеПресеты85.Формы;
    Если Формы.Количество() <> 3 Тогда
        ВызватьИсключение "Подготовьте ровно три собственные обычные формы хранилища";
    КонецЕсли;
    Для Каждого Форма Из Формы Цикл
        Если СтрРазделить("Пульт,Сохранение,Загрузка", ",").Найти(Форма.Имя) = Неопределено Тогда
            ВызватьИсключение "Недопустимая форма в своем хранилище";
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

Функция СвоеХранилище85() Экспорт
    Хранилища = ХранилищаНастроек;
    Если ТипЗнч(Хранилища) <> Тип("ХранилищаНастроекМенеджер") Тогда
        ВызватьИсключение "Нужен native менеджер собственных хранилищ, не стандартное хранилище";
    КонецЕсли;
    Количество = 0;
    Для Каждого Хранилище Из Хранилища Цикл
        Количество = Количество + 1;
        Если ТипЗнч(Хранилище) <> Тип("ХранилищеНастроекМенеджер.УчебныеПресеты85") Тогда
            ВызватьИсключение "В собственном пространстве обнаружено другое хранилище";
        КонецЕсли;
    КонецЦикла;
    Если Количество <> 1 Тогда
        ВызватьИсключение "Разрешено ровно одно собственное хранилище";
    КонецЕсли;
    Возврат Хранилища.УчебныеПресеты85;
КонецФункции

Функция СвойРегистр85(UUID, Пользователь, Количество) Экспорт
    ПроверитьСвойПресет85(UUID, Пользователь);
    Запрос = Новый Запрос("ВЫБРАТЬ Д.* ИЗ РегистрСведений.УчебныеДанныеПресетов85 КАК Д");
    Данные = Запрос.Выполнить().Выгрузить();
    Если Данные.Количество() <> Количество Тогда
        ВызватьИсключение "Во всем собственном регистре другое число строк; неизвестные данные не изменять";
    КонецЕсли;
    Для Каждого СтрокаДанных Из Данные Цикл
        Если СтрокаДанных.КлючОбъекта85 <> UUID Или СтрокаДанных.КлючНастроек85 <> "book-cart"
            Или СтрокаДанных.Пользователь85 <> Пользователь Тогда
            ВызватьИсключение "Строка не входит в точный whitelist своегоUUID/пресета/текущего пользователя";
        КонецЕсли;
        ПроверитьПакет85(СтрокаДанных.Данные85.Получить());
    КонецЦикла;
    Возврат Данные;
КонецФункции

Процедура ПроверитьПакет85(Пакет) Экспорт
    Если ТипЗнч(Пакет) <> Тип("Структура") Или Пакет.Количество() <> 4
        Или Не Пакет.Свойство("Код") Или Не Пакет.Свойство("Количество")
        Или Не Пакет.Свойство("Цена") Или Не Пакет.Свойство("Сумма") Тогда
        ВызватьИсключение "Нужен собственный пакетКод/Количество/Цена/Сумма";
    КонецЕсли;
    Если Пакет.Код <> "BOOK" Или ТипЗнч(Пакет.Количество) <> Тип("Число") Или Пакет.Количество <> 3
        Или ТипЗнч(Пакет.Цена) <> Тип("Число") Или Пакет.Цена <> 250
        Или ТипЗнч(Пакет.Сумма) <> Тип("Число") Или Пакет.Сумма <> 3 * 250 Тогда
        ВызватьИсключение "Собственный пакет должен численно соответствоватьBOOK/3×250=750";
    КонецЕсли;
КонецПроцедуры

Функция ОписаниеСвоегоПресета85(UUID, Пользователь, Представление) Экспорт
    Описание = Новый ОписаниеНастроек;
    Описание.КлючОбъекта = UUID;
    Описание.КлючНастроек = "book-cart";
    Описание.Пользователь = Пользователь;
    Описание.Представление = Представление;
    Возврат Описание;
КонецФункции

Процедура СохранитьСвойПресет85(UUID, Пользователь, Подтверждение) Экспорт
    Если Подтверждение <> "СОХРАНИТЬ:" + UUID Тогда
        ВызватьИсключение "Введите отдельное точное подтверждениеСОХРАНИТЬ:UUID";
    КонецЕсли;
    СвойРегистр85(UUID, Пользователь, 0);
    Пакет = Новый Структура("Код,Количество,Цена,Сумма", "BOOK", 3, 250, 3 * 250);
    Описание = ОписаниеСвоегоПресета85(UUID, Пользователь, "Книга3×250=750");
    Хранилище = СвоеХранилище85();
    Хранилище.Сохранить(UUID, "book-cart", Пакет, Описание, Пользователь);
    Данные = СвойРегистр85(UUID, Пользователь, 1);
    Если Данные.Получить(0).Подпись85 <> "Книга3×250=750" Тогда
        ВызватьИсключение "Сохраненная подпись не подтверждена в реальном регистре";
    КонецЕсли;
    ПрочитатьСвойПресет85(UUID, Пользователь, "Книга3×250=750");
КонецПроцедуры

Функция ПрочитатьСвойПресет85(UUID, Пользователь, ОжидаемаяПодпись) Экспорт
    Данные = СвойРегистр85(UUID, Пользователь, 1);
    Хранилище = СвоеХранилище85();
    ЗагруженноеОписание = Новый ОписаниеНастроек;
    Пакет = Хранилище.Загрузить(UUID, "book-cart", ЗагруженноеОписание, Пользователь);
    ПроверитьПакет85(Пакет);
    Описание = Хранилище.ПолучитьОписание(UUID, "book-cart", Пользователь);
    Если Данные.Получить(0).Подпись85 <> ОжидаемаяПодпись
        Или ЗагруженноеОписание.Представление <> ОжидаемаяПодпись Или Описание.Представление <> ОжидаемаяПодпись
        Или Описание.КлючОбъекта <> UUID Или Описание.КлючНастроек <> "book-cart" Или Описание.Пользователь <> Пользователь Тогда
        ВызватьИсключение "Raw/Load/GetDescription должны подтверждать одну собственную подпись и точный ключ";
    КонецЕсли;
    Возврат Пакет;
КонецФункции

Процедура ИзменитьСвоюПодпись85(UUID, Пользователь, Подтверждение) Экспорт
    Если Подтверждение <> "ПОДПИСЬ:" + UUID Тогда
        ВызватьИсключение "Введите отдельное подтверждениеПОДПИСЬ:UUID";
    КонецЕсли;
    ПрочитатьСвойПресет85(UUID, Пользователь, "Книга3×250=750");
    Хранилище = СвоеХранилище85();
    Описание = ОписаниеСвоегоПресета85(UUID, Пользователь, "Проверено:750");
    Хранилище.УстановитьОписание(UUID, "book-cart", Описание, Пользователь);
    ПрочитатьСвойПресет85(UUID, Пользователь, "Проверено:750");
КонецПроцедуры

#Если ТолстыйКлиентОбычноеПриложение Тогда
Процедура ОткрытьСвойПульт85() Экспорт
    UUID = Строка(Новый УникальныйИдентификатор);
    Пользователь = ИмяПользователя();
    СвойРегистр85(UUID, Пользователь, 0);
    Хранилище = СвоеХранилище85();
    Если Хранилище.Загрузить(UUID, "book-cart", , Пользователь) <> Неопределено Тогда
        ВызватьИсключение "Собственная реализацияLoad должна подтвердить отсутствие нового ключа";
    КонецЕсли;
    Пульт = Хранилище.ПолучитьФорму("Пульт", Неопределено, UUID);
    Если Пульт = Неопределено Или ТипЗнч(Пульт) <> Тип("Форма") Тогда
        ВызватьИсключение "Нужна реально подготовленная обычная формаПульт";
    КонецЕсли;
    Пульт.UUID85 = UUID;
    Пульт.Пользователь85 = Пользователь;
    Пульт.Ошибка85 = Ложь;
    Пульт.ПодписьИзменена85 = Ложь;
    Пульт.Открыть();
КонецПроцедуры

Процедура ОткрытьСвоюЗапись85(Пульт) Экспорт
    Если Пульт.Ошибка85 Тогда
        ВызватьИсключение "Результат прошлого этапа неизвестен; не открывать новую попытку записи";
    КонецЕсли;
    СвойРегистр85(Пульт.UUID85, Пульт.Пользователь85, 0);
    Хранилище = СвоеХранилище85();
    Форма = Хранилище.ПолучитьФормуСохранения("Сохранение", Пульт, Пульт.UUID85 + ":save");
    Если Форма = Неопределено Или ТипЗнч(Форма) <> Тип("Форма") Или Форма.ВладелецФормы <> Пульт Тогда
        ВызватьИсключение "Нужна своя обычная формаСохранение с точным пультом-владельцем";
    КонецЕсли;
    Форма.UUID85 = Пульт.UUID85;
    Форма.Пользователь85 = Пульт.Пользователь85;
    Форма.Подтверждение85 = "";
    Форма.Открыть();
КонецПроцедуры

Процедура ОткрытьСвоеЧтение85(Пульт) Экспорт
    Если Пульт.Ошибка85 Тогда
        ВызватьИсключение "Остановитесь после ошибки; скрытого повторного сохранения нет";
    КонецЕсли;
    Подпись = ?(Пульт.ПодписьИзменена85, "Проверено:750", "Книга3×250=750");
    ПрочитатьСвойПресет85(Пульт.UUID85, Пульт.Пользователь85, Подпись);
    Хранилище = СвоеХранилище85();
    Форма = Хранилище.ПолучитьФормуЗагрузки("Загрузка", Пульт, Пульт.UUID85 + ":load");
    Если Форма = Неопределено Или ТипЗнч(Форма) <> Тип("Форма") Или Форма.ВладелецФормы <> Пульт Тогда
        ВызватьИсключение "Нужна своя обычная формаЗагрузка с точным владельцем";
    КонецЕсли;
    Форма.UUID85 = Пульт.UUID85;
    Форма.Пользователь85 = Пульт.Пользователь85;
    Форма.ОжидаемаяПодпись85 = Подпись;
    Форма.Открыть();
КонецПроцедуры
#КонецЕсли

Процедура ПроверитьСвойПустойСтенд()
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0 Или Метаданные.Перечисления.Количество() <> 0 Или Метаданные.РегистрыСведений.Количество() <> 1 Или Метаданные.РегистрыНакопления.Количество() <> 0 Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Или Метаданные.ПланыВидовХарактеристик.Количество() <> 0 Или Метаданные.ПланыВидовРасчета.Количество() <> 0 Или Метаданные.ПланыСчетов.Количество() <> 0 Или Метаданные.ПланыОбмена.Количество() <> 0 Или Метаданные.Последовательности.Количество() <> 0 Или Метаданные.БизнесПроцессы.Количество() <> 0 Или Метаданные.Задачи.Количество() <> 0 Или Метаданные.ОбщиеРеквизиты.Количество() <> 0 Или Метаданные.ПодпискиНаСобытия.Количество() <> 0 Или Метаданные.РегламентныеЗадания.Количество() <> 0 Или Метаданные.ВнешниеИсточникиДанных.Количество() <> 0 Тогда
        ВызватьИсключение "Нужен только свой новый пустой учебный стенд";
    КонецЕсли;
    Если Метаданные.ЕстьИзмененияРасширениямиКонфигурации() Тогда
        ВызватьИсключение "Свой сеанс не должен изменяться расширениями";
    КонецЕсли;
    Источники = Новый Массив;
    Источники.Добавить(ИсточникРасширенийКонфигурации.БазаДанных);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансАктивные);
    Источники.Добавить(ИсточникРасширенийКонфигурации.СеансОтключенные);
    Для Каждого Источник Из Источники Цикл
        Расширения = РасширенияКонфигурации.Получить(, Источник);
        Если ТипЗнч(Расширения) <> Тип("Массив") Тогда
            ВызватьИсключение "Native список расширений должен иметь тип Массив";
        КонецЕсли;
        Если Расширения.Количество() <> 0 Тогда
            ВызватьИсключение "В своём новом стенде нет расширений базы или сеанса";
        КонецЕсли;
    КонецЦикла;
    Если ТранзакцияАктивна() Тогда
        ВызватьИсключение "Чужая или вложенная активная транзакция не допускается";
    КонецЕсли;
КонецПроцедуры
Модуль менеджера УчебныеПресеты85: четыре предопределенных события

Своя CF УчебныеСвоиПресеты85 → Общие → ХранилищаНастроек → УчебныеПресеты85 → модуль менеджера целиком.

Модуль менеджера собственного хранилища. Native четыре события вызываются платформой, не вручную. Сервер и толстый обычный клиент согласно контрактам событий; подготовка и весь маршрут только своей отдельной ИБ.

Процедура ОбработкаСохранения(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, Пользователь)
    ПроверитьСвойКлюч85(КлючОбъекта, КлючНастроек, Пользователь);
    УчебныеПресетыМаршрут85.СвойРегистр85(КлючОбъекта, Пользователь, 0);
    УчебныеПресетыМаршрут85.ПроверитьПакет85(Настройки);
    Если ОписаниеНастроек = Неопределено Или ОписаниеНастроек.Представление <> "Книга3×250=750" Тогда
        ВызватьИсключение "Сохранение только собственной начальной подписи и реального описания";
    КонецЕсли;
    Запись = РегистрыСведений.УчебныеДанныеПресетов85.СоздатьМенеджерЗаписи();
    Запись.КлючОбъекта85 = КлючОбъекта;
    Запись.КлючНастроек85 = КлючНастроек;
    Запись.Пользователь85 = Пользователь;
    Запись.Прочитать();
    Если Запись.Выбран() Тогда
        ВызватьИсключение "Существующее не заменяется";
    КонецЕсли;
    Запись.КлючОбъекта85 = КлючОбъекта;
    Запись.КлючНастроек85 = КлючНастроек;
    Запись.Пользователь85 = Пользователь;
    Запись.Данные85 = Новый ХранилищеЗначения(Настройки);
    Запись.Подпись85 = ОписаниеНастроек.Представление;
    Запись.Записать(Ложь);
КонецПроцедуры

Процедура ОбработкаЗагрузки(КлючОбъекта, КлючНастроек, Настройки, ОписаниеНастроек, Пользователь)
    ПроверитьСвойКлюч85(КлючОбъекта, КлючНастроек, Пользователь);
    Запись = ПрочитатьСвоюЗапись85(КлючОбъекта, КлючНастроек, Пользователь);
    Если Не Запись.Выбран() Тогда
        УчебныеПресетыМаршрут85.СвойРегистр85(КлючОбъекта, Пользователь, 0);
        Настройки = Неопределено;
        Возврат;
    КонецЕсли;
    УчебныеПресетыМаршрут85.СвойРегистр85(КлючОбъекта, Пользователь, 1);
    Настройки = Запись.Данные85.Получить();
    УчебныеПресетыМаршрут85.ПроверитьПакет85(Настройки);
    Если ОписаниеНастроек <> Неопределено Тогда
        ОписаниеНастроек = УчебныеПресетыМаршрут85.ОписаниеСвоегоПресета85(КлючОбъекта, Пользователь, Запись.Подпись85);
    КонецЕсли;
КонецПроцедуры

Процедура ОбработкаПолученияОписания(КлючОбъекта, КлючНастроек, ОписаниеНастроек, Пользователь)
    ПроверитьСвойКлюч85(КлючОбъекта, КлючНастроек, Пользователь);
    УчебныеПресетыМаршрут85.СвойРегистр85(КлючОбъекта, Пользователь, 1);
    Запись = ПрочитатьСвоюЗапись85(КлючОбъекта, КлючНастроек, Пользователь);
    Если Не Запись.Выбран() Тогда
        ВызватьИсключение "Описания отсутствующего своего пресета нет";
    КонецЕсли;
    ОписаниеНастроек = УчебныеПресетыМаршрут85.ОписаниеСвоегоПресета85(КлючОбъекта, Пользователь, Запись.Подпись85);
КонецПроцедуры

Процедура ОбработкаУстановкиОписания(КлючОбъекта, КлючНастроек, ОписаниеНастроек, Пользователь)
    ПроверитьСвойКлюч85(КлючОбъекта, КлючНастроек, Пользователь);
    Данные = УчебныеПресетыМаршрут85.СвойРегистр85(КлючОбъекта, Пользователь, 1);
    Если Данные.Получить(0).Подпись85 <> "Книга3×250=750" Или ОписаниеНастроек.Представление <> "Проверено:750" Тогда
        ВызватьИсключение "Изменение только своей существующей начальной подписи наПроверено:750";
    КонецЕсли;
    Запись = ПрочитатьСвоюЗапись85(КлючОбъекта, КлючНастроек, Пользователь);
    Если Не Запись.Выбран() Или Запись.Подпись85 <> "Книга3×250=750" Тогда
        ВызватьИсключение "Fresh менеджер не подтвердил прежнюю свою подпись";
    КонецЕсли;
    УчебныеПресетыМаршрут85.ПроверитьПакет85(Запись.Данные85.Получить());
    Запись.Подпись85 = ОписаниеНастроек.Представление;
    Запись.Записать();
КонецПроцедуры

Процедура ПроверитьСвойКлюч85(КлючОбъекта, КлючНастроек, Пользователь)
    УчебныеПресетыМаршрут85.ПроверитьСвойПресет85(КлючОбъекта, Пользователь);
    Если ТипЗнч(КлючНастроек) <> Тип("Строка") Или КлючНастроек <> "book-cart" Тогда
        ВызватьИсключение "Не генерировать неизвестные ключи; разрешен толькоbook-cart собственногоUUID";
    КонецЕсли;
КонецПроцедуры

Функция ПрочитатьСвоюЗапись85(КлючОбъекта, КлючНастроек, Пользователь)
    Запись = РегистрыСведений.УчебныеДанныеПресетов85.СоздатьМенеджерЗаписи();
    Запись.КлючОбъекта85 = КлючОбъекта;
    Запись.КлючНастроек85 = КлючНастроек;
    Запись.Пользователь85 = Пользователь;
    Запись.Прочитать();
    Возврат Запись;
КонецФункции
Модуль обычной формы Пульт

Своя CF → Общие → ХранилищаНастроек → УчебныеПресеты85 → Формы → Пульт → модуль формы целиком.

Толстый клиент, обычное приложение. Три одноимённых действия кнопок с параметром Кнопка; реквизиты и guards своего пульта заданы в подготовке.

Процедура ОткрытьСохранение85(Кнопка)
    Если Ошибка85 Тогда
        ВызватьИсключение "Предыдущая ошибка требует ручной проверки; не повторять";
    КонецЕсли;
    Попытка
        УчебныеПресетыМаршрут85.ОткрытьСвоюЗапись85(ЭтаФорма);
    Исключение
        Ошибка85 = Истина;
        Результат85 = "СТОП: " + ОписаниеОшибки();
    КонецПопытки;
КонецПроцедуры

Процедура ОткрытьЗагрузку85(Кнопка)
    Если Ошибка85 Тогда
        ВызватьИсключение "После ошибки сначала вручную исследуйте собственный стенд";
    КонецЕсли;
    Попытка
        УчебныеПресетыМаршрут85.ОткрытьСвоеЧтение85(ЭтаФорма);
    Исключение
        Ошибка85 = Истина;
        Результат85 = "СТОП: " + ОписаниеОшибки();
    КонецПопытки;
КонецПроцедуры

Процедура СменитьПодпись85(Кнопка)
    Если Ошибка85 Или ПодписьИзменена85 Тогда
        ВызватьИсключение "Не повторять изменение или неопределенную операцию";
    КонецЕсли;
    Согласие = Подтверждение85;
    Подтверждение85 = "";
    Попытка
        УчебныеПресетыМаршрут85.ИзменитьСвоюПодпись85(UUID85, Пользователь85, Согласие);
        ПодписьИзменена85 = Истина;
        Результат85 = "ПодписьПроверено:750, пакетBOOK/3×250=750 подтвержден отдельно";
    Исключение
        Ошибка85 = Истина;
        Результат85 = "СТОП: результат изменения может быть частичным. " + ОписаниеОшибки();
    КонецПопытки;
КонецПроцедуры
Модуль обычной формы Сохранение

Своя CF → Общие → ХранилищаНастроек → УчебныеПресеты85 → Формы → Сохранение → модуль формы целиком.

Толстый клиент, обычное приложение. Native владелец — собственный пульт. Действия Сохранить85/Отмена85(Кнопка), никаких автоматических событий открытия/закрытия.

Процедура Сохранить85(Кнопка)
    Если ВладелецФормы = Неопределено Или ТипЗнч(ВладелецФормы) <> Тип("Форма") Тогда
        ВызватьИсключение "Нужен собственный обычный пульт-владелец";
    КонецЕсли;
    Если ВладелецФормы.Ошибка85 Или ВладелецФормы.UUID85 <> UUID85
        Или ВладелецФормы.Пользователь85 <> Пользователь85 Тогда
        ВызватьИсключение "Пульт остановлен или не соответствует нашемуUUID/пользователю";
    КонецЕсли;
    Согласие = Подтверждение85;
    Подтверждение85 = "";
    Попытка
        УчебныеПресетыМаршрут85.СохранитьСвойПресет85(UUID85, Пользователь85, Согласие);
        ВладелецФормы.Результат85 = "Пресет750 сохранен и независимо загружен. Закройте эту форму; затемЗагрузка.";
        Результат85 = ВладелецФормы.Результат85;
    Исключение
        ВладелецФормы.Ошибка85 = Истина;
        Результат85 = "СТОП: запись могла завершиться частично. " + ОписаниеОшибки();
        ВладелецФормы.Результат85 = Результат85;
    КонецПопытки;
КонецПроцедуры

Процедура Отмена85(Кнопка)
    ЭтаФорма.Закрыть();
КонецПроцедуры
Модуль обычной формы Загрузка

Своя CF → Общие → ХранилищаНастроек → УчебныеПресеты85 → Формы → Загрузка → модуль формы целиком.

Толстый клиент, обычное приложение. Native владелец — собственный пульт. Действия Прочитать85/Отмена85(Кнопка), сохранение этим модулем не вызывается.

Процедура Прочитать85(Кнопка)
    Если ВладелецФормы = Неопределено Или ТипЗнч(ВладелецФормы) <> Тип("Форма") Тогда
        ВызватьИсключение "Нужен реальный собственный обычный пульт";
    КонецЕсли;
    Если ВладелецФормы.Ошибка85 Или ВладелецФормы.UUID85 <> UUID85
        Или ВладелецФормы.Пользователь85 <> Пользователь85 Тогда
        ВызватьИсключение "Владелец не соответствует собственному опыту или остановлен";
    КонецЕсли;
    Попытка
        Пакет = УчебныеПресетыМаршрут85.ПрочитатьСвойПресет85(UUID85, Пользователь85, ОжидаемаяПодпись85);
        Результат85 = СтрШаблон("Код=%1, количество=%2, цена=%3, сумма=%4; подпись=%5", Пакет.Код, Пакет.Количество, Пакет.Цена, Пакет.Сумма, ОжидаемаяПодпись85);
    Исключение
        ВладелецФормы.Ошибка85 = Истина;
        Результат85 = "СТОП: " + ОписаниеОшибки();
        ВладелецФормы.Результат85 = Результат85;
    КонецПопытки;
КонецПроцедуры

Процедура Отмена85(Кнопка)
    ЭтаФорма.Закрыть();
КонецПроцедуры
Модуль общей обычной стартовой формы

Своя CF → Общие → ОбщиеФормы → УчебныйСтартПресета85 → модуль обычной формы целиком.

Толстый клиент, обычное приложение. Реальное действие кнопки ОткрытьПульт85(Кнопка), вызывающее общий модуль собственного стенда.

Процедура ОткрытьПульт85(Кнопка)
    УчебныеПресетыМаршрут85.ОткрытьСвойПульт85();
КонецПроцедуры

Разбор по шагам

  1. Глобальное ХранилищаНастроек дает только пользовательские хранилища конфигурации. Его реальная коллекция/тип и ровно один собственный менеджер проверяются; стандартное хранилище не подменяется.

  2. Пульт, Сохранение и Загрузка — реально подготовленные обычные формы толстого клиента. Их получают соответствующими ПолучитьФорму/ПолучитьФормуСохранения/ПолучитьФормуЗагрузки с точными именами, владельцем и своим ключом; Неопределено обрабатывается до доступа к реквизитам.

  3. Перед началом полный регистр пуст. Новый UUID и настоящий текущий пользователь становятся тремя ключевыми полями UUID/book-cart/currentuser; посторонние записи вызывают отказ, а не исключаются фильтром.

  4. Отмена/крестик не сохраняют собственный учебный пресет; возможное сохранение платформой положения окна здесь не исследуется. Только явная кнопка с СОХРАНИТЬ:UUID вызывает native Сохранить с пятью настоящими аргументами и свой ОбработкаСохранения; это не прямой вызов события.

  5. Свой обработчик проверяет пакет и0строк, читает новый менеджер записи и сохраняет ХранилищеЗначения/подпись. Fresh Load возвращает пакет через ОбработкаЗагрузки, а GetDescription — настоящее описание через свой одноименный обработчик.

  6. ОбработкаЗагрузки знает отрицательный контракт именно этого хранилища: нет записи — возвращается Неопределено. Положительный Load и raw-чтение независимо подтверждают3/250/750, подпись и ключ.

  7. Отдельная команда ПОДПИСЬ:UUID сначала читает начальную подпись и пакет. УстановитьОписание вызывает собственный четвертый обработчик, который меняет только существующую Подпись85; данные пакета не переназначаются.

  8. Повторный Load/GetDescription/raw-readback дают Проверено:750 и прежнийBOOK/3/250/750. Ошибка блокирует реального владельца-пульта; автоматических откатов, удалений и повторов нет.

Как проверить результат

  1. Перед явным сохранением0строк; закрытие/Отмена Сохранение оставляют0.

  2. После сохранения ровно одна собственная строка(UUID,book-cart,guide-own-presets), подпись Книга3×250=750 и проверенный пакет750.

  3. В форме Загрузка: BOOK,3,250,750; GetDescription/переданное Load описание/raw-подпись совпадают.

  4. После смены подписи ровно та же одна строка, Проверено:750, данные3×250 неизменны.

  5. Чужой ключ/пользователь, другой пакет, непустой начальный регистр, неизвестная подпись или повтор операции приводят к отказу.

Ожидаемый результат

Ожидаемый при ручном запуске результат: один свой сохраненный пресет750 с новой подписью, понятные формы сохранения/загрузки и работающие собственные native обработчики.

На что обратить внимание

  1. Контекст только thick ordinary, не управляемые формы. Все триGet* имеют3параметра и native результатФорма/Неопределено; наличие имени в metadata само по себе не доказывает runtime-открытие.

  2. Сохранение/Load-семантика задаются модулем менеджера. Стандартное хранилище/BSP и их параметры нельзя переносить без проверки.

  3. У обработчиков отключается безопасный режим платформой; безопасность урока основана на отдельной собственнойИБ, полном коде и строгих guards, не на обещании sandbox.

  4. Конкурентные изменения/частичный результат не устраняются моментальным readback. На ошибке остановитесь и исследуйте свой ключ, не повторяйте запись вслепую.

  5. ПолучитьМакет с противоречивой0-параметрной сигнатурой не используется и не покрывается; хранение не создает резервные копии.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.