Когда в бухгалтерии заменили принтер. «Надо всем переподключить»

z3qsadwuqxsnrfftkxqd1hph8gy.jpeg


Если такая заявка в вашей системе сервис-деска вызывает дергающийся глаз и падение тонуса ― у вас наверняка еще не настроено удобное централизованное управление принтерами. Пора исправлять эту неувязочку.


Статья скорее для тех, у кого нет этого сферического корпорейта в вакууме, с виртуальными принтерами, прикладыванием пропуска для печати на HP M8xx, а то и даже Ricoh Pro 8ххх. Как обычно, запасаемся скриптами, GPO и еще раз скриптами.


Собираем принтеры в одну точку подключения

В качестве первой меры, облегчающей жизнь, рекомендую завести сервер печати, где можно развернуть все принтеры организации. В идеале это отдельная виртуальная машина, где все принтеры являются сетевыми и выведены в отдельный VLAN с доступом только с сервера печати. Если невозможно использовать сетевой принтер, то в крайнем случае можно превратить компьютер с USB\LPT принтером в принт-сервер. Например, при помощи утилиты rawprintserver.


Помимо удобства обслуживания конфигурация с единым сервером печати позволит запросто реализовать и «наколеночные» отчеты печати, разбирая журнал Microsoft-Windows-PrintService/Operational. Надеюсь, что с решением этой задачи поможет наш материал «Вертим логи как хотим ― анализ журналов в системах Windows», а в качестве примера предложу следующий скрипт PowerShell:


$events = Get-WinEvent -FilterHashtable @{LogName = "Microsoft-Windows-PrintService/Operational"; ID = 307} | foreach{
New-Object PSobject -Property @{
Time_Created = $_.TimeCreated
Document_Number = $_.Properties[0].value
Document_Name = $_.Properties[1].value
UserID = $_.Properties[2].value
Printer = $_.Properties[4].value
PagesCount = $_.Properties[7].value
}
} 
$events  | select userid, printer ,pagescount


fbvr2xmy_h3cjhv4gofjneatir8.jpeg
Результат работы скрипта.


Вдобавок, можно как следует заняться оптимизацией быстродействия единого сервера печати, объединять принтеры в кластер. В общем, развлекаться как угодно ― хотя бы мониторить принтеры по SNMP и заранее уведомлять сотрудников о заканчивающихся картриджах.


Перейдем к подключению принтеров пользователям: вариантам затейливым и не очень.


Подключаем принтеры при входе

Использование логон-скриптов ― это старое и проверенное средство, работает всегда и везде. При входе пользователя в систему срабатывает скрипт, который подключает нужный принтер и устанавливает его по умолчанию ― все просто и стабильно. На cmd скрипт будет вида:


rundll32 printui.dll,PrintUIEntry /in /n\\servername\printername /y


Подробнее про работу команды cmd для работы с принтерами можно почитать в документации Microsoft.


Любителям vbs придется уже использовать объекты, и подключение принтера будет выглядеть так:


On Error Resume Next
Set WshNetwork = CreateObject("WScript.Network")
WshNetwork.AddWindowsPrinterConnection "\\servername\printername"
WshNetwork.SetDefaultPrinter "\\servername\printername"


Аналогичным образом задача решается на PowerShell:


$net = new-object -com wscript.network
$net.AddWindowsPrinterConnection("\\servername\printername")
$net.SetDefaultPrinter("\\servername\printername")


Почитать про возможности ком-интерфейса Wscript.Network можно в материале TechNet WshNetwork Object, а про управление принтерами при помощи PowerShell ― в разделе документации PowerShell Working with Printers.


Если непосредственно с подключением принтера все просто ― лишь бы драйвер стоял на компьютере, ― то выборочное подключение принтеров потребует архитектурной смекалки. Приведу пару вариантов, которые встречались на просторах админской деятельности.


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


7ackplyfzy8eyakfnxyucwzi0_k.jpeg
Нужно больше групповых политик.


Вариант неплохой, но при добавлении нового принтера приходится создавать новую группу безопасности, новую групповую политику и новый скрипт для подключения. Конечно же, это можно автоматизировать не без помощи нашего материала «Погружение в шаблоны и приручение GPO Windows», но решение все равно выглядит далеко не самым изящным.


Другой вариант таков ― создается единый скрипт, который проверяет какой-либо атрибут пользователя или компьютера и в зависимости от него подключает нужный принтер. В качестве атрибута может выступать расположение, описание или вовсе членство в группе безопасности.


Соответствие атрибута и имени принтера или жестко задано в теле скрипта, или прописывается во внешнем источнике данных, таких как текстовый файл или даже таблица SQL. Этот вариант чуть проще в обслуживании ― в случае чего нужно править только один скрипт или внешний источник данных.


Под спойлером приведу вариант подобного скрипта на vbs.
Set WshShell = WScript.CreateObject("WScript.Shell") 
 Set objSysInfo = CreateObject("ADSystemInfo") 
 strComputer = "." 
 Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv") 
 strUserDN = objSysInfo.userName 
 Set UserObj = GetObject("LDAP://" & strUserDN) 

 'начинаем создавать массив групп безопасности текущего пользователя' 
 iGroup = 0 

 For Each GroupObj In UserObj.Groups 
     iGroup = iGroup + 1 
     Redim Preserve strArrayUserGroups(iGroup) 
     strArrayUserGroups(iGroup) = Replace(GroupObj.Name, "CN=", "") 
 Next 

 'начинаем проверку и подключение принтеров'
 For i = 1 To iGroup 
     AddPrintersByGroup strArrayUserGroups(i) 
 Next

Function AddPrintersByGroup (strGroup) 
  Set WshNetwork = CreateObject("WScript.Network")
  Select Case strGroup 

    Case "Add Printer HP2055BUH2" 
      WshNetwork.AddWindowsPrinterConnection "\\servername\HP2055BUH2"
      WshNetwork.SetDefaultPrinter "\\servername\HP2055BUH2"

    Case "Add Printer HP2055HR"
      WshNetwork.AddWindowsPrinterConnection "\\servername\HP2055HR"
      WshNetwork.SetDefaultPrinter "\\servername\HP2055HR"
...
   End Select
End Function 


Лучше политик для подключения принтеров могут быть только другие политики

С появлением Group Policy Preferences или предпочтений групповых политик стало возможным обходиться без скриптов вовсе. Действительно, подключение к принтерам можно настроить в разделе «Конфигурация пользователя ― Настройка ― Панель управления ― Принтеры».


b6pf6yqr3tvhrvzuccxeqt9sh50.jpeg
Подключение к новому или старому принтеру.


При этом не обязательно настраивать политики по количеству принтеров в домене инструментом «Нацеливание» на вкладке «Общие параметры». По сути этот инструмент напоминает wmi-фильтры в групповой политике, только у него заранее создан готовый набор опций помимо фильтров.


siysgxetbz7qzg_worwnqc7ct1q.jpeg
Возможные варианты нацеливания.


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


При автоматизации добавления-изменения можно использовать тот факт, что сами настройки предпочтения групповых политик располагаются в папке групповой политики в подпапке Preference. В случае принтеров это будет xml-файл Printers.xml в подпапке Printers.


ocd0avu1wykafmq1thbb-khqgpo.png
Физическое расположение настроек принтеров.


Если открыть его, можно увидеть, что структура xml достаточно проста:











И при желании можно аккуратно добавлять\изменять параметры вручную или скриптами. Конечно же, изобретать велосипед и лезть немытыми руками в xml весело и занимательно, но совершенно не обязательно ― в галерее скриптов TechNet уже есть готовый скрипт Add-Printer-IN-GPO, который добавит принтеры к групповой политике с нацеливанием на группы безопасности.


В завершение статьи расскажу про один занятный способ, который мне как-то раз пришлось реализовать.


В копилку странных способов подключения ― назначенные задания

От заказчика поступила задача ― создать инструмент для автоматического подключения принтеров пользователю. При этом время реакции должно быть минимально и никакие перелогины недопустимы, поэтому классические варианты вроде логон-скриптов и групповых политик сразу отмели.


Нюанс был и в том, что пользователи работали на терминальных серверах в ферме и без фермы. Голь на выдумки хитра, поэтому мне пришлось вспомнить возможные варианты запуска команд на удаленном компьютере под разными сессиями ― часть вариантов описана в нашей статье »1000++ способ запуска команд на удаленном компьютере». Лучшим оказался вариант с назначенными заданиями.


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


Основной проблемой была необходимость запускать команды на подключение принтера непосредственно в сессии пользователя, а не зная его пароля, обычные методы не очень результативны. Как раз для этого я использовал возможность задать имя пользователя при создании назначенного задания вот такой командой:


schtasks /create /S computername /SC ONCE /ST 00:00 /RU domain\username /TN taskname /tr "rundll32 printui.dll,PrintUIEntry /in /nPrintername" 


Второй проблемой было найти компьютер, на котором пользователь работает в момент обращения. Я использовал утилиту qwinsta и список возможных компьютеров в текстовом файле. Разумеется, есть и другие способы ― например, брать имя компьютера из атрибута Active Directory или из текстового файла. Но эта процедура потребует дополнительных Logon-скриптов. В качестве примера реализации могу посоветовать материал How to: Show User’s Logged On Computer Name In Active Directory.


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


Полный листинг скрипта под спойлером.
@echo off 
rem На каждом сервере из списка...
for /F  %%i in (servers.txt) do ( 
rem Ищем нужного пользователя
qwinsta /SERVER %%i | find "%1" && call :subroutine %%i %1 %2 
) 

GOTO :EOF 
:subroutine 
rem Cоздаем назначенное задание
schtasks /create /S %1 /SC ONCE /ST 00:00 /RU domain\%2 /TN printer_%2 /tr "rundll32 printui.dll,PrintUIEntry /in /n%3" 
rem Запускаем задание
schtasks /run /S %1 /TN printer_%2 
rem Удаляем задание
schtasks /delete /S %1 /TN printer_%2 /F 

GOTO :EOF 


Конечно же, есть компании, где пользователи сами в состоянии подключиться к нужному принтеру, выбрать его по умолчанию и не дергать для этого IT-службу. К сожалению, не все такие продвинутые.


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

© Habrahabr.ru