Глобальный контекст.ПолучитьРазделительПути

Методы · GetPathSeparator

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

Синтаксис

ПолучитьРазделительПути()
Полное описание, параметры и ограничения

Глобальный контекст.ПолучитьРазделительПути (Global context.GetPathSeparator)

Глобальный контекст (Global context)

ПолучитьРазделительПути (GetPathSeparator)

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

Синтаксис:
ПолучитьРазделительПути()
Возвращаемое значение:
Тип: Строка.

Описание:

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

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

Тонкий клиент, веб-клиент, мобильный клиент, сервер, толстый клиент, внешнее соединение, мобильное приложение (клиент), мобильное приложение (сервер), мобильный автономный сервер.

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

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

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

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

Найти свои файлы на клиенте и сервере правильными масками и разделителями

Полный модуль формы: создаёт два независимых коротких файла на соответствующих сторонах, использует фактические маски ОС для поиска, проверяет байты и удаляет только свой опыт.

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

Полный модуль управляемой формы УчебныеФайловыеКонтексты85: толстый клиент Windows, НаСервереБезКонтекста и чистая проверка НаКлиентеНаСервереБезКонтекста.

Подготовка

  1. Создайте новую пустую конфигурацию УчебныеФайловыеКонтексты85 на платформе 8.5.1.1343, управляемое приложение. Рабочие базы и реальные файловые данные не подходят.

  2. Клиент — толстый клиент Windows. Для содержательного сравнения разных ОС можно позже вручную использовать изолированный сервер 1С Linux; это не обязательная настройка и сейчас сервер не разворачивается.

  3. Обработки → ОпытКонтекстов85 → управляемая форма Форма. Весь приведённый код помещается в один модуль формы: директивы определяют, на какой стороне выполняется каждая процедура.

  4. Реквизиты формы: ПодтверждаюСвоиФайлы85 и Занято85 типа Булево; ПутьСвоегоКаталога85 и Итог85 типа Строка неограниченной длины. Исходно флажки Ложь.

  5. Согласие показывайте флажком для ввода, занятость, путь и итог — только для просмотра. Никакого пользовательского поля для серверного пути нет.

  6. Создайте команду СравнитьСвоиФайловыеКонтексты85 и её действие, выведите кнопку. ПередЗакрытием назначьте одноимённому событию с четырьмя параметрами из полного модуля.

  7. Вставьте код, нажмите F7 и обновите только стенд. runtimeVerifiedScenarios=0: 1С, серверный вызов, создание файлов, поиск и очистка здесь не выполнялись.

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

  9. На сервере путь создаёт сам неконтекстный серверный метод через ПолучитьИмяВременногоФайла. Путь клиента туда вообще не передаётся и не становится серверным источником.

  10. Клиентский опыт содержит source.txt с ABC-85, серверный — server-source.txt с SERVER-85. Это соответственно шесть и девять байт UTF-8; секретные и рабочие файлы не используются.

  11. Клиентская папка имеет расширение guidefiles, серверная — guidectx. Существующий объект по сгенерированному имени отклоняется; имена не означают атомарного резервирования.

  12. Подтвердите только собственный опыт и вручную запустите команду. Дождитесь снятия Занято85, не меняйте файлы извне и не прерывайте клиент/сервер во время опыта.

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

  14. Не ожидайте разных результатов масок на одинаковой ОС и не требуйте равенства масок на разных ОС. Проверяется обнаружение собственного файла, а не заранее заданная строка *.* или определённый разделитель.

  15. Серверная очистка завершается до возврата отчёта. Клиентская выполняется независимо после результата или ошибки серверного вызова; никакие посторонние файлы и непустые каталоги не удаляются.

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

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

&НаСервереБезКонтекста
Функция ПроверитьСвойСерверныйКаталог85(Согласие)
    Если Не Согласие Тогда
        ВызватьИсключение "Только свой пустой стенд УчебныеФайловыеКонтексты85 с согласием";
    КонецЕсли;
    Разделитель = ПолучитьРазделительПутиСервера();
    МаскаСервера = ПолучитьМаскуВсеФайлыСервера();
    МаскаТекущая = ПолучитьМаскуВсеФайлы();
    Каталог = ПолучитьИмяВременногоФайла("guidectx");
    ФайлКаталога = Новый Файл(Каталог);
    Если ФайлКаталога.Существует() Тогда
        ВызватьИсключение "Серверное имя уже занято; объект не считается своим";
    КонецЕсли;
    Путь = Каталог + Разделитель + "server-source.txt";
    КаталогСоздан = Ложь;
    ОшибкаОпыта = "";
    Попытка
        СоздатьКаталог(Каталог);
        КаталогСоздан = Истина;
        СвойФайл = Новый Файл(Путь);
        Если СвойФайл.Существует() Тогда
            ВызватьИсключение "Серверный источник уже занят; перезапись запрещена";
        КонецЕсли;
        ОжидаемыеБайты = ПолучитьДвоичныеДанныеИзСтроки("SERVER-85", КодировкаТекста.UTF8);
        ОжидаемыеБайты.Записать(Путь);
        ПроверитьОдноСвоеСовпадение85(НайтиФайлы(Каталог, МаскаСервера, Ложь), Путь);
        ПроверитьОдноСвоеСовпадение85(НайтиФайлы(Каталог, МаскаТекущая, Ложь), Путь);
        ПрочитанныеБайты = Новый ДвоичныеДанные(Путь);
        Если Base64Строка(ПрочитанныеБайты) <> Base64Строка(ОжидаемыеБайты) Тогда
            ВызватьИсключение "Серверный файл отличается от SERVER-85";
        КонецЕсли;
    Исключение
        ОшибкаОпыта = ОписаниеОшибки();
    КонецПопытки;
    ОшибкаОчистки = ОчиститьСвойСерверныйКаталог85(Каталог, Разделитель, Путь, КаталогСоздан);
    Если ОшибкаОпыта <> "" Или ОшибкаОчистки <> "" Тогда
        ВызватьИсключение ОшибкаОпыта + " " + ОшибкаОчистки;
    КонецЕсли;
    Возврат Новый Структура("Каталог,Разделитель,МаскаСервера,МаскаТекущая", Каталог, Разделитель, МаскаСервера, МаскаТекущая);
КонецФункции

&НаСервереБезКонтекста
Функция ОчиститьСвойСерверныйКаталог85(Каталог, Разделитель, Путь, КаталогСоздан)
    Если Не КаталогСоздан Тогда
        Возврат "Создание собственного серверного каталога не подтверждено; очистка не начата";
    КонецЕсли;
    Если Прав(Каталог, 9) <> ".guidectx" Или Путь <> Каталог + Разделитель + "server-source.txt" Тогда
        Возврат "Не совпали границы собственного серверного опыта; очистка не начата";
    КонецЕсли;
    ОшибкаОчистки = "";
    Попытка
        СвойФайл = Новый Файл(Путь);
        Если СвойФайл.Существует() Тогда
            Если СвойФайл.ЭтоКаталог() Тогда
                ВызватьИсключение "На месте своего серверного файла каталог; его не удаляем";
            КонецЕсли;
            УдалитьФайлы(Путь);
        КонецЕсли;
        Если СвойФайл.Существует() Тогда
            ВызватьИсключение "Свой серверный файл остался после удаления";
        КонецЕсли;
    Исключение
        ОшибкаОчистки = ОшибкаОчистки + " " + ОписаниеОшибки();
    КонецПопытки;
    Попытка
        СвойКаталог = Новый Файл(Каталог);
        Если СвойКаталог.Существует() Тогда
            Остаток = НайтиФайлы(Каталог, "*", Ложь);
            Если Остаток.Количество() <> 0 Тогда
                ВызватьИсключение "Серверный каталог не пуст; чужие объекты не удаляем";
            КонецЕсли;
            УдалитьФайлы(Каталог);
        КонецЕсли;
        Если СвойКаталог.Существует() Тогда
            ВызватьИсключение "Свой пустой серверный каталог остался после удаления";
        КонецЕсли;
    Исключение
        ОшибкаОчистки = ОшибкаОчистки + " " + ОписаниеОшибки();
    КонецПопытки;
    Возврат ОшибкаОчистки;
КонецФункции

&НаКлиенте
Процедура ПроверитьСвойСтенд85()
    Если Не ПодтверждаюСвоиФайлы85 Тогда
        ВызватьИсключение "Только собственный новый стенд УчебныеФайловыеКонтексты85 с согласием";
    КонецЕсли;
    Если Занято85 Тогда
        ВызватьИсключение "Дождитесь завершения текущего собственного опыта";
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Функция СоздатьСвойКонтекст85()
    Разделитель = ПолучитьРазделительПути();
    Каталог = ПолучитьИмяВременногоФайла("guidefiles");
    ФайлКаталога = Новый Файл(Каталог);
    Если ФайлКаталога.Существует() Тогда
        ВызватьИсключение "Уникальное имя уже занято; найденный объект не считается своим";
    КонецЕсли;
    К = Новый Структура;
    К.Вставить("Каталог", Каталог);
    К.Вставить("Разделитель", Разделитель);
    К.Вставить("КаталогСоздан", Ложь);
    К.Вставить("Исходник", Каталог + Разделитель + "source.txt");
    К.Вставить("Копия", Каталог + Разделитель + "copy.txt");
    К.Вставить("Перемещенный", Каталог + Разделитель + "moved.txt");
    К.Вставить("ОжидаемыеБайты", ПолучитьДвоичныеДанныеИзСтроки("ABC-85", КодировкаТекста.UTF8));
    ПутьСвоегоКаталога85 = Каталог;
    Возврат К;
КонецФункции

&НаКлиенте
Процедура ПроверитьСвоюОбласть85(К)
    Если К.Каталог <> ПутьСвоегоКаталога85 Или Прав(К.Каталог, 11) <> ".guidefiles" Тогда
        ВызватьИсключение "Не совпал собственный сгенерированный каталог этого опыта";
    КонецЕсли;
    Если К.Исходник <> К.Каталог + К.Разделитель + "source.txt"
        Или К.Копия <> К.Каталог + К.Разделитель + "copy.txt"
        Или К.Перемещенный <> К.Каталог + К.Разделитель + "moved.txt" Тогда
        ВызватьИсключение "Изменились границы собственной файловой области";
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ЗаписатьСвойИсходник85(К)
    ПроверитьСвоюОбласть85(К);
    ФайлКаталога = Новый Файл(К.Каталог);
    Если Не К.КаталогСоздан Или Не ФайлКаталога.Существует() Или Не ФайлКаталога.ЭтоКаталог() Тогда
        ВызватьИсключение "Создание своего каталога ещё не подтверждено";
    КонецЕсли;
    ФайлИсходника = Новый Файл(К.Исходник);
    Если ФайлИсходника.Существует() Тогда
        ВызватьИсключение "Свой источник не должен перезаписывать существующий файл";
    КонецЕсли;
    К.ОжидаемыеБайты.Записать(К.Исходник);
КонецПроцедуры

&НаКлиенте
Функция ОчиститьТолькоСвойОпыт85(К)
    Если К = Неопределено Тогда
        Возврат "";
    КонецЕсли;
    ОшибкаОчистки = "";
    Попытка
        ПроверитьСвоюОбласть85(К);
    Исключение
        Возврат "Границы опыта не подтвердились; очистка не начата: " + ОписаниеОшибки();
    КонецПопытки;
    Если Не К.КаталогСоздан Тогда
        Возврат "Создание каталога не подтвердилось; автоматическая очистка не выполнялась";
    КонецЕсли;
    Имена = Новый Массив;
    Имена.Добавить(К.Исходник);
    Имена.Добавить(К.Копия);
    Имена.Добавить(К.Перемещенный);
    Для Каждого Имя Из Имена Цикл
        Попытка
            СвойФайл = Новый Файл(Имя);
            Если СвойФайл.Существует() Тогда
                Если СвойФайл.ЭтоКаталог() Тогда
                    ВызватьИсключение "На месте своего файла обнаружен каталог; его не удаляем";
                КонецЕсли;
                УдалитьФайлы(Имя);
            КонецЕсли;
            Если СвойФайл.Существует() Тогда
                ВызватьИсключение "Свой файл остался после удаления";
            КонецЕсли;
        Исключение
            ОшибкаОчистки = ОшибкаОчистки + " " + ОписаниеОшибки();
        КонецПопытки;
    КонецЦикла;
    Попытка
        СвойКаталог = Новый Файл(К.Каталог);
        Если СвойКаталог.Существует() Тогда
            Остаток = НайтиФайлы(К.Каталог, "*", Ложь);
            Если Остаток.Количество() <> 0 Тогда
                ВызватьИсключение "Каталог не пуст; неизвестные объекты не удаляем";
            КонецЕсли;
            УдалитьФайлы(К.Каталог);
        КонецЕсли;
        Если СвойКаталог.Существует() Тогда
            ВызватьИсключение "Свой пустой каталог остался после удаления";
        КонецЕсли;
    Исключение
        ОшибкаОчистки = ОшибкаОчистки + " " + ОписаниеОшибки();
    КонецПопытки;
    Возврат ОшибкаОчистки;
КонецФункции

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

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

  1. Клиентский обработчик проверяет свой стенд, версию и согласие; флаг занятости исключает второй запуск. Создаётся только source.txt в новом собственном клиентском каталоге.

  2. ПолучитьМаскуВсеФайлыКлиента возвращает правило ОС клиента, ПолучитьМаскуВсеФайлы — текущего контекста. Обе полученные строки используются в отдельном поиске собственного каталога.

  3. Общий чистый проверочный метод компилируется для клиента и сервера. Он не переносит файловые операции между сторонами: проверяет только один реальный найденный Файл, полный путь и отсутствие каталога.

  4. На клиенте читаются реальные байты source.txt и сравниваются с ABC-85. Затем неконтекстный серверный вызов получает только согласие, а не клиентский путь.

  5. На сервере вновь проверяются конфигурация и версия. ПолучитьРазделительПутиСервера строит собственный серверный путь; ПолучитьМаскуВсеФайлыСервера и текущая маска используются только на этой стороне.

  6. Сервер создаёт свой server-source.txt из SERVER-85, выполняет два нерекурсивных поиска и сравнивает фактически прочитанные байты. Заранее заданных серверных путей нет.

  7. Очистка сервера проверяет подтверждение создания, суффикс и точный свой файл. Удаление файла и проверка пустоты каталога выполняются независимо; обе ошибки сохраняются.

  8. На клиент возвращается только структура строкового отчёта после успешной серверной очистки. Клиент независимо удаляет собственный опыт и сообщает успех только при отсутствии обеих ошибок.

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

  1. Каждая из двух масок клиента находит ровно его source.txt; обе серверные маски — ровно server-source.txt в собственном серверном каталоге.

  2. Клиентский файл подтверждён как ABC-85, серверный как SERVER-85. Совпадение имён или размеров не заменяет сравнение содержимого.

  3. В клиентской части нет вызовов ПолучитьРазделительПутиСервера и ПолучитьМаскуВсеФайлыСервера. Они находятся только под НаСервереБезКонтекста.

  4. На одинаковой ОС маски/разделители могут совпасть; на разных могут отличаться. Это не меняет проверку собственных файлов и не делает серверный путь доступным клиенту.

  5. После штатного успеха оба опыта очищены. При ошибке результат не выдаётся за успех; неизвестные объекты и непустые каталоги остаются.

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

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

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

  1. ПолучитьРазделительПутиСервера и ПолучитьМаскуВсеФайлыСервера вызывают исключение на клиенте в клиент-серверном варианте. Доступность «толстый клиент» не отменяет это примечание; здесь оба вызова находятся на сервере.

  2. ПолучитьМаскуВсеФайлы определяется текущей стороной исполнения. Одна и та же процедура формы не исполняется одновременно на обеих сторонах; директивы задают контекст.

  3. В файловом варианте серверный контекст может исполняться локально. Это не повод переставлять серверные вызовы в клиентский обработчик: модуль сохраняет правильные директивы.

  4. Серверный путь в отчёте предназначен для диагностики владельцем, не для НайтиФайлы на клиенте. Даже совпавшие строки путей на разных компьютерах относятся к разным файловым системам.

  5. Маска «все файлы» не является рекурсивным обходом и не является гарантией обнаружения всех системных, скрытых или запрещённых по правам объектов. Урок проверяет только свой один обычный txt-файл.

  6. Уникальное имя и Существует не являются атомарным резервированием. Учебные каталоги должны быть закрыты от сторонних писателей; это не production-защита от подмены и гонок.

  7. УдалитьФайлы может рекурсивно удалить каталог. Здесь это допускается только для подтверждённого собственного пустого каталога; файл заранее проверяется на ЭтоКаталог=Ложь.

  8. Очистка использует * для нерекурсивной проверки любых остатков, а не только *.txt. Неизвестные файлы и подкаталоги никогда не удаляются автоматически.

  9. Если сервер аварийно завершился или файловые права не позволяют очистку, гарантии удаления нет. Администратор разбирает собственный путь; пользовательские каталоги не очищаются.

  10. Нет сетевого диска, внешнего API, архива и резервного копирования данных. Все операции файлов в этом уроке — только будущий отдельный ручной учебный опыт.

  11. Проверка согласия и имени пустой базы — ограничение учебного стенда, не система авторизации production-сервиса. Серверный метод не должен принимать произвольные пути от недоверенного клиента.

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

Пройти файловый цикл Асинх/Ждать на своих шести байтах и проверить очистку

Один контролируемый локальный опыт: новый собственный каталог, источник ABC-85, копирование, перемещение, нерекурсивный поиск, чтение реальных байтов и удаление только своих файлов.

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

Полный модуль управляемой формы в толстом клиенте Windows; Асинх/Ждать и небольшой собственный файловый опыт только на клиенте.

Подготовка

  1. Создайте новую пустую конфигурацию УчебныеФайлы85 на платформе8.5.1.1343, управляемое приложение, режим совместимости Не использовать. Не используйте рабочую базу или чужие обработчики.

  2. Оба урока выполняются именно толстым клиентом Windows с управляемым приложением. Они не предназначены для веб-клиента, мобильного клиента, сервера или фонового задания.

  3. Обработки → ОпытФайлов85 → основная управляемая форма Форма. Для каждого урока используйте отдельную обработку либо целиком заменяйте модуль формы, не объединяйте два полных модуля.

  4. Создайте реквизиты ПодтверждаюСвоиФайлы85 типа Булево, Занято85 типа Булево, ПутьСвоегоКаталога85 типа Строка неограниченной длины и Итог85 типа Строка неограниченной длины. Исходно оба флажка Ложь; Занято85, путь и итог показывайте только для просмотра.

  5. Добавьте команду с именем основной процедуры урока и одноимённое действие; перетащите её на форму. Назначьте ПередЗакрытием с четырьмя параметрами из полного модуля.

  6. Нажмите F7 и обновите только стенд. runtimeVerifiedScenarios=0: 1С здесь не запускалась; учебные каталоги, файлы, копирование и удаление не выполнялись.

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

  8. ПолучитьИмяВременногоФайла генерирует имя, но не создаёт файл. Это имя с расширением guidefiles используется как отдельный каталог опыта; существующий объект по такому имени отклоняется до операций.

  9. Внутри собственного каталога создаётся source.txt с шестью байтами ABC-85 в UTF-8 без данных пользователя. copy.txt и moved.txt относятся только к этому же опыту; пути не берутся из полей ввода.

  10. После собственного ручного подтверждения запустите команду и дождитесь Занято85=Ложь. Не закрывайте клиент и не изменяйте файлы извне между асинхронными этапами.

  11. Очистка удаляет только три заранее известные собственные файловые имена. Пустой собственный каталог удаляется лишь после нерекурсивного поиска всех оставшихся объектов; неизвестные файлы/подкаталоги не удаляются.

  12. Операции очистки небольшого локального опыта синхронные и допустимы в выбранном толстом клиенте. При отказе прав, вмешательстве другого процесса или принудительном завершении очистка не обещается: итог сообщает ошибку, а сгенерированный путь остаётся видимым для ручной проверки.

  13. Команда и кнопка ВыполнитьСвоиФайлыАсинх85. Асинх Процедура уже объявлена; не вставляйте Ждать в обычный неасинхронный обработчик.

&НаКлиенте
Асинх Процедура ВыполнитьСвоиФайлыАсинх85(Команда)
    ПроверитьСвойСтенд85();
    Занято85 = Истина;
    К = Неопределено;
    ОшибкаОпыта = "";
    Попытка
        К = СоздатьСвойКонтекст85();
        СозданныйКаталог = Ждать СоздатьКаталогАсинх(К.Каталог);
        К.КаталогСоздан = Истина;
        Если СозданныйКаталог <> К.Каталог Тогда
            ВызватьИсключение "Результат создания не совпал со своим запрошенным каталогом";
        КонецЕсли;
        ЗаписатьСвойИсходник85(К);
        Копия = Ждать КопироватьФайлАсинх(К.Исходник, К.Копия);
        Если Копия <> К.Копия Тогда
            ВызватьИсключение "Возвращён не свой путь копии";
        КонецЕсли;
        Перемещенный = Ждать ПереместитьФайлАсинх(К.Копия, К.Перемещенный);
        Если Перемещенный <> К.Перемещенный Тогда
            ВызватьИсключение "Возвращён не свой путь перемещения";
        КонецЕсли;
        ПрежняяКопия = Новый Файл(К.Копия);
        Если ПрежняяКопия.Существует() Тогда
            ВызватьИсключение "После перемещения copy.txt должен исчезнуть";
        КонецЕсли;
        Найденные = Ждать НайтиФайлыАсинх(К.Каталог, "*.txt", Ложь);
        ПроверитьСвойПоиск85(Найденные, К);
        ПрочитанныеБайты = Ждать СоздатьДвоичныеДанныеИзФайлаАсинх(К.Перемещенный);
        Если Base64Строка(ПрочитанныеБайты) <> Base64Строка(К.ОжидаемыеБайты) Тогда
            ВызватьИсключение "Байты перемещённого файла отличаются от ABC-85 в UTF-8";
        КонецЕсли;
        Ждать УдалитьФайлыАсинх(К.Исходник);
        Ждать УдалитьФайлыАсинх(К.Перемещенный);
    Исключение
        ОшибкаОпыта = ОписаниеОшибки();
    КонецПопытки;
    ОшибкаОчистки = ОчиститьТолькоСвойОпыт85(К);
    Занято85 = Ложь;
    Если ОшибкаОпыта <> "" Или ОшибкаОчистки <> "" Тогда
        Итог85 = ОшибкаОпыта + " " + ОшибкаОчистки;
        ВызватьИсключение Итог85;
    КонецЕсли;
    Итог85 = "Копирование, перемещение, поиск и чтение ABC-85 подтверждены. Свои файлы и пустой каталог удалены.";
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьСвойСтенд85()
    Если Не ПодтверждаюСвоиФайлы85 Тогда
        ВызватьИсключение "Только собственный новый стенд УчебныеФайлы85 с согласием";
    КонецЕсли;
    Если Занято85 Тогда
        ВызватьИсключение "Дождитесь завершения текущего собственного опыта";
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Функция СоздатьСвойКонтекст85()
    Разделитель = ПолучитьРазделительПути();
    Каталог = ПолучитьИмяВременногоФайла("guidefiles");
    ФайлКаталога = Новый Файл(Каталог);
    Если ФайлКаталога.Существует() Тогда
        ВызватьИсключение "Уникальное имя уже занято; найденный объект не считается своим";
    КонецЕсли;
    К = Новый Структура;
    К.Вставить("Каталог", Каталог);
    К.Вставить("Разделитель", Разделитель);
    К.Вставить("КаталогСоздан", Ложь);
    К.Вставить("Исходник", Каталог + Разделитель + "source.txt");
    К.Вставить("Копия", Каталог + Разделитель + "copy.txt");
    К.Вставить("Перемещенный", Каталог + Разделитель + "moved.txt");
    К.Вставить("ОжидаемыеБайты", ПолучитьДвоичныеДанныеИзСтроки("ABC-85", КодировкаТекста.UTF8));
    К.Вставить("Ошибка", "");
    К.Вставить("Завершено", Ложь);
    ПутьСвоегоКаталога85 = Каталог;
    Возврат К;
КонецФункции

&НаКлиенте
Процедура ПроверитьСвоюОбласть85(К)
    Если К.Каталог <> ПутьСвоегоКаталога85 Или Прав(К.Каталог, 11) <> ".guidefiles" Тогда
        ВызватьИсключение "Не совпал собственный сгенерированный каталог этого опыта";
    КонецЕсли;
    Если К.Исходник <> К.Каталог + К.Разделитель + "source.txt"
        Или К.Копия <> К.Каталог + К.Разделитель + "copy.txt"
        Или К.Перемещенный <> К.Каталог + К.Разделитель + "moved.txt" Тогда
        ВызватьИсключение "Изменились границы собственной файловой области";
    КонецЕсли;
КонецПроцедуры

&НаКлиенте
Процедура ЗаписатьСвойИсходник85(К)
    ПроверитьСвоюОбласть85(К);
    ФайлКаталога = Новый Файл(К.Каталог);
    Если Не К.КаталогСоздан Или Не ФайлКаталога.Существует() Или Не ФайлКаталога.ЭтоКаталог() Тогда
        ВызватьИсключение "Создание своего каталога ещё не подтверждено";
    КонецЕсли;
    ФайлИсходника = Новый Файл(К.Исходник);
    Если ФайлИсходника.Существует() Тогда
        ВызватьИсключение "Свой источник не должен перезаписывать существующий файл";
    КонецЕсли;
    К.ОжидаемыеБайты.Записать(К.Исходник);
КонецПроцедуры

&НаКлиенте
Процедура ПроверитьСвойПоиск85(Найденные, К)
    ПроверитьСвоюОбласть85(К);
    Если ТипЗнч(Найденные) <> Тип("Массив") Или Найденные.Количество() <> 2 Тогда
        ВызватьИсключение "После перемещения нужны два реальных собственных txt-файла";
    КонецЕсли;
    Для Каждого Найденный Из Найденные Цикл
        Если Найденный.ПолноеИмя <> К.Исходник И Найденный.ПолноеИмя <> К.Перемещенный Тогда
            ВызватьИсключение "Поиск вернул неожиданный объект; не удаляйте его";
        КонецЕсли;
        Если Найденный.ЭтоКаталог() Тогда
            ВызватьИсключение "Вместо собственного txt-файла найден каталог";
        КонецЕсли;
    КонецЦикла;
КонецПроцедуры

&НаКлиенте
Функция ОчиститьТолькоСвойОпыт85(К)
    Если К = Неопределено Тогда
        Возврат "";
    КонецЕсли;
    ОшибкаОчистки = "";
    Попытка
        ПроверитьСвоюОбласть85(К);
    Исключение
        Возврат "Границы опыта не подтвердились; очистка не начата: " + ОписаниеОшибки();
    КонецПопытки;
    Если Не К.КаталогСоздан Тогда
        Возврат "Создание каталога не подтвердилось; автоматическая очистка не выполнялась";
    КонецЕсли;
    Имена = Новый Массив;
    Имена.Добавить(К.Исходник);
    Имена.Добавить(К.Копия);
    Имена.Добавить(К.Перемещенный);
    Для Каждого Имя Из Имена Цикл
        Попытка
            СвойФайл = Новый Файл(Имя);
            Если СвойФайл.Существует() Тогда
                Если СвойФайл.ЭтоКаталог() Тогда
                    ВызватьИсключение "На месте своего файла обнаружен каталог; его не удаляем";
                КонецЕсли;
                УдалитьФайлы(Имя);
            КонецЕсли;
            Если СвойФайл.Существует() Тогда
                ВызватьИсключение "Свой файл остался после удаления";
            КонецЕсли;
        Исключение
            ОшибкаОчистки = ОшибкаОчистки + " " + ОписаниеОшибки();
        КонецПопытки;
    КонецЦикла;
    Попытка
        СвойКаталог = Новый Файл(К.Каталог);
        Если СвойКаталог.Существует() Тогда
            Остаток = НайтиФайлы(К.Каталог, "*", Ложь);
            Если Остаток.Количество() <> 0 Тогда
                ВызватьИсключение "Каталог не пуст; неизвестные объекты не удаляем";
            КонецЕсли;
            УдалитьФайлы(К.Каталог);
        КонецЕсли;
        Если СвойКаталог.Существует() Тогда
            ВызватьИсключение "Свой пустой каталог остался после удаления";
        КонецЕсли;
    Исключение
        ОшибкаОчистки = ОшибкаОчистки + " " + ОписаниеОшибки();
    КонецПопытки;
    Возврат ОшибкаОчистки;
КонецФункции

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

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

  1. Проверка стенда и согласия выполняется до операций. Занято85 не допускает второго опыта; собственный контекст создаёт имена внутри одного нового каталога через реальный разделитель пути ОС.

  2. Ждать СоздатьКаталогАсинх получает фактический строковый результат. После успеха создаётся только собственный источник из ДвоичныеДанные ABC-85.

  3. Ждать КопироватьФайлАсинх и Ждать ПереместитьФайлАсинх выполняются последовательно; возвращённые пути проверяются. Старый copy.txt после перемещения не должен существовать.

  4. Ждать НайтиФайлыАсинх возвращает массив Файл. Проверяются два результата, их полные имена и отсутствие каталогов вместо файлов; обход подкаталогов выключен.

  5. Ждать СоздатьДвоичныеДанныеИзФайлаАсинх читает moved.txt. Base64Строка фактических байтов сравнивается с Base64 исходных шести байт.

  6. Два Ждать УдалитьФайлыАсинх удаляют source.txt и moved.txt. Независимая завершающая очистка проверяет известные имена и пустоту каталога даже после ошибки основной операции.

  7. Занято85 снимается после попытки очистки. Успех показывается только при отсутствии основной ошибки и ошибки очистки; иначе обе сохраняются в исключении.

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

  1. Один опыт создаёт только собственную папку и свои файлы; пользовательские документы не используются.

  2. После перемещения поиск обнаруживает source.txt и moved.txt, но не copy.txt.

  3. Прочитанные байты moved.txt в точности совпадают с ABC-85 в UTF-8.

  4. После успешного завершения собственных файлов и каталога нет; при ошибке очистки итог не содержит ложного успеха.

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

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

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

  1. Копирование допускает перезапись приёмника. Здесь приёмник появляется только в новом собственном каталоге; не заменяйте путь рабочим файлом или папкой.

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

  3. УдалитьФайлы без маски может рекурсивно удалить каталог. Файловые имена сначала проверяются на ЭтоКаталог=Ложь, а каталог опыта — на отсутствие любых дочерних объектов. Не убирайте эти проверки.

  4. Маска *.txt и ИскатьВПодкаталогах=Ложь относятся только к своей новой папке. Поиск в КаталогДокументов, профиле пользователя или корне диска здесь не выполняется.

  5. Проверка содержимого сравнивает реальные двоичные данные через Base64, а не размер или красивое сообщение. Для больших файлов такой подход потребует другой стратегии; здесь всего6 байт.

  6. После перемещения старый copy.txt должен исчезнуть. Перемещение в другой том может иметь иной профиль ошибок; урок использует только одну собственную папку.

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

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

  9. Создать/копировать/переместить возвращают строковые пути, удаление возвращает Неопределено, а поиск и чтение возвращают разные типы. Не трактуйте все результаты как Булево.

  10. Синхронная запись6 байт и завершающая очистка здесь намеренно локальные. Урок объясняет жизненный цикл, а не утверждает, что каждая операция приложения должна быть асинхронной.

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

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

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

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

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