При интеграции 1С с внешними системами (например, промышленными станками, сетевыми хранилищами, базами данных общего доступа) разработчики часто сталкиваются с необходимостью записи файлов в сетевые папки (UNC-пути вида \\server\share). Если целевой каталог защищен паролем или находится в другом домене, стандартные методы платформы 1С выдадут ошибку доступа. Ситуация усложняется, когда код должен выполняться на стороне сервера 1С, где интерактивный ввод пароля невозможен, или в веб-клиенте с мобильных устройств.
В этой статье мы подробно рассмотрим, почему возникает эта проблема, проанализируем разницу контекстов выполнения кода и разберем несколько надежных способов подключения к защищенным каталогам с авторизацией.
Прежде чем переходить к коду, выясним причину возникновения ошибки. Всё зависит от того, в каком контексте выполняется ваш код в 1С:
&НаКлиенте): Программа работает в сессии текущего пользователя Windows. Если этот пользователь уже авторизован в сети или у него подключен сетевой диск с нужными правами, запись пройдет успешно. Если доступа нет, операционная система затребует ввод логина и пароля, что невозможно сделать программно через стандартный диалог.&НаСервере): Код исполняется службой «Агент сервера 1С:Предприятия». По умолчанию эта служба запускается от имени специального локального пользователя (например, USR1CV8). У этого пользователя нет прав доступа к сетевым ресурсам вашей компании, и он ничего «не знает» про сетевые диски, подключенные на вашем компьютере. Более того, серверная служба не имеет интерактивного интерфейса.Ниже мы подробно разберем решения для каждого из этих сценариев.
Самый надежный и безопасный способ, не требующий хранения паролей в коде 1С, — делегирование прав на уровне операционной системы Windows. Если ваш сервер 1С работает в доменной сети, выполните следующие шаги:
domain\svc_1c).\\192.168.100.100\files).После этой настройки сервер 1С будет прозрачно и автоматически авторизовываться на сетевом ресурсе. В коде 1С вам достаточно написать самый простой и чистый код:
// Код выполняется НаСервере
ПутьККаталогу = "\\192.168.100.100\files\";
ИмяФайла = ПутьККаталогу + "data.txt";
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
Запись.ЗаписатьСтроку("Данные успешно выгружены из 1С.");
Запись.Закрыть();
Важно: Если целевое устройство (например, Wi-Fi модуль станка) не входит в домен и поддерживает только локальную авторизацию, администратор сервера 1С может сохранить сетевой пароль в Диспетчере учетных данных Windows (Credential Manager) конкретно для пользователя, под которым запущена служба 1С. В таком случае прозрачный доступ также будет работать.
Если сетевые каталоги меняются динамически, либо у вас нет возможности привлекать системных администраторов для изменения настроек службы 1С, можно авторизоваться в папке программно. Для этого мы задействуем системный COM-объект операционной системы Windows WScript.Network.
Этот способ позволяет смонтировать сетевой ресурс как локальный диск под определенной буквой, передав логин и пароль в параметрах метода, выполнить запись файла и затем безопасно размонтировать диск.
Рассмотрим пример кода, реализующий этот алгоритм на сервере:
// Код должен выполняться строго на стороне сервера Windows
БукваДиска = "Z:";
СетевойРесурс = "\\192.168.100.100\files";
Логин = "ИмяПользователя";
Пароль = "ПарольДоступа";
// Шаг 1. Инициализируем COM-объект для работы с сетью
Попытка
СетевоеОкружение = Новый COMОбъект("WScript.Network");
Исключение
ВызватьИсключение "Не удалось инициализировать системный объект WScript.Network. Проверьте ОС сервера.";
КонецПопытки;
// Шаг 2. Подключаем сетевой диск с передачей авторизационных данных
Попытка
// Параметры метода MapNetworkDrive:
// 1. Буква подключаемого диска
// 2. Сетевой UNC-путь
// 3. Флаг сохранения подключения (Ложь - не сохранять после перезагрузки)
// 4. Имя пользователя
// 5. Пароль
СетевоеОкружение.MapNetworkDrive(БукваДиска, СетевойРесурс, Ложь, Логин, Пароль);
Исключение
// Если диск Z уже занят или авторизация не удалась
ЗаписьЖурналаРегистрации("СетевойДоступ", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
ВызватьИсключение "Ошибка подключения сетевого диска: " + ОписаниеОшибки();
КонецПопытки;
// Шаг 3. Записываем файл на временно подключенный диск
Попытка
ИмяФайла = БукваДиска + "\export_data.txt";
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
Запись.ЗаписатьСтроку("Команда для выполнения на станке");
Запись.Закрыть();
Успешно = Истина;
Исключение
Успешно = Ложь;
ЗаписьЖурналаРегистрации("СетевойДоступ", УровеньЖурналаРегистрации.Ошибка,,, "Ошибка записи файла: " + ОписаниеОшибки());
КонецПопытки;
// Шаг 4. Обязательно отключаем диск, чтобы освободить букву в системе
Попытка
// Параметры метода RemoveNetworkDrive:
// 1. Буква диска
// 2. Флаг принудительного отключения (Истина)
// 3. Флаг обновления профиля пользователя (Истина)
СетевоеОкружение.RemoveNetworkDrive(БукваДиска, Истина, Истина);
Исключение
// Данная ошибка не влияет на результат записи файла, но ее стоит зафиксировать
ЗаписьЖурналаРегистрации("СетевойДоступ", УровеньЖурналаРегистрации.Предупреждение,,, "Не удалось отключить диск: " + ОписаниеОшибки());
КонецПопытки;
Если Не Успешно Тогда
ВызватьИсключение "Операция записи файла не была завершена из-за внутренних ошибок.";
КонецЕсли;
В процессе обсуждения на форуме участники часто предлагают использовать системную команду net use. Однако вызов метода КомандаСистемы() недоступен на сервере в контексте управляемых форм. Для решения этой проблемы мы можем программно создать временный командный файл (с расширением .bat или .cmd) на сервере и выполнить его через встроенную функцию ЗапуститьПриложение().
Проанализируем этот подход по шагам:
OEM (DOS-кодировка).Пример программной реализации:
// Код выполняется строго НаСервере
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("cmd");
// Создаем bat-файл с командами авторизации, записи и отключения
СодержимоеБат = Новый ЗаписьТекста(ИмяВременногоФайла, КодировкаТекста.OEM);
СодержимоеБат.ЗаписатьСтроку("net use Y: \\192.168.100.100\files /user:DeviceUser DevicePassword /yes");
СодержимоеБат.ЗаписатьСтроку("echo CommandData > Y:\job_card.txt");
СодержимоеБат.ЗаписатьСтроку("net use Y: /delete /yes");
СодержимоеБат.Закрыть();
// Запускаем bat-файл на сервере
КодВозврата = 0;
// Третий параметр "Истина" указывает системе дождаться окончания выполнения скрипта
ЗапуститьПриложение(ИмяВременногоФайла, , Истина, КодВозврата);
// Удаляем временный командный файл с жесткого диска сервера
Попытка
УдалитьФайлы(ИмяВременногоФайла);
Исключение
// Логируем ошибку удаления, если файл заблокирован процессом
ЗаписьЖурналаРегистрации("ОчисткаВременныхФайлов", УровеньЖурналаРегистрации.Предупреждение,,, ОписаниеОшибки());
КонецПопытки;
Если КодВозврата <> 0 Тогда
ВызватьИсключение "Ошибка выполнения системной команды. Код возврата: " + Строка(КодВозврата);
КонецЕсли;
Поскольку современные сервера 1С всё чаще разворачиваются на операционных системах семейства Linux (Ubuntu, CentOS, Astra Linux), методы работы с COM-объектами Windows или вызовы команд net use в них работать не будут. Кроссплатформенное решение этой задачи полностью лежит в плоскости администрирования операционной системы сервера.
Разберем алгоритм настройки для Linux-окружения:
cifs-utils)./mnt/cnc_share./etc/fstab прописывается автоматическое монтирование защищенной папки при старте системы:
//192.168.100.100/files /mnt/cnc_share cifs credentials=/etc/cnc-credentials,iocharset=utf8,uid=usr1cv8,gid=grp1cv8 0 0
/etc/cnc-credentials сохраняются логин и пароль авторизации удаленного ресурса./mnt/cnc_share выдаются пользователю Linux, под которым запущена служба сервера 1С (обычно это usr1cv8).При такой архитектуре программный код 1С становится абсолютно независимым от операционной системы и максимально простым:
// Кроссплатформенный код записи файла на сервере 1С
ИмяФайла = "/mnt/cnc_share/file.txt"; // Для Linux
// Либо ИмяФайла = "\\192.168.100.100\files\file.txt"; // Для Windows с прозрачной авторизацией
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.UTF8);
Запись.ЗаписатьСтроку("Данные для оборудования");
Запись.Закрыть();
В обсуждении на форуме упоминается важный нюанс: конечный пользователь работает через веб-клиент с мобильного устройства (планшета или телефона) и управляет станком. Напрямую обратиться к сетевому каталогу из браузера мобильного устройства невозможно из-за ограничений безопасности веб-обозревателей.
Для реализации этой бизнес-задачи мы должны использовать классическую трехзвенную схему передачи данных:
Рассмотрим пример реализации такой схемы:
&НаКлиенте
Процедура ОтправитьФайлНаСтанок(Команда)
// Подготавливаем тестовые данные для отправки на станок
ТекстКоманды = "START_JOB;ID=123;SPEED=450;";
// Помещаем текстовые данные во временное хранилище
АдресХранилища = ПоместитьВоВременноеХранилище(ТекстКоманды, УникальныйИдентификатор);
// Передаем управление серверу для выполнения физической записи файла
РезультатЗаписи = ЗаписатьФайлНаСервере(АдресХранилища);
Если РезультатЗаписи Тогда
ПоказатьПредупреждение(, "Файл успешно отправлен на станок через сетевой каталог!");
Иначе
ПоказатьПредупреждение(, "Произошла ошибка при отправке файла. Обратитесь к системному администратору.");
EndIf;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ЗаписатьФайлНаСервере(Знач АдресХранилища)
// Получаем текстовые данные из временного хранилища
ТекстДляЗаписи = ПолучитьИзВременногоХранилища(АдресХранилища);
// Путь к сетевой папке станка (настроенной по Решению 1 с правами для USR1CV8)
КаталогСтанка = "\\192.168.100.100\wifi_cnc_memory\";
ИмяФайла = КаталогСтанка + "program.txt";
Попытка
Запись = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
Запись.ЗаписатьСтроку(ТекстДляЗаписи);
Запись.Закрыть();
Возврат Истина;
Исключение
ЗаписьЖурналаРегистрации("ЗаписьНаСтанок", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
Возврат Ложь;
КонецПопытки;
КонецФункции
Если сервер 1С и целевые станки/хранилища распределены по разным изолированным доменам, между которыми не настроены доверительные отношения (Trust Relationships), доменная авторизация Windows работать не будет. В этом случае мы рекомендуем использовать механизм зеркальных учетных записей (Pass-Through Authentication):
usr_exchange_1c) с определенным сложным паролем.usr_exchange_1c и точно таким же паролем.Используя приведенные инструкции и примеры кода, вы сможете выстроить надежную и безопасную архитектуру обмена файлами в защищенных сетевых каталогах, работающую стабильно в любых режимах запуска платформы 1С:Предприятие.