Здравствуйте уважаемые читатели. Эта небольшая статья больше шпаргалка для меня, но, надеюсь, она будет полезна и другим. Всем, кто проявит интерес к статье буду признателен, особенно тем, кто укажет на недочеты. Жду ваши комментарии.
Итак начнем. Задача, которую пытались решить — это установка принтеров на терминальные серверы (нынче серверы узла сеансов) фермы. Было несколько путей:
установка с помощью групповых политик
установка скриптом
установка вручную
Установка вручную — конечно, самый простой путь, но если серверов несколько, то вероятность ошибки велика, да и установка вручную — это скучно. Нужна была автоматизация, поэтому сначала выбрал групповые политики — разворачивание принтера на компьютер (на rdsh).
Выбрал установку на компьютер, потому что AD, которое мне досталось по сути не имело структуры — все пользователи размещались в одном OU. Чтобы навести порядок в AD и распределить пользователей на OU, которые соответствуют либо структуре здания либо штатному расписанию потребуется много времени.
В результате использования GPO выявил следующие нюансы:
драйверы принтеров не устанавливаются автоматически или это происходит долго;
даже если установить драйверы принтера на rdsh, то установка принтера через gpo происходит только после перезагрузки сервера;
после входа пользователя на сервер — список принтеров пуст примерно минут пять бывает больше;
принтеры очень часто не отображаются в панели управления, но отображаются в диалоговом окне печати, например в блокноте. В оснастке управления печатью развернутые принтеры не отображаются;
При удалении принтера из групповой политики принтер частенько не удаляется сразу, даже после gpupdate force.
Самое критичное — это установка принтера только после перезагрузки — довольно неприятная ситуация, когда необходимо выкинуть с терминала 50 пользователей. Поэтому начал смотреть в сторону скрипта на Powershell.
Организацию работы по установке принтера предполагал такой: принтер устанавливается вручную на сервер печати, затем запускается скрипт, который устанавливает этот принтер на все терминальные серверы фермы, с такими же настройками что и на сервере печати.

В результате сбора информации нашел хорошую статью про PrintBRM - Отказоустойчивый сервер печати на базе Windows, благодарю автора - информация была полезна. Испытал, метод рабочий, но хотелось больше контроля над алгоритмом установки, поэтому использовал Powershell.

Сам скрипт:
$driversFile= "\\storage\printDrivers\drivers.txt"
$printersFile= "\\storage\printDrivers\printers.txt"
$ACLfolder = "\\storage\printDrivers\acl\"
$csvfile= "\\storage\printDrivers\printers.csv"
$folderDrivers= "\\storage\printDrivers\drivers\"
$terminals = @("tspd-01", "tspd-02", "its-01", "its-02")
$exportFlag=0
#удаляем файл списка названий драйверов
if(Test-Path $ACLfolder){Remove-Item -Path $ACLfolder -Recurse}
if(Test-Path $driversFile){Remove-Item -Path $driversFile}
if(Test-Path $printersFile){Remove-Item -Path $printersFile}
if(Test-Path $csvfile){Remove-Item -Path $csvfile}
Start-Sleep -Seconds 5
#формируем список названий драйверов
$drivers=Get-PrinterDriver | select Name | where {$_.Name -notlike "*Microsoft*" -and $_.Name -notlike "Remote*"}
foreach ($driver in $drivers) {
write $driver.Name | out-file $driversFile -Append
}
#формируем список принтеров
$printers = get-printer | where {$_.Name -notlike "*Microsoft*" -and $_.Name -notlike "Remote*"}
#создаем директорию для ACL
Mkdir $ACLfolder
foreach($printer in $printers){
Write $printer.Name | out-file $printersFile -Append
#экспортируем ACL принтера в текстовый файл
$aclfile=$ACLfolder+$printer.Name+".txt"
(Get-Printer $printer.Name -Full).PermissionSDDL | Out-File $aclfile
}
#формируем csv файл с информацией о принтере
get-printer | where {$_.Name -notlike "*Microsoft*" -and $_.Name -notlike "Remote*"} |Export-CSV $csvfile -NoTypeInformation -Encoding UTF8
#функция экспорта драйверов
function ExportDrivers($folderDrivers){
#очищаем папку с драйверами
if(Test-Path $folderDrivers){Remove-Item -Path $folderDrivers -Recurse}
#получаем список драйверов принтеров
$PrintDriver = Get-WindowsDriver -Online | where {($_.ClassName -like "Printer")}
foreach ($print in $PrintDriver){
write $print
#Записываем название драйверов НЕ от микрософта
if($print.ProviderName -ne "Microsoft"){
#Создаем имя папки
$folderName=($folderDrivers + $print.Driver).replace('.inf','')
write $folderName
#Создаем папку
Mkdir $folderName
#экспортируем драйвера принтеров в папку
pnputil.exe /export-driver $print.Driver $folderName
}
}
}
#Запуск экспорта
if($exportFlag -eq 1){ExportDrivers -folderDrivers $folderDrivers}
Write "_____________________"
$pass = "Morkovka10"
$us="Domain\mylogin"
$password = ConvertTo-SecureString -String $pass -AsPlainText -Force
$cred= New-Object System.Management.Automation.PSCredential ($us, $password )
#Запуск удаленной сесии
foreach($server in $terminals){
$s = New-PSSession -computerName $server -authentication CredSSP -credential $cred
Invoke-Command -Session $s -Scriptblock {
#проброс перемнных в сессию
$csvfile=$using:csvfile
$ACLfolder= $using:ACLfolder
$folderDrivers=$using:folderDrivers
$driversFile=$using:driversFile
$h = hostname
write "____________________________________ $h ________________________________________________________________________"
#устанавливаем драйвера в хранилище драйверов
write "install drivers!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
$folderDrivers=$folderDrivers+"*.inf"
pnputil.exe /add-driver $folderDrivers /subdirs /install
write "install drivers!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
#добавляем отсутствующие драйвера
write "_______________________________"
Write "добавляем отсутствующие драйвера принтеров из хранилища драйверов"
$drivers = Get-Content -Path $driversFile
foreach ($driver in $drivers){
if((Get-PrinterDriver -Name $driver).Count -eq 0){
Add-PrinterDriver -Name $driver
}
}
write "_______________________________"
#Получаем массив объектов - список принтеров на принтсервере из csv
$printers = $printers =Import-CSV -Path $csvfile
#Получаем массив локальных принтеров
$localPrinters = get-printer -Full | where {$_.Name -notlike "*Microsoft*" -and $_.Name -notlike "Remote*"}
#удаляем локальные принтеры которых нет на принтсервере
foreach ($localP in $localPrinters){
$match = $printers -match $localP.Name
if($match.Count -eq 0){
$pname=$localP.Name
write "REMOVE $pname - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"
Remove-Printer -Name $localP.Name
}
}
Foreach($p in $printers){
write $p.Name
write $p.DriverName
write $p.PortName
$aclfile=$ACLfolder+$p.Name+".txt"
$perms = Get-Content -Path $aclfile
if((Get-Printer -Name $p.Name).Count -ne 0){
#синхронизируем ACL
Set-Printer $p.Name -PermissionSDDL $perms
#Получаем локальный принтер
$localprinter= Get-Printer -Name $p.Name
#Проверяем порт
if($localprinter.PortName -ne $p.PortName){
write "порт НЕ совпадает"
#Добавляем порт если его нет
if((Get-PrinterPort -Name $p.PortName).Count -eq 0){
Add-PrinterPort -Name $p.PortName -PrinterHostAddress $p.PortName
}
#Добавляем порт принтеру
Set-Printer -Name $p.Name -PortName $p.PortName
}else{write "порт совпадает"}
#Проверяем драйвер
if($localprinter.DriverName -ne $p.DriverName){
Set-Printer -Name $p.Name -DriverName $p.DriverName
}
} else {
#Добавляем порт
if((Get-PrinterPort -Name $p.Name).Count -eq 0){
Add-PrinterPort -Name $p.PortName -PrinterHostAddress $p.PortName
}
#Добавляем принтер
Add-Printer -Name $p.Name -DriverName $p.DriverName -PortName $p.PortName
#Добавляем ACL
Set-Printer $p.Name -PermissionSDDL $perms
}
}
}
}
Скорость работы скрипта зависит от количества принтеров, которые необходимо установить. Попытался максимально понятно писать комментарии к скрипту.
В результате мы получили:
удаленную установку принтеров на терминальные серверы без необходимости их перезагрузки;
единый сервер администрирования печати — сервер‑печати, который является эталонным — именно с него копируются все настройки устанавливаемых принтеров;
простой метод развертывания принтеров, поэтому его можно передать специалистам службы поддержки — установил принтер на сервер печати, настроил права и затем запустил скрипт — все просто!
Сервер печати — занимает мало места (в виде ВМ), поэтому можно быстро и легко его бекапить каждый день, поэтому не страшно, если техподдержка начудит — его быстро можно восстановить.
Задачка решена, способ конечно немного велосипедоизобретательный, но рабочий. Жду Ваших комментарий, делитесь опытом! Всем Добра!