Как в 1С получить сетевой (UNC) путь к папке вместо буквы диска?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При интерактивном выборе каталога через стандартный ДиалогВыбораФайла платформа 1С возвращает локальный путь. Если папка расположена на сетевом диске, пользователь получает путь с буквой диска, например Y:\Счета\2024. Однако при записи такого пути в базу данных для общего доступа других пользователей или для обработки на стороне сервера 1С этот путь оказывается недействительным. У других пользователей этот же каталог может быть подключен под другой буквой, а служба сервера 1С вовсе не видит пользовательские сетевые диски.

Для универсального доступа путь необходимо привести к формату UNC (Universal Naming Convention), то есть к виду \\ServerName\ShareName\Счета\2024. В платформе 1С нет встроенного прямого метода для трансляции буквы диска в UNC-путь, но эту задачу можно решить с помощью системных компонентов Windows.

Особенности реализации и контекст выполнения

Прежде чем перейти к программному коду, разберем ключевые особенности сетевого взаимодействия в среде Windows и 1С:

  1. Контекст выполнения (Клиент): Подключение сетевых дисков (маппинг) всегда выполняется в рамках конкретной пользовательской сессии Windows. Служба сервера 1С работает под отдельной системной или доменной учетной записью и не имеет доступа к сессионным дискам пользователя. Поэтому преобразование пути обязательно должно выполняться на стороне клиента в процедурах с директивой &НаКлиенте.
  2. Разрядность платформы: В теме форума автор использовал компонент MSScriptControl.ScriptControl. Обратите внимание: этот компонент является исключительно 32-битным. Если база запускается под 64-битным клиентом 1С, попытка создания MSScriptControl приведет к ошибке отсутствия зарегистрированного класса. Оптимально вызывать системные библиотеки напрямую через стандартный COMОбъект без промежуточных скриптов.
  3. Проверка исходной строки: Если пользователь открыл ресурс напрямую через «Сетевое окружение», возвращенный путь уже имеет формат UNC (начинается с символов \\). В таком случае никакие преобразования выполнять не требуется.

Способ 1. Прямое обращение к Scripting.FileSystemObject (рекомендуемый)

Рассмотрим наиболее надежный и быстрый способ на базе системной библиотеки Scripting.FileSystemObject. Данный COM-объект присутствует во всех версиях Windows и корректно работает как в 32-битной, так и в 64-битной версии клиента 1С.

Объект диска GetDrive содержит специальное свойство ShareName, которое возвращает сетевое имя ресурса для сетевых дисков и пустую строку для локальных.

Посмотрим на пример универсальной функции, выполняющей преобразование:


&НаКлиенте
Функция ПолучитьСетевойПутьUNC(Знач ИсходныйПуть) Экспорт
    
    // Если путь уже является UNC или строка пустая, возвращаем как есть
    Если ПустаяСтрока(ИсходныйПуть) Или Лев(ИсходныйПуть, 2) = "\\" Тогда
        Возврат ИсходныйПуть;
    КонецЕсли;
    
    Попытка
        ФСО = Новый COMОбъект("Scripting.FileSystemObject");
        ИмяДиска = ФСО.GetDriveName(ИсходныйПуть); // Получает, например, "Y:"
        
        Если ПустаяСтрока(ИмяДиска) Тогда
            Возврат ИсходныйПуть;
        КонецЕсли;
        
        ОбъектДиск = ФСО.GetDrive(ИмяДиска);
        СетевойРесурс = ОбъектДиск.ShareName; // Возвращает, например, "\\server\share"
        
        // Если диск сетевой, заменяем букву диска на сетевой ресурс
        Если Не ПустаяСтрока(СетевойРесурс) Тогда
            ДлинаИмениДиска = СтрДлина(ИмяДиска);
            ОстатокПути = Сред(ИсходныйПуть, ДлинаИмениДиска + 1);
            Возврат СетевойРесурс + ОстатокПути;
        КонецЕсли;
        
    Исключение
        // В случае ошибки COM-объекта возвращаем исходный путь
        Возврат ИсходныйПуть;
    КонецПопытки;
    
    Возврат ИсходныйПуть;
    
КонецФункции

Способ 2. Получение списка подключений через Wscript.Network

Разберем альтернативный вариант решения через объект Wscript.Network. Метод EnumNetworkDrives() возвращает коллекцию всех подключенных сетевых дисков в текущей сессии Windows.

Коллекция устроена в виде одномерного массива, где элементы чередуются парами: по четным индексам располагается локальное имя (буква диска), а по следующим за ними нечетным индексам — соответствующее сетевое имя ресурса.

Посмотрим на программную реализацию сопоставления буквы диска с сетевым ресурсом:


&НаКлиенте
Функция ПреобразоватьДискВUNC_WScript(Знач ИсходныйПуть) Экспорт
    
    Если ПустаяСтрока(ИсходныйПуть) Или Лев(ИсходныйПуть, 2) = "\\" Тогда
        Возврат ИсходныйПуть;
    КонецЕсли;
    
    Попытка
        Сеть = Новый COMОбъект("Wscript.Network");
        СетевыеДиски = Сеть.EnumNetworkDrives();
        
        // Извлекаем букву диска с двоеточием, например "Y:"
        ПозицияДвоеточия = СтрНайти(ИсходныйПуть, ":");
        Если ПозицияДвоеточия = 0 Тогда
            Возврат ИсходныйПуть;
        КонецЕсли;
        
        БукваДиска = ВРег(Лев(ИсходныйПуть, ПозицияДвоеточия));
        СетевоеИмя = "";
        
        // Обходим коллекцию с шагом 2
        ВсегоЭлементов = СетевыеДиски.Count();
        Для Индекс = 0 По ВсегоЭлементов - 1 Цикл
            Если Индекс % 2 = 0 Тогда
                Если ВРег(СетевыеДиски.Item(Индекс)) = БукваДиска Тогда
                    СетевоеИмя = СетевыеДиски.Item(Индекс + 1);
                    Прервать;
                КонецЕсли;
            КонецЕсли;
        КонецЦикла;
        
        Если Не ПустаяСтрока(СетевоеИмя) Тогда
            Возврат СетевоеИмя + Сред(ИсходныйПуть, ПозицияДвоеточия + 1);
        КонецЕсли;
        
    Исключение
        Возврат ИсходныйПуть;
    КонецПопытки;
    
    Возврат ИсходныйПуть;
    
КонецФункции

Способ 3. Вариант автора темы (VBScript через MSScriptControl)

Проанализируем решение, к которому пришел автор темы. В нем для вызова методов 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;
    КонецЕсли;
    
КонецПроцедуры

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

← На главную