Наверное, одна из самых частых проблем при работе на терминальном сервере — проблемы при печати. Заставить работать старые принтеры под новыми операционками без танцев с бубном получается крайне редко. При наличии чужих серверов без административных прав, подключение принтеров выглядит совсем печальным процессом. Отсюда родился костыль вида: pdf-принтер настроенный на сохранение в определенную папку и скрипт, который мониторит эту папку и если в ней появляется файл с расширением pdf, отправляет его на печать, а потом удаляет.
В качестве pdf-принтера ваш покорный слуга использовал PDFCreator v1.7.3 (скачать можно отсюда). Вообще, подойдет любой pdf-принтер, PDFCreator мне просто привычнее.
В PDFCreator заходим Принтер —> Настройки —> Автосохранение. Ставим галку использовать автосохранение и выбираем папку куда будем сохранять.
В скрипте указываем туже папку что и в настройках PDFCreator.
Текст VBS-скрипта:
Option Explicit : Dim objWord, objDoc, wssh, objFS, objShell, objPath, objFolder, objItem
Set wssh = CreateObject(«WScript.Shell»)
Set objFS = CreateObject(«Scripting.FileSystemObject»)
Set objPath = objFS.GetFolder(«d:\pdfprint\») ‘Папка, из которой файлы отправляются на печать
Do
PrintDelInFolder objPath
WScript.Sleep 1000 ‘ Частота проверки папки — 1 секунда
Loop
Sub PrintDelInFolder(objFolder)
For Each objItem In objFolder.Files
If StrComp(objFS.GetExtensionName(objItem.Name), «pdf», vbTextCompare) = 0 Then
With wssh
WScript.Sleep 1000
On Error Resume Next
dim f
f = Cstr(objItem.Path+».pdf»)
objFS.MoveFile objItem.Path, f
If err.number=0 then
Set objShell = CreateObject(«Shell.Application»)
objShell.ShellExecute f, «vbHide», «», «print», 0
set objShell = nothing
err.Clear
Do
WScript.Sleep 5000
objFS.DeleteFile f ,true
Loop While objFS.FileExists(f)
err.Clear
End If
On Error Goto 0
End With
End If
Next
End Sub
WScript.Quit 0
Скачать скрипт можно отсюда.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
1 2010-04-13 15:21:35
- lemuriec
- Гость
Тема: VBS: Автоматическая печать из указанной папки с последующим удалением
Доброго времени суток.
К сожалению до программирования не дорос пока, но столкнулся с одной не большой проблемой. Мне необходимо автоматически распечатывать doc и pdf файлы из указанной папки. Програмка должна мониторить состояние папки, указанную мною, и как только файл попадает в папку она должна его распечатать а затем удалить из папки. Так называемая «Очередь печати»)). Облазил сеть ничего не нашел(. Если есть возможность помогите.
P. S. В VBScript’ах не разбираюсь. Подскажите как устанавливать скрипты? Или где об этом почитать.
Заранее благодарен, форумчанин-нуб):D
2 Ответ от Lucky 2010-04-13 17:31:07 (изменено: Lucky, 2010-04-14 09:27:28)
- Lucky
- Разработчик
- Неактивен
- Рейтинг : [0|0]
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Привет! Скрипт распечатывет документы Microsoft Word (.doc) из указанной папки (в примере d:\doc\) с последующим их удалением. Сделал так, что скрипт будет каждый час спрашивать завершать ли свою работу… можете убрать это условие по вашему усмотрению.
lemuriec пишет:
В VBScript’ах не разбираюсь…
Надо будет скопировать код скрипта и сохранить его в любом текстовом редакторе в файл формата vbs (Печать.vbs к примеру).
Option Explicit : Dim objWord, objDoc, wssh, objFS, objPath, objFolder, objItem, ques
Const wdDoNotSaveChanges = 0
Const wdPromptToSaveChanges = -2
Const wdSaveChanges = -1
Set wssh = CreateObject("WScript.Shell")
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objPath = objFS.GetFolder("d:\doc\") 'Папка, из которой производится печать
Do
PrintDelInFolder objPath
WScript.Sleep 1000
If Minute(Time)=0 and Second(Time)<5 then 'условие проверки времени для вывода на экран вопроса о завершении своей работы
ques=wssh.Popup("Не желаете завершить работу скрипта автопечати документов?"&vbCrLf&"Следующий запрос будет через час...",, "Скрипт автопечати | Lucky edited", 36)
if ques=6 then WScript.Quit
WScript.Sleep 5000
End If
Loop
Sub PrintDelInFolder(objFolder)
For Each objItem In objFolder.Files
If StrComp(objFS.GetExtensionName(objItem.Name), "doc", vbTextCompare) = 0 Then
With WScript.CreateObject("Word.Application")
Set objDoc = .Documents.Open(objItem.Path, False, True, False)
objDoc.PrintOut False
.Quit
Set objDoc = Nothing
WScript.Sleep 500
objFS.DeleteFile objItem.Path ',true 'если надо удалять и доки с атрибутом "Только чтение" - уберите символ ' перед true
End With
End If
Next
End Sub
Set objWord = Nothing
WScript.Quit 0
Стремление — залог успеха
3 Ответ от lemuriec 2010-04-14 09:34:59
- lemuriec
- Гость
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Спасибо большое за старания…но возникла какая то ошибка.
«Сервер сценариев Windows/
Сценарий: C:Doc and Settings\_\Рабочий стол\print_from.vbs
Строка 24
Символ 17
Ошибка: не верно указаны путь или имя документа.
Попробуйте выполнить следующие действия:
Убедитесь что путь введен правильно
Выберите команду «Открыть» в меню файл и выберите нужный файл из списка. (\\192.168.0.1\>1I0O\…\Print.doc)
Код 800А1499
Источник MS WORD»
Возможно ли это потому что папка из которой надо печатать висит на сервере??? Что делать?
Заранее спасибо)
4 Ответ от Lucky 2010-04-14 09:49:31 (изменено: Lucky, 2010-04-14 09:52:28)
- Lucky
- Разработчик
- Неактивен
- Рейтинг : [0|0]
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
lemuriec пишет:
Возможно ли это потому что папка из которой надо печатать висит на сервере???
Скорей всего так и есть. Проверял локально — работает.
Вы покажите как вводите адрес к папке на сервере
P.S: А вы уверены что у скрипта есть права на доступ к файлам сервера? И тем более на удаление файлов оттуда…
Стремление — залог успеха
5 Ответ от lemuriec 2010-04-14 09:51:15
- lemuriec
- Гость
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Ребят я наверное наглею.. а можно туда добавить еще и Excel файлы?… Я забыл про них совсем(
Извиняюсь….заранее спасибо…
6 Ответ от lemuriec 2010-04-14 09:53:10
- lemuriec
- Гость
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Да локально работает. Адрес следующий «\\Servermon\общая\ОТДЕЛ ЭКОНОМИЧЕСКОГО АНАЛИЗА И ПРОГНОЗИРОВАНИЯ\Ochered»
7 Ответ от lemuriec 2010-04-14 09:59:21
- lemuriec
- Гость
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
У скрипта не знаю. Но на сервере нет пароля. и я спокойно сам могу удалять файлы с сервера. Может в скрипте это надо где то прописать? Я извиняюсь… я в программировании мало что понимаю)) наверное для многих мои слова кажутся смешными)) и все таки как это решить?
8 Ответ от Lucky 2010-04-14 11:33:55 (изменено: Lucky, 2010-04-14 11:35:45)
- Lucky
- Разработчик
- Неактивен
- Рейтинг : [0|0]
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
lemuriec пишет:
Адрес следующий «\\Servermon\общая\ОТДЕЛ ЭКОНОМИЧЕСКОГО АНАЛИЗА И ПРОГНОЗИРОВАНИЯ\Ochered»
Странно, но у меня аналогичное работает… Полагаю у вас в компьютерах установлены Microsoft Office…
Вот подобие на Excel, остается соединить и отшлифовать…
Option Explicit : Dim objWord, objDoc, wssh, objFS, objPath, objFolder, objItem, ques
Const wdDoNotSaveChanges = 0
Const wdPromptToSaveChanges = -2
Const wdSaveChanges = -1
Set wssh = CreateObject("WScript.Shell")
Set objFS = CreateObject("Scripting.FileSystemObject")
Set objPath = objFS.GetFolder("d:\doc\") 'Папка, из которой производится печать
Do
PrintDelInFolder objPath
WScript.Sleep 1000
If Minute(Time)=0 and Second(Time)<5 then 'условие проверки времени для вывода на экран вопроса о завершении своей работы
ques=wssh.Popup("Не желаете завершить работу скрипта автопечати документов?"&vbCrLf&"Следующий запрос будет через час...",, "Скрипт автопечати | Lucky edited", 36)
if ques=6 then WScript.Quit
WScript.Sleep 5000
End If
Loop
Sub PrintDelInFolder(objFolder)
For Each objItem In objFolder.Files
If StrComp(objFS.GetExtensionName(objItem.Name), "xls", vbTextCompare) = 0 Then
With WScript.CreateObject("Excel.Application")
Set objDoc = .Workbooks.Open(objItem.Path)
objDoc.PrintOut
.Quit
Set objDoc = Nothing
WScript.Sleep 500
objFS.DeleteFile objItem.Path ',true 'если надо удалять и доки с атрибутом "Только чтение" - уберите символ ' перед true
End With
End If
Next
End Sub
Set objWord = Nothing
WScript.Quit 0
Стремление — залог успеха
9 Ответ от lemuriec 2010-04-14 12:25:37
- lemuriec
- Гость
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Спасибо Вам большое))
Единственное с сервера не возможно распечатать(… Но я кажется придумал решение этой проблемы)
Програмка будет копировать файлы с сервера на локалку, а оттуда уже будет работать Ваш скрипт))
Ан тут можно как то выражать благодарность участнику форума?)
10 Ответ от Lucky 2010-04-14 12:37:28 (изменено: Lucky, 2010-04-14 15:18:08)
- Lucky
- Разработчик
- Неактивен
- Рейтинг : [0|0]
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Пожалуйста! Рад помочь…
lemuriec пишет:
… Но я кажется придумал решение этой проблемы)
Програмка будет копировать файлы с сервера на локалку, а оттуда уже будет работать Ваш скрипт))
Я догадался (увидел следующую вашу тему)
Стремление — залог успеха
11 Ответ от Sandril 2010-09-27 08:32:35
- Sandril
- Гость
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Очень полезный скрипт, спасибо большое!!!!
А как избавиться от постоянно всплывающего окна с вопросом о прекращении работы скрипта. Хочу чтобы он работал постоянно или прекращал работу через 3 часа, но без диалога с оператором
12 Ответ от Lucky 2010-09-27 23:23:05
- Lucky
- Разработчик
- Неактивен
- Рейтинг : [0|0]
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
1)
Sandril пишет:
Очень полезный скрипт, спасибо большое!!!!
А как избавиться от постоянно всплывающего окна с вопросом о прекращении работы скрипта. Хочу чтобы он работал постоянно…
Просто уберите в скрипте участок кода:
If Minute(Time)=0 and Second(Time)<5 then 'условие проверки времени для вывода на экран вопроса о завершении своей работы
ques=wssh.Popup("Не желаете завершить работу скрипта автопечати документов?"&vbCrLf&"Следующий запрос будет через час...",, "Скрипт автопечати | Lucky edited", 36)
if ques=6 then WScript.Quit
WScript.Sleep 5000
End If
2)
Sandril пишет:
…или прекращал работу через 3 часа, но без диалога с оператором
пункт №1 плюс замените в скрипте Do на:
Dim t1
t1=timer
Do while (timer-t1)/3600 < 3
p.s: Не забудьте убрать на первой строке определение переменной ques
Стремление — залог успеха
13 Ответ от Sandril 2010-09-28 08:43:48
- Sandril
- Гость
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Спасибо большое!!!!
Всё работает, все довольные
14 Ответ от msc_nv 2011-01-11 13:42:35 (изменено: msc_nv, 2011-01-11 13:43:33)
- msc_nv
- Гость
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
А как бы сделать чтобы программа не завершала работу? И что бы печатала, по две копии каждого файла?
15 Ответ от ChemistE 2011-11-18 04:28:35
- ChemistE
- Гость
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Подскажите пожалуйста, если кто слышит
Как подредактировать этот скрипт автоматической печати для распечатывания PDF файлов?
16 Ответ от a_lobachev 2012-02-25 09:43:14
- a_lobachev
- Гость
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
а как переделать этот скрипт под pdf файлы
17 Ответ от alexii 2012-02-25 10:22:28
- alexii
- Разработчик
- Неактивен
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Под печать PDF потребуются сторонние средства. Вы готовы к этому?
18 Ответ от Евген 2012-02-25 11:11:27
- Евген
- Разработчик
- Неактивен
- Рейтинг : [0|0]
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Раньше adobereader с ключом /p печатал файлы, сейчас нет ?
Времени не хватает…
19 Ответ от alexii 2012-02-25 13:51:50
- alexii
- Разработчик
- Неактивен
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
Печатать-то, может и печатал, а вот отследить момент завершения печати не удавалось. То ли он не закрывался в конце.
Поищите, уже было.
20 Ответ от smaharbA 2012-02-25 14:04:05
- smaharbA
- Разработчик
- Неактивен
- Рейтинг : [0|0]
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
AcroReader работает с джабоскриптом в усерспейсе
Я конечно далек от мысли… (с)
21 Ответ от workonw 2013-05-15 15:35:46
- workonw
- Участник
- Неактивен
- Рейтинг : [0|0]
Re: VBS: Автоматическая печать из указанной папки с последующим удалением
smaharbA пишет:
AcroReader работает с джабоскриптом в усерспейсе
Если не трудно, опишите пожалуйста подробнее, или укажите ссылку.
Страницы 1
Чтобы отправить ответ, вы должны войти или зарегистрироваться
Print File — это утилита Windows, которая позволяет следить за любым каталогом или папкой и автоматически печатать их по мере копирования в них файлов. Это может быть полезно, если у вас много файлов для печати. Компьютеры могут подключаться к одному и тому же каталогу, и файлы могут печататься по одному. Это приложение работает в Windows 10, Windows 8.1, Windows 7, Windows Vista и Windows XP.
Содержание
Как постоянно автопечатать файлы из папки (Windows)
Вы также можете использовать папку Dropbox или OneDrive на часах. Если вы получаете документы и изображения из нескольких источников в этой папке, файлы будут автоматически загружаться и отправляться на печать.
Особенности PrintFile
- Действует как Directory Spooler. т.е. следит за каталогом и печатает его, когда новый файл становится доступным.
- Операции Drag and Drop для пакетной печати данных.
- Программа распознает обычный текст, PostScript, Encapsulated PostScript (EPS) и двоичные форматы.
- Можно выбрать произвольный диапазон страниц для печати при печати нескольких страниц PostScript-файлов и выполнить печать n-up.
- PrintFile также может печатать файлы PostScript и EPS, созданные в системах Macintosh и UNIX.
Как сделать каталог спула для автоматической печати файлов из папки
- После установки программы перейдите к настройкам. Отметьте опцию включения спулера.
- Откройте командную строку и введите D:PrintFile>prfile32.exe /s:d:spool* .* /b:d:/spool/bkp и нажмите клавишу Enter. Обратите внимание, что я установил его на диск D). Попробуем разобраться в опциях.
- prfile32.exe — Это программа printfile, которую вы установили.
- /s:d:spool* .* — опция /s делает начало спулинга «:» (двоеточие) и путь — каталог, который будет просматриваться
- /b:d:/spool/bkp — опция /b делает резервную копию распечатанного файла в другом каталоге (d:/spool/bkp), так как по умолчанию он будет удален из спулингового каталога.
Что еще может Print File :
-
Text File: В случае простых текстовых файлов, вы можете настроить их полное игнорирование или изменение шрифта, обернуть большие файлы, добавить текст заголовка и колонтитула и т.д.
-
Поддержка PostScript: Если вам нужен автоматизированный контроль, поддерживается использование postscript. Вы также можете использовать n-Up для объединения страниц.
-
Конвертация файлов: Если вы игнорируете текстовые файлы, вы можете преобразовать их в PDF или любой другой формат с помощью программы, которая может это сделать. Вам понадобится, как заставить ее работать на уровне командной строки.
-
Создание профилей или настроек: В зависимости от типа файла, вам могут понадобиться различные настройки. В этом случае создайте несколько профилей и выберите один для автоматической печати файлов.
-
Файлы PostScript обычно можно печатать только на принтерах PostScript. Если программа преобразования, например GhostscriptОднако PrintFile может автоматически выполнить преобразование перед отправкой файла на принтер.
-
Программа также может печатать Encapsulated PostScript Files (EPS).
Если у вас возникли проблемы, загляните в файл справки, там есть более подробная информация. Скачать PrintFile
YouTube видео: Как постоянно осуществлять автоматическую печать файлов из папки (Windows)
Некоторое время назад на одном из нижегородских форумов мне была задана задача следующего содержания:
Есть конкретная задача по доработке автоматической печати документов. Имеется специальная программа, создающая файлы данных, в которых все реквизиты для печатной формы и сохраняющая их в определённом каталоге. Есть специализированная утилита, которая мониторит появление файлов в нём и готовит к печати формы документа по данным из этого файла После успешной печати файл с данными переносится в каталог напечатанных доков, а в случае с проблемой, в каталог сбойных форм. Задумка печатать не все документы подряд, а выбирая их по заранее известному признаку, т.е. будет накопление файлов с данными, а их отправку в каталог (из которого будет идти формирование и печать) должна заниматься программа автоматизации. Пока такой программой видится xStarter, как умеющая работать с несколькими заданиями одновременно и запускать по условиям готовые задачи из других задач. Уже написано и испытано правило для неё, которое для уменьшения износа, из-за лишних пусков остановок принтера, отправку на печать делает пачками по 30 документов, или по команде диспетчера принудительной отправки на печать всех накопленных документов.
Вопрос в следующем, есть ли более удобная программа, чем xStarter для решения этой задачи?
http://www.nn.ru/community/techno/tech/?do=read&thread=2472515&topic_id=56032801#56144406
Более подробно по решению этой задачи я ответил на том же форуме…
http://www.nn.ru/community/techno/tech/?do=read&thread=2504249&topic_id=56950460
Ну а здесь я позволю себе опубликовать описание простенького скрипта, написанного на скриптовом языке PowerShellб который непосредственно и решает задачу печати документов из папки…
Эта задача в основном крутится вокруг двух встроенных в WINDOWS объектов – это сама служба печати, и служба, работающая непосредственно с очередью печати (спулер). Наиболее эффективным решением любых задач работы с этими службами было бы использование методов самой WINDOWS, работающими с этими объектами. Тогда не придётся ставить сторонние прграммы, и не придётся отнимать у WINDOWS всегда нужную в таких случаях оперативную память. Понятно, что если под решение каждой задачи использовать сторонниий инструмент, то тогда нам никакй памяти не хватит. Поэтому в таких случаях рано или поздно придётся искать компромисы.
И в этом смысле я бы вновь посоветовал всем заняться изучением языка сценариев PowerShell, который является встроенным во все последние версии WINDOWS и практически этот язык призван вскоре полностью заменить собой .BAT и .CMD сценарии, используемых в ранних версиях WINDOWS.
К тому же этот язык сценариев работает напрямую практичсеки со всеми объектами WINDOWS. И часто бывает достаточно использования одного=двух командлетов, чтобы решить задачу той или иной автоматизации.
Вот например маленький скрипт на PowerShell, которым я попробовал решить задачу печати документов из нужной мне папки:
Dir c:\Doc\*.doc | Foreach-Object { Start-Process -FilePath $_.FullName –Verb Print }
В данном случае я в начале создал папку “Doc” в корневой структуре диска С, и скидываю туда все необходимые мне отпечатать в конце дня документы.
Данную строку мы проосто копируем в любой текстовый редактор, позволяющий сохранять документ в любом удобном для нас формате. Я давно активно использую редактор BRED. Жаль что автор уже давно забросил этот проект. Но редактор хороший и для простых вещей меня устраивает.
А главное, он как раз позволяет без проблем сохранить нужный мне сценарий со строкой выше в формат, который ассоциирован в WINDOWS со встроенным псевдонимом расширения PowerShewll.
В принципе то же самое можно проделать и в виндовом Блокноте. Надо просто быть повнимательнее с сохранением и смотреть, чтобы файл был сохранён именно с расширением PS1.
То есть сохряняя этот файл сценария, скопированный в текстовый редактор, я просто отказываюсь от сохранения в формате .TXT, при сохранении в строке ТИП ФАЙЛА выбираю “ВСЕ ФАЙЛЫ”, и указываю файлу своё явное расширение .PS1. Это расширение ассоциировано в WINDOWS как раз с PowerShell.
Правда напрямую это сегодня касается только компьютеров с операционной системой WINDOWS 7 или 8, а также с WINDOWS SERVER 2008 и 2012. В эти операционки PowerShell уже встроен.
А например в WINDOWS XP и в WINDOWS SERVER 2003 вначале требуется скачать отдельно и установить пакет Windows Management Framework. Пакет распространяется MICROSOFT бесплатно и качается свободно из папки MSDN у них на сайте или через ГУГЛ-сервис.
Всё! После этого можно спокойно на всех этих компах запускать любой .PowerShell скрипт, просто щёлкая на файле с расширением .PS1. При этом запустится редактор PowerShell и скрипт будет выполнен непосредственно в редакторе.
Ну либо же можно просто запустить скрипт на исполнение через командную строку или даже через альяс строки меню ВЫПОЛНИТЬ:
Например если мой скрипт сохранён в корне диска С:\ и имеет имя PrintFile.ps1, то я просто могу набрать в командной строке или в меню ВЫПОЛНИТЬ следующую команду:
powershell "С:\PrintFile.ps1"
В моём случае я эту команду просто скармливаю либо встроенному в WINDOWS шедулеру, либо в nnCron, и указываю время, когда он должен быть отработан. Там же в nnCrone могу указать и некоторые дополнительные признаки отработки этой команды по дополнительным условиям.
Всё! После этого будет выполнен скрипт и все документы с выбранным раширением ( в моём случае это расширение – .doc) из папки “С:\Doc” будут отосланы на печать. Причём в нужное мне время и только нужные мне документы.
Указав другие расширения и другие признаки в сохраняемом сценарии, я просто сохраняю его в другом файле с расширением .PS1, и настраиваю Cron на другое удобное мне время.
Это общий принцип автоматизации печати в данном случае.
К тому же в этом моём примере уже реализован принцип использования примерного признака, по которому печататься будут не все документы из этой папки, а только те, у которых расширение .doc
Вы при этом можете указать своё расширение или использовать вместо указания расширения звёздочку. В последнем случае на печать будут уходить все файлы, сохраняемые ранее в эту папку.
Ну впрочем это всего лишь пример. В реальном случае конечно скрипт будет отличаться от приведённого здесь, в нём должны будут учтены именно ваши признаки и требования, и с учётом более сложных признаков сценарий скрипта будет несколько сложнее. Не одна, а скажем, 2-3 строчки. Но всё равно это не так сложно, и если вы любите так же как и я, видеть результат как можно быстрее и сразу, то даже в изучении это интересно.
Что касается сортировки документов в спулере или в папке, то там можно написать отдельные сценарии подобного типа.
По данному типовому примеру использования языка PowerShell можно в принципе решить любую задачу автоматизации печати документов из выбранной заранее папки по любым признакам фильтрования и сортировки документов.
Удачи всем!
Время на прочтение
6 мин
Количество просмотров 38K
Иногда нужно быстро распечатать много
картинок с котиками
документов, а открывать для этого каждый файл совсем не хочется. Первым делом напрашивается использование контекстного меню проводника, но у этого способа есть свои ограничения и нюансы. Поэтому пришлось искать альтернативу. За подробностями — прошу под кат.
Анализируем ситуацию и собираем данные
Тема пакетной печати не раз освещалась в
трудах великих учёных
интернет-статьях. Например, в этой и этой.
Мы же начнем с выяснения того, какой функционал нужен конечным пользователям. В результате общения с коллегами получися такой список:
- печатать нужно только XML-файлы;
- форматирование для XML не требуется;
- на бумаге, помимо содержимого, должно быть указано и имя печатаемого файла;
- файлы должны быть отсортированы по имени, чтобы было удобно подшивать бумажные листы в архив.
Пожалуй, самым простым и очевидным видится печать из контекстного меню проводника, о чем можно почитать тут и здесь. По второй ссылке дана информация по удалению пункта «Печать» для определенных типов файлов, но сообразительный читатель легко поймет из нее, как, наоборот, можно добавить недостающее.
Но у такого способа есть, как минимум, два недостатка:
- нельзя напечатать больше 15 файлов за раз;
- файлы печатаются в случайном порядке (возможно, логика все же есть, но я ее не нашел), а не так, как они отсортированы в проводнике.
Первый недостаток легко устраним твиком реестра. Для решения второго есть рекомендации в виде танцев с бубном, но в нашей среде боги суровы и эти обряды не помогли.
Есть готовые сторонние решения (ссылки на статьи с информацией о них даны выше). Но при коммерческом использовании за эти продукты придется заплатить, к тому же всегда приятно
забить элегантный костыль и изобрести очередной велосипед
сделать что-то своими руками.
Выбираем инструмент и разрабатываем решение
Примечание. Чтобы не переводить бумагу, на этапе подготовки и тестирования скрипта удобно использовать виртуальный принтер. Меня устроил штатный Microsoft XPS Document Writer, но есть еще PDF24 Creator, doPDF, CutePDF Writer — как говорится, на вкус и цвет…
В качестве языка был выбран PowerShell. В базовой комплектации скрипт выглядит так:
Вариант 0
$FolderToPrint = "\\server\share\Folder"
$FileMask = "*.xml"
$FolderToPrint | Get-ChildItem -File -Filter $FileMask | Sort-Object Name | ForEach-Object {
Write-Output ("Печать файла `"" + $_.FullName + "`"")
Start-Process -FilePath notepad -ArgumentList ("/P `"" + $_.FullName + "`"") -Wait
}
Печать выполняется средствами штатного блокнота Windows (чтоб не простаивал без дела).
Как видно из 3-й строки, сортировка в примере происходит по имени файла (Name). Вместо этого можно взять за основу размер (Length) или дату изменения (LastWriteTime). Если вам требуется что-то более экзотичное, можно зайти сюда.
Для сортировки в обратном порядке у командлета Sort-Object есть ключ -Descending.
В этом варианте печать идет на принтер по умолчанию, и нас такое поведение устроило. Если же нужно печатать на принтер, отличный от дефолтного, у блокнота есть параметр /PT.
Соответственно, код примет следующий вид:
<...>
$PrinterName = "\\server2\Network Printer"
<...>
Start-Process -FilePath notepad -ArgumentList ("/PT `"$PrinterName`" `"" + $_.FullName + "`"") -Wait
<...>
Аналогично вместо блокнота можно поэксплуатировать любую другую программу в зависимости от того, какой формат файлов нужно печатать. Главное — чтобы она поддерживала печать через интерфейс командной строки.
Примечание. Если будете приручать Adobe Reader, имейте в виду этот старый баг. В нашем окружении он все еще проявляется, возможно, вам повезет больше. А еще есть хорошая статья, посвященная печати PDF из PowerShell.
Если же вам на выходе нужен только «голый» текст из обычного текстовика, то 5-я строка варианта 0 примет такой вид:
Get-Content $_.FullName | Out-Printer -Name $PrinterName
Для печати на дефолтный принтер параметр -Name нужно опустить.
Для нашей задачи требовалась печать файлов из нескольких расположений. Немного дополнив вариант 0, получаем
Вариант 1
$FolderToPrint = @(
"\\server1\share\Folder1",
"\\server1\share\Folder2",
"\\server1\share\Folder3"
)
$FileMask = "*.xml"
$ErrorActionPreference = "Stop"
Try {
$FolderToPrint | Get-ChildItem -File -Filter $FileMask | Sort-Object Name | ForEach-Object {
Write-Output ("Печать файла `"" + $_.FullName + "`"")
Start-Process -FilePath notepad -ArgumentList ("/P `"" + $_.FullName + "`"") -Wait
}
}
Catch {
Write-Host "При выполнении операции возникла ошибка:"
Write-Host $Error[0] -ForegroundColor Red
Read-Host "Нажмите ENTER для завершения"
}
Для приличия добавлена функция обработки исключений. И в случае, если, например, папка, из которой печатаются файлы, стала недоступной, то выполнение печати прервется и пользователю будет выведено соответствующее уведомление. Кстати, замечено, что блокнот возвращает в exit-коде 0 даже при попытке распечатать несуществующий/недоступный файл, но в GUI при этом ругается.
Опробовав вариант 1, пользователи попросили дать возможность выбора папки и конкретных файлов в ней, поэтому было добавлено немного интерактивности в виде диалогового окна выбора файлов. Так появился
Вариант 2
Add-Type -AssemblyName System.Windows.Forms | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.InitialDirectory = "\\server\share"
$OpenFileDialog.Multiselect = $True
$OpenFileDialog.Filter = "XML-файлы (*.xml)|*.xml|Все файлы (*.*)|*.*"
$OpenFileDialog.ShowHelp = $true
$OpenFileDialog.ShowDialog() | Out-Null
$FilesToPrint = $OpenFileDialog.FileNames | Sort-Object
ForEach ($FullFileName in $FilesToPrint) {
Write-Output "Печать файла `"$FullFileName`""
Start-Process -FilePath notepad -ArgumentList ("/P `"$FullFileName`"") -Wait
}
Теперь при запуске получаем привычное окно проводника Windows с удобным выбором нужных файлов:
клик
Подробнее о работе с диалоговым окном открытия файлов можно почитать в официальной документации, а кто хочет узнать больше про GUI-зацию PowerShell, легко найдет много материала в сети, есть даже онлайн-конструктор форм.
Обработка исключений во втором варианте была убрана, т.к. интерактивное информирование пользователя было отдано на откуп проводнику и блокноту.
При запуске кода из ISE диалоговое окно выбора файлов выводится на заднем плане (Ctrl+Tab в помощь), но из командной строки все работает как положено. Также обратите внимание, что свойство ShowHelp должно быть $true, чтобы обойти этот баг.
Еще хотелось бы обратить внимание на свойство InitialDirectory. Кэп подсказывает, что оно определяет путь к папке, которая будет выбрана по умолчанию при запуске скрипта. Но, учитывая, что проводник «запоминает» последнее выбранное расположение, которое было указано пользователем в диалоге выбора файлов, InitialDirectory может пригодиться только при первом запуске скрипта.
Вариант 2 полностью подошел нашим пользователям, поэтому на нем мы и остановились. Но если вам нужен вариант с
дамами и преферансом
интерактивностью и сортировкой, отличной от имени (например, по дате изменения), это тоже реализуемо. Получаем
Вариант 3
Add-Type -AssemblyName System.Windows.Forms | Out-Null
$OpenFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$OpenFileDialog.InitialDirectory = "\\server\share"
$OpenFileDialog.Multiselect = $True
$OpenFileDialog.Filter = "XML-файлы (*.xml)|*.xml|Все файлы (*.*)|*.*"
$OpenFileDialog.ShowHelp = $true
$OpenFileDialog.ShowDialog() | Out-Null
$SelectedFiles = $OpenFileDialog.FileNames
#Если ничего не выбрано, завершаем работу
If (!($SelectedFiles)) {
Break
}
#На основании полного имени выбранного файла определяем выбранную папку
$SelectedDir = (Split-Path -Parent $OpenFileDialog.FileName)
#Получаем список всех файлов в выбранной папке
$FilesToPrint = Get-ChildItem -Path $SelectedDir -Force |
#отбираем только те из них, которые были выбраны в диалоговом окне
Where-Object {$_.FullName -in $OpenFileDialog.FileNames} |
#и сортируем
Sort-Object -Property LastWriteTime
ForEach ($File in $FilesToPrint) {
$FullFileName = $File.FullName
Write-Output "Печать файла `"$FullFileName`""
Start-Process -FilePath notepad -ArgumentList ("/P `"$FullFileName`"") -Wait
}
Т.к. из объекта $OpenFileDialog нельзя напрямую извлечь такие параметры, как размер или дату создания файла, то мы с помощью командлета Get-ChildItem получаем список всех файлов в папке, выбранной пользователем, а потом оставляем только те из них, которые были выбраны пользователем, и сортируем их в нужном нам виде.
Отдаем в продакшн
Убедившись, что всё работает как надо, кладем скрипт в сетевую папку и выводим пользователям ярлык на рабочий стол.
А чтобы наш маленький беззащитный скрипт не обижали злые Execution Policies, прячем его в такую скорлупу:
powershell.exe -NoLogo -ExecutionPolicy Bypass -File "\\server\share\Scripts\BulkPrint.ps1"
клик
Или можно обернуть в теплый ламповый батник.
Среди прочего, в корпоративной среде запуску скрипта могут мешать суровые Software Restriction Policies и безжалостный AppLocker, а также другое защитное ПО, но это уже выходит за рамки статьи.
Можно добавить лоска, установив красивый значок для ярлыка. Я выбрал такой:
клик
Если пользователей нашего скрипта много, можно массово раздать ярлык с помощью предпочтений групповой политики.
Итог
Такое бывает, если выкатить без предварительного тестирования.
А у нас будет вот так:
И крамольная мысль напоследок: а что, если подумать в другом направлении и вместо всего описанного выше пообщаться с начальством и перестроить рабочий процесс?