При интерактивном выборе каталога через стандартный ДиалогВыбораФайла платформа 1С возвращает локальный путь. Если папка расположена на сетевом диске, пользователь получает путь с буквой диска, например Y:\Счета\2024. Однако при записи такого пути в базу данных для общего доступа других пользователей или для обработки на стороне сервера 1С этот путь оказывается недействительным. У других пользователей этот же каталог может быть подключен под другой буквой, а служба сервера 1С вовсе не видит пользовательские сетевые диски.
Для универсального доступа путь необходимо привести к формату UNC (Universal Naming Convention), то есть к виду \\ServerName\ShareName\Счета\2024. В платформе 1С нет встроенного прямого метода для трансляции буквы диска в UNC-путь, но эту задачу можно решить с помощью системных компонентов Windows.
Прежде чем перейти к программному коду, разберем ключевые особенности сетевого взаимодействия в среде Windows и 1С:
&НаКлиенте.MSScriptControl.ScriptControl. Обратите внимание: этот компонент является исключительно 32-битным. Если база запускается под 64-битным клиентом 1С, попытка создания MSScriptControl приведет к ошибке отсутствия зарегистрированного класса. Оптимально вызывать системные библиотеки напрямую через стандартный COMОбъект без промежуточных скриптов.\\). В таком случае никакие преобразования выполнять не требуется.Рассмотрим наиболее надежный и быстрый способ на базе системной библиотеки Scripting.FileSystemObject. Данный COM-объект присутствует во всех версиях Windows и корректно работает как в 32-битной, так и в 64-битной версии клиента 1С.
Объект диска GetDrive содержит специальное свойство ShareName, которое возвращает сетевое имя ресурса для сетевых дисков и пустую строку для локальных.
Посмотрим на пример универсальной функции, выполняющей преобразование:
&НаКлиенте
Функция ПолучитьСетевойПутьUNC(Знач ИсходныйПуть) Экспорт
// Если путь уже является UNC или строка пустая, возвращаем как есть
Если ПустаяСтрока(ИсходныйПуть) Или Лев(ИсходныйПуть, 2) = "\\" Тогда
Возврат ИсходныйПуть;
КонецЕсли;
Попытка
ФСО = Новый COMОбъект("Scripting.FileSystemObject");
ИмяДиска = ФСО.GetDriveName(ИсходныйПуть); // Получает, например, "Y:"
Если ПустаяСтрока(ИмяДиска) Тогда
Возврат ИсходныйПуть;
КонецЕсли;
ОбъектДиск = ФСО.GetDrive(ИмяДиска);
СетевойРесурс = ОбъектДиск.ShareName; // Возвращает, например, "\\server\share"
// Если диск сетевой, заменяем букву диска на сетевой ресурс
Если Не ПустаяСтрока(СетевойРесурс) Тогда
ДлинаИмениДиска = СтрДлина(ИмяДиска);
ОстатокПути = Сред(ИсходныйПуть, ДлинаИмениДиска + 1);
Возврат СетевойРесурс + ОстатокПути;
КонецЕсли;
Исключение
// В случае ошибки COM-объекта возвращаем исходный путь
Возврат ИсходныйПуть;
КонецПопытки;
Возврат ИсходныйПуть;
КонецФункции
Разберем альтернативный вариант решения через объект Wscript.Network. Метод EnumNetworkDrives() возвращает коллекцию всех подключенных сетевых дисков в текущей сессии Windows.
Коллекция устроена в виде одномерного массива, где элементы чередуются парами: по четным индексам располагается локальное имя (буква диска), а по следующим за ними нечетным индексам — соответствующее сетевое имя ресурса.
Посмотрим на программную реализацию сопоставления буквы диска с сетевым ресурсом:
&НаКлиенте
Функция ПреобразоватьДискВUNC_WScript(Знач ИсходныйПуть) Экспорт
Если ПустаяСтрока(ИсходныйПуть) Или Лев(ИсходныйПуть, 2) = "\\" Тогда
Возврат ИсходныйПуть;
КонецЕсли;
Попытка
Сеть = Новый COMОбъект("Wscript.Network");
СетевыеДиски = Сеть.EnumNetworkDrives();
// Извлекаем букву диска с двоеточием, например "Y:"
ПозицияДвоеточия = СтрНайти(ИсходныйПуть, ":");
Если ПозицияДвоеточия = 0 Тогда
Возврат ИсходныйПуть;
КонецЕсли;
БукваДиска = ВРег(Лев(ИсходныйПуть, ПозицияДвоеточия));
СетевоеИмя = "";
// Обходим коллекцию с шагом 2
ВсегоЭлементов = СетевыеДиски.Count();
Для Индекс = 0 По ВсегоЭлементов - 1 Цикл
Если Индекс % 2 = 0 Тогда
Если ВРег(СетевыеДиски.Item(Индекс)) = БукваДиска Тогда
СетевоеИмя = СетевыеДиски.Item(Индекс + 1);
Прервать;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Если Не ПустаяСтрока(СетевоеИмя) Тогда
Возврат СетевоеИмя + Сред(ИсходныйПуть, ПозицияДвоеточия + 1);
КонецЕсли;
Исключение
Возврат ИсходныйПуть;
КонецПопытки;
Возврат ИсходныйПуть;
КонецФункции
Проанализируем решение, к которому пришел автор темы. В нем для вызова методов FileSystemObject используется прослойка из компонента MSScriptControl.ScriptControl.
Пример кода из темы:
Функция СетевоеИмяДиска(ИмяДиска)
СетевоеИмяДиска = "";
Скрипт = Новый COMОбъект("MSScriptControl.ScriptControl");
Скрипт.language = "VBscript";
Текст = СтрШаблон(
"Function Driveinfo()
|Dim drvpath
|drvpath = ""%1""
|Dim fs, d
|Set fs = CreateObject(""Scripting.FileSystemObject"")
|Set d = fs.GetDrive(fs.GetDriveName(drvpath))
|Driveinfo = Driveinfo & d.sharename
|End Function", ИмяДиска);
Скрипт.AddCode(Текст);
Попытка
СетевоеИмяДиска = Скрипт.Run("Driveinfo");
Исключение
КонецПопытки;
Если ТипЗнч(СетевоеИмяДиска) = Тип("Строка") И Не ПустаяСтрока(СетевоеИмяДиска) Тогда
Возврат СетевоеИмяДиска;
Иначе
Возврат ИмяДиска;
КонецЕсли;
КонецФункции
Важное предостережение: Данный подход избыточен, так как создает дополнительный COM-объект сценариев вместо прямого вызова FileSystemObject. Кроме того, как упоминалось ранее, MSScriptControl гарантированно вызовет аварийное завершение попытки создания объекта на 64-разрядном клиенте 1С («Класс не зарегистрирован»). Рекомендуется отдавать предпочтение Способу 1.
Выясним, как соединить получение пути из диалога и его конвертацию в практическом сценарии формы:
&НаКлиенте
Процедура ВыбратьКаталог(Команда)
ДиалогВыбора = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.ВыборКаталога);
ДиалогВыбора.Заголовок = "Выберите общую сетевую папку";
Если ДиалогВыбора.Выбрать() Тогда
ВыбранныйПуть = ДиалогВыбора.Каталог;
// Преобразуем локальный диск в UNC
СетевойПутьUNC = ПолучитьСетевойПутьUNC(ВыбранныйПуть);
// Проверяем, не остался ли путь локальным (например, C:\Папка)
Если Лев(СетевойПутьUNC, 2) <> "\\" Тогда
Сообщить("Внимание! Выбран локальный каталог, недоступный другим пользователям по сети: " + СетевойПутьUNC);
КонецЕсли;
Объект.ПутьККаталогу = СетевойПутьUNC;
КонецЕсли;
КонецПроцедуры
Такой подход обеспечивает сохранение корректного сетевого пути в базе данных, позволяя серверным фоновым заданиям и другим рабочим местам беспрепятственно обращаться к общим файлам.