Как по полному имени файла определить, что он находится на удаленной машине?

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

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

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

Подводные камни простой проверки по префиксу UNC

Самое очевидное решение, которое приходит в голову разработчику, — проверить начало строки полного пути файла на наличие двойного слэша:


Если Лев(ПолноеИмяФайла, 2) = "\\" Тогда
    // Файл находится в сети (UNC-путь)
КонецЕсли;

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

  1. Подключенные сетевые диски: Пользователь или администратор может подключить сетевую папку (шару) как отдельную букву диска (например, Z:\). В этом случае полный путь будет выглядеть как Z:\documents\file.txt, и проверка на двойной слэш вернет Ложь, хотя файл фактически лежит на удаленном сервере.
  2. Символические ссылки и точки соединения: Локальный каталог на диске C:\ может являться символической ссылкой (symlink) или точкой соединения (junction), ведущей на удаленный сетевой ресурс. Внешне путь остается полностью локальным.
  3. Контекст выполнения (Клиент / Сервер): В среде Windows смонтированные диски существуют только в рамках пользовательской сессии. Если код выполняется на сервере 1С под системной учетной записью, подключенные пользователем буквы дисков там вообще не будут видны.

Способ 1. Определение типа диска через WMI (Win32_LogicalDisk)

Для того чтобы корректно распознать смонтированные сетевые диски под операционной системой Windows, обратимся к средствам WMI (Windows Management Instrumentation). Через WMI можно получить список всех логических дисков в системе и их свойства.

Рассмотрим пример кода на платформе 1С, который опрашивает класс Win32_LogicalDisk:


objLocator = Новый COMОбъект("WbemScripting.SWbemLocator");
objWMIService = objLocator.ConnectServer(".", "root\cimv2");
colDisks = objWMIService.ExecQuery("Select * from Win32_LogicalDisk");

Для Каждого objDisk Из colDisks Цикл
    Если objDisk.DriveType = 1 Тогда
        Сообщить("Диск: " + objDisk.DeviceID + " - Тип не определен (No root directory)");
    ИначеЕсли objDisk.DriveType = 2 Тогда
        Сообщить("Диск: " + objDisk.DeviceID + " - Съемный диск (Removable drive)");
    ИначеЕсли objDisk.DriveType = 3 Тогда
        Сообщить("Диск: " + objDisk.DeviceID + " - Локальный жесткий диск (Local hard disk)");
    ИначеЕсли objDisk.DriveType = 4 Тогда
        Сообщить("Диск: " + objDisk.DeviceID + " - Сетевой диск (Network disk)");
    ИначеЕсли objDisk.DriveType = 5 Тогда
        Сообщить("Диск: " + objDisk.DeviceID + " - Оптический привод (Compact disk)");
    ИначеЕсли objDisk.DriveType = 6 Тогда
        Сообщить("Диск: " + objDisk.DeviceID + " - RAM-диск (RAM disk)");
    Иначе
        Сообщить("Диск: " + objDisk.DeviceID + " - Неизвестный тип диска");
    КонецЕсли;
КонецЦикла;

Значение свойства DriveType = 4 однозначно свидетельствует о том, что буква диска сопоставлена с удаленным сетевым ресурсом.

Способ 2. Проверка через Scripting.FileSystemObject

Обращение к WMI может занимать заметное время при инициализации COM-объекта. Если требуется быстрая проверка конкретного пути на стороне клиента Windows, более легковесным решением будет использование объекта Scripting.FileSystemObject.

Разберем по шагам реализацию универсальной функции:


Функция ЭтоУдаленныйФайл(Знач ПолныйПуть) Экспорт

    // 1. Проверяем классический UNC-путь
    Если Лев(ПолныйПуть, 2) = "\\" Тогда
        Возврат Истина;
    КонецЕсли;

    // 2. Проверяем букву диска через FileSystemObject
    Попытка
        ФСО = Новый COMОбъект("Scripting.FileSystemObject");
        ИмяДиска = ФСО.GetDriveName(ПолныйПуть);
        
        Если ЗначениеЗаполнено(ИмяДиска) Тогда
            Диск = ФСО.GetDrive(ИмяДиска);
            // DriveType = 3 соответствует сетевому диску (Remote)
            Если Диск.DriveType = 3 Тогда
                Возврат Истина;
            КонецЕсли;
        КонецЕсли;
    Исключение
        // Ошибка обращения к COM-объекту или отсутствие доступа к диску
        Возврат Ложь;
    КонецПопытки;

    Возврат Ложь;

КонецФункции

Особенности кроссплатформенности и работы под Linux

Обратите внимание: штатный объект 1С Файл предоставляет только базовые атрибуты (размер, дату модификации, признак существования) и не умеет возвращать информацию о типе накопителя.

При разработке решений, работающих на Linux-серверах или кроссплатформенных клиентах, вызовы COM-объектов (WScript, WMI, Scripting.FileSystemObject) работать не будут. В среде Linux сетевые папки (SMB, NFS) монтируются непосредственно в файловую иерархию (например, в /mnt/share). В таких случаях для надежного определения сетевого расположения анализируют файл точек монтирования /proc/mounts либо используют внешние компоненты Native API.

← На главную