В процессе разработки конфигураций или внешних обработок в среде 1С:Предприятие 8 часто возникает задача обращения к внешним файлам: логам, настройкам в формате .xml или текстовым данным. Типичная ошибка начинающего разработчика — указание жесткого (абсолютного) пути, например, E:\123\2\LOG.log. Такой подход делает код нежизнеспособным, как только база переносится на другой сервер или открывается другим пользователем. В этой статье мы подробно разберем, как сделать путь к файлу динамическим, чтобы система сама понимала, где искать нужный объект, не заставляя пользователя вводить путь вручную.
Важно понимать фундаментальную особенность платформы: 1С не поддерживает относительные пути в стиле операционных систем (например, ..\log.txt) напрямую в методах работы с файлами. Объекты вроде ЧтениеТекста или ТекстовыйДокумент всегда требуют полный путь. Следовательно, наша задача — научиться вычислять этот путь программно.
Проанализируем ситуацию, когда наш файл должен находиться непосредственно в папке с информационной базой. Это удобно для файловых баз, так как файл перемещается вместе с данными. Для этого мы можем использовать функцию СтрокаСоединенияИнформационнойБазы(). Разберем по шагам, как извлечь из нее путь:
Строка соединения для файловой базы выглядит примерно так: File="D:\Bases\MyBase";. Нам нужно отсечь лишние символы. Посмотрим на пример кода:
СтрокаСоединения = СтрокаСоединенияИнформационнойБазы();
// Извлекаем путь, убирая "File=" и кавычки
ПутьКБазе = Сред(СтрокаСоединения, 7, СтрДлина(СтрокаСоединения) - 8);
ПолныйПутьКФайлу = ПутьКБазе + "LOG.log";
НомерСтрLog = Новый ЧтениеТекста;
НомерСтрLog.Открыть(ПолныйПутьКФайлу);
Этот метод отлично подходит для небольших локальных систем, но стоит помнить, что в клиент-серверном варианте (SQL) строка соединения будет содержать имя сервера и базы, а не путь к диску. Поэтому для серверных решений этот способ не применим.
Если ваша логика сосредоточена во внешней обработке (файл .epf), и вспомогательный файл (например, лог) лежит в той же папке, мы можем использовать свойство ИспользуемоеИмяФайла. Рассмотрим, как это работает в Обычном приложении:
// В модуле внешней обработки
ФайлОбработки = Новый Файл(ЭтотОбъект.ИспользуемоеИмяФайла);
КаталогОбработки = ФайлОбработки.Путь;
ПолныйПутьКФайлу = КаталогОбработки + "LOG.log";
В Управляемом приложении ситуация сложнее, так как код может выполняться на сервере, где файла обработки физически нет. В этом случае рекомендуется передавать путь с клиента на сервер или использовать временные хранилища. Тем не менее, для локальных инструментов администратора этот метод остается крайне эффективным.
Зачастую программе не важно, где именно лежит файл, главное — чтобы у текущего пользователя были права на чтение и запись. Для этого 1С предоставляет встроенные функции для доступа к стандартным папкам Windows или Linux. Рассмотрим основные из них:
Проанализируем пример использования временного каталога:
ИмяФайла = КаталогВременныхФайлов() + "my_temp_log.log";
Чтение = Новый ЧтениеТекста;
// Теперь мы уверены, что путь существует и доступен
Чтение.Открыть(ИмяФайла);
Иногда требуется обратиться к папкам, которые заданы в системных переменных Windows, например, %APPDATA% или %USERPROFILE%. Напрямую 1С их не понимает, но мы можем использовать объект WScript.Shell для их раскрытия. Разберем этот продвинутый метод:
Shell = Новый COMОбъект("WScript.Shell");
// Раскрываем переменную окружения
ПутьAppData = Shell.ExpandEnvironmentStrings("%APPDATA%");
ПолныйПуть = ПутьAppData + "\1C_Logs\LOG.log";
// Далее работаем с файлом как обычно
ФайлЛога = Новый Файл(ПолныйПуть);
Если ФайлЛога.Существует() Тогда
// выполняем чтение
КонецЕсли;
Этот подход делает ваш путь "относительным" относительно профиля пользователя в операционной системе, что очень удобно для хранения персональных настроек.
Если мы знаем только диск (например, E:\) и имя файла, но не знаем точную вложенность папок, мы можем задействовать метод НайтиФайлы. Это позволяет реализовать гибкий поиск. Проанализируем пример поиска во всех подкаталогах:
// Ищем файл LOG.log на диске E в любой папке
НайденныеФайлы = НайтиФайлы("E:\", "LOG.log", Истина);
Для Каждого ТекущийФайл Из НайденныеФайлы Цикл
Сообщить("Файл найден здесь: " + ТекущийФайл.ПолноеИмя);
// Берем первый попавшийся и выходим
НужныйПуть = ТекущийФайл.ПолноеИмя;
Прервать;
КонецЦикла;
Важное замечание: Поиск по всему диску может занять много времени, поэтому старайтесь максимально ограничивать начальный каталог поиска.
При написании универсального кода, который должен работать и на Windows, и на Linux, никогда не используйте жестко заданный обратный слеш (\). В Linux разделителем является прямой слеш (/). Выясним, как сделать код универсальным:
Используйте функцию ПолучитьРазделительПути(). Проанализируем правильное построение строки пути:
Разделитель = ПолучитьРазделительПути();
ПутьКФайлу = КаталогВременныхФайлов() + Разделитель + "LOG.log";
Такой код будет успешно работать на сервере под любой операционной системой.
Выясним причину частой ошибки: код отлично работает на локальном компьютере программиста, но "валится" при выполнении на сервере. Когда код выполняется в контексте сервера (например, в регламентном задании), он запускается от имени системного пользователя (обычно USR1CV8). У этого пользователя часто нет прав на чтение дисков D: или E:.
Рекомендация: Если вам нужно писать логи из серверного кода, используйте КаталогВременныхФайлов() или заранее создайте на сервере папку и дайте пользователю USR1CV8 полные права на нее. В этом случае путь лучше хранить в Константе или Параметрах сеанса, чтобы администратор мог изменить его в любой момент без правки кода.
Подводя итог, мы видим, что "относительный путь" в 1С — это всегда результат динамического вычисления. Используя комбинацию системных функций и объектов для работы с файловой системой, вы сможете создавать надежные и переносимые решения.