При работе в терминальном режиме (RDP) программисты 1С часто сталкиваются с задачей упрощения передачи файлов между сервером и локальным компьютером пользователя. Типичный сценарий: в базе данных хранится путь к файлу на сервере, и пользователю нужно быстро «забрать» этот файл себе на рабочий стол. Традиционный поиск файла через проводник занимает много времени, поэтому идеальным решением является программное помещение файла в буфер обмена по нажатию кнопки в 1С. После этого пользователю остается только свернуть окно RDP и нажать Ctrl+V на своем компьютере.
В этой статье мы подробно разберем, почему стандартные методы работы с текстом здесь не подходят, и изучим несколько эффективных способов реализации этой задачи.
Разберем ситуацию: многие начинающие разработчики пытаются использовать команду КопироватьФайл или утилиту clip.exe. Проанализируем, почему это не дает нужного результата:
КопироватьФайл в 1С предназначен для физического копирования файла из одного места на диске в другое. Он требует указания целевого пути (например, C:\Temp\file.txt), но буфер обмена не является папкой в файловой системе.clip.exe, встроенная в Windows, умеет работать только с текстовыми данными. Если вы попытаетесь отправить в нее файл, она запишет в буфер его содержимое (текст) или путь к нему, но не сам файловый объект.Для того чтобы операционная система поняла, что в буфере лежит именно файл, данные должны быть помещены туда в специальном формате CF_HDROP. Рассмотрим, как этого добиться.
Начиная с Windows 7 и выше, в системе присутствует оболочка PowerShell, которая обладает мощными средствами работы с буфером обмена. Командлет Set-Clipboard позволяет передавать объекты файловой системы напрямую в буфер.
Проанализируем пример кода на языке 1С, который вызывает PowerShell для решения нашей задачи:
Процедура КопироватьФайлВБуфер(ПутьКФайлу)
// Формируем команду для PowerShell.
// Параметр -Path указывает, что мы передаем именно файл, а не текст.
Команда = "powershell -ExecutionPolicy Bypass -Command ""Set-Clipboard -Path '" + ПутьКФайлу + "'""";
// Запускаем приложение в скрытом режиме
ЗапуститьПриложение(Команда, , Истина);
Сообщить("Файл успешно помещен в буфер обмена: " + ПутьКФайлу);
КонецПроцедуры
Важный нюанс: при формировании строки команды обратите внимание на кавычки. Если в пути к файлу есть пробелы, PowerShell может некорректно воспринять путь, поэтому мы обрамляем ПутьКФайлу одинарными кавычками внутри двойных.
Если ваша конфигурация работает на платформе 8.3, наиболее правильным и «чистым» с точки зрения архитектуры 1С способом будет использование механизма передачи файлов. Вместо того чтобы заставлять пользователя нажимать Ctrl+V, мы можем программно инициировать скачивание файла на его локальную машину.
Рассмотрим, как это реализовать:
&НаКлиенте
Процедура СкачатьФайлНаЛокальныйПК(ПутьНаСервере, ИмяФайла)
// Описываем, какой файл мы хотим передать
Описание = Новый ОписаниеПередаваемогоФайла(ИмяФайла, ПутьНаСервере);
МассивФайлов = Новый Массив;
МассивФайлов.Добавить(Описание);
// Вызываем диалог сохранения файла на стороне клиента
ПараметрыПолучения = Новый ПараметрыДиалогаПолученияФайлов("Выберите папку для сохранения файла");
ПолучитьФайлы(МассивФайлов, , ПараметрыПолучения, Истина);
КонецПроцедуры
Этот метод гораздо надежнее работы с буфером обмена, так как он не зависит от настроек синхронизации RDP и прав доступа к системным утилитам. Мы просто передаем поток данных с сервера на клиент.
Выясним причину, по которой иногда прибегают к методу SendKeys. Это происходит, когда нужно максимально имитировать ручной ввод. Однако, как отмечалось в обсуждении, это «костыльный» метод. Он требует, чтобы окно проводника было открыто и находилось в фокусе.
Тем не менее, проанализируем ситуацию, если вы решите использовать системный объект WScript.Shell для передачи горячих клавиш:
wsh = Новый COMОбъект("WScript.Shell");
// Имитация нажатия Ctrl+C
wsh.SendKeys("^c");
Важно: этот код сработает только в том случае, если в момент выполнения файл уже выделен в каком-либо окне. Для программного выделения файла в проводнике можно использовать команду explorer.exe /select, "путь_к_файлу", а затем посылать нажатие клавиш. Но мы рекомендуем использовать Способ 1, так как он работает в фоновом режиме и не требует открытия лишних окон.
Для глубокого понимания процесса разберем, что происходит «под капотом» Windows. Когда вы копируете файл в проводнике, ОС создает в памяти структуру DROPFILES. Она содержит список путей к файлам, разделенных нулевыми символами. Если вы программируете на низком уровне (например, используя внешние компоненты на C++ или Delphi, как показано в сообщении №19), вам необходимо выполнить следующие шаги:
GlobalAlloc.DROPFILES, указав смещение к списку файлов.OpenClipboard.CF_HDROP.Именно этот формат позволяет другим приложениям (и самой Windows) понимать, что из буфера нужно извлечь не текст «C:\file.txt», а сам объект по этому адресу.
Посмотрим на ситуацию со стороны системного администрирования. Даже если ваш код в 1С написан идеально, файл может не «долететь» до локального компьютера пользователя, если отключена синхронизация буфера в настройках RDP-клиента.
Проверьте следующие настройки:
rdpclip.exe. Если буфер перестал работать, попробуйте завершить этот процесс через диспетчер задач и запустить его заново.Использование связки 1С и PowerShell — это наиболее сбалансированное решение, которое позволяет копировать файлы в буфер без лишних диалоговых окон, обеспечивая пользователю привычный интерфейс работы через Ctrl+V.