Failover Windows based print server
- Tutorial

This admin can sleep only when he has everything backed up, monitored and duplicated.
It so happened that I mainly use Microsoft products in my work and I can say that the company is serious about backing up its services: Active Directory, Exchange DAG, SQL Always On, DFSR, etc. As elsewhere, there are both very elegant and successful implementations, as well as obviously uncomfortable and heavy ones. There is also a solution for the print service, but Hyper-V based clustering is required for it. And I wanted a simple out-of-box solution that does not require additional finance. Windows 2012 R2 was taken as a basis, but most likely the same scheme will work without any problems on any server versions starting from Windows 2008, and even client OS from Vista and higher (hello lovers to save the budget!). Who cares - I ask under the cat.
DisclaimerIn order to respect the work of the Indians. Since the audience of Habr is mostly Russian-speaking and it is easier for novice admins, the examples use the Russian version of the Windows interface. Links, where possible, also lead to Russian-language resources.
Some theory
Whoever doesn’t like theory and wants to quickly click the mouse and keyboard, can immediately move on to the next part.
As mentioned above, the official recommendation today is a solution using clustering and virtualization Hyper-V. Also, nothing prevents to provide fault tolerance of the print service at the level of virtualization, and not necessarily Hyper-V, but such solutions cost money.
I really wanted something similar to DHCP Failover , but for the role of the print server.
On the Internet in general and in particular, nothing suitable was found - and I had to invent it myself.
The essence of the idea in one paragraph
The solution described below is based on the use of the BrintBrm utility, included in the standard Windows distribution and replaced by printmig .
The backup server works in standby mode and synchronizes the settings with the main server with the specified server using this utility. For client machines in DNS, a CNAME with a small TTL is created that refers to the main server. In the event of a primary server crash, the administrator rules CNAME, switching clients to the backup server. That's all.
If the topic is interesting and I want to get acquainted with the cones already stuffed with me and ways to bypass the rake, please follow this further.
Before you begin, or what you need to know about PrintBrm
So, what is it, this utility PrintBrm, the main purpose of which is to serve the print server?
- Well maintained. It has a GUI-embodiment, which is called transfer printer ( Print Migration ) and can be launched from the tooling management seal . The GUI option is less functional and has problems with port migration.
- Attentive. By default, it processes the print server's ACL. In other words, if you allow printing \\ printserver \ printer1 to a printer only to employees who are members of the AD Accounting group , then this restriction will be taken into account by import / export. Or will not be, if you put the key -NOACL . In this case, the ACL of the print server itself is not processed regardless of the key.
- Capricious. At the time of importing the settings from the file, the target server must have at least one shared printer, otherwise you will get an error.
- Gentle. Lost by seeing spaces in the file path. At the sight of quotes framing such a path, it grieves and gives an error 0x8007007b.
- Modest. If, when trying to export settings, the specified file already exists, it cannot overwrite it, is embarrassed to ask, and also ends with an error.
- Mysterious. Always returns an exit code of 0 . It turns out the perfect program.
- Prone to meditation. May hang at the stage of 100% minutes for 5, and sometimes more. But then it comes to its senses and quits (unless, of course, you have enough patience not to press Ctrl + C).
- Sudden and contradictory. Maybe make these surprises .
- Clever. May reassign source drivers to others. For example, using an XML file, you can specify that all HP Universal Printing PCL 5 drivers in the saved file on the target server need to be reassigned to HP Universal Printing PCL 6. I haven’t used it in practice, but it can be useful for someone.
- Willful. I could not use it to transfer settings between domains without trust, even with the -NOACL switch. Either not able in principle, or my magic is not strong enough.
- You can get acquainted closer here and here , but for those brave people who do not hesitate to ask directly, is there a key /?
I admit that I undeservedly bypassed some features. Perhaps in Windows 10/2016 she began to behave differently. If there is information, please share.
Environment preparation
It is assumed that you have already deployed Active Directory and you know at least 3 ways to disable it and at least 2 of them have been tested in practice.
Some lyrics
Отступая от темы статьи, замечу, что мне нравится порядок, и я за то, чтобы на каждом сетевом принтере и МФУ была наклейка, соответствующая его сетевому имени. Это упрощает работу сотрудников ИТ, когда они пытаются выяснить у пользователя, на каком именно принтере фото котиков важные аналитические отчеты печатаются в ядовито-кислотных тонах вместо нежно-фисташковых. Клеить такие наклейки лучше на дно принтера, чтобы было всем было интереснее и веселее.
Также мне нравится, когда каждый сетевой принтер прописан во внутренней DNS-зоне. С этой задачей легко справится DHCP-сервер на базе Windows.
К примеру, имя принтера может быть формата msk-prn001 или sale-printer023, причем имена портов для этих принтеров на принт-сервере названы точно так же. Но это лично мои предпочтения, готов выслушать возражения в комментариях.
Также мне нравится, когда каждый сетевой принтер прописан во внутренней DNS-зоне. С этой задачей легко справится DHCP-сервер на базе Windows.
К примеру, имя принтера может быть формата msk-prn001 или sale-printer023, причем имена портов для этих принтеров на принт-сервере названы точно так же. Но это лично мои предпочтения, готов выслушать возражения в комментариях.
We will assume that all printers are networked and are available for printing from the main and backup print servers. Let these servers be called prn-srv01 and prn-srv02 respectively.
As a print server, suitable domain machines on a Windows Server are not lower than 2008. In principle, suitable client OS, starting with Vista, if you really really want to save. The example uses Windows 2012 R2. Before setting up, it is highly recommended to install all necessary operating system updates both on servers and client machines.
Of course, you yourself understand, but the cap still needs to pay attention: if the print servers are virtual, then they must be distributed to different physical servers, otherwise our failover will turn into just fail.
A print server role should be added to prn-srv01 and prn-srv02 . It is more convenient for me to use the PowerShell cmdlet for this:
Install-WindowsFeature Print-Services
Also on the print servers, the registry tweak should be applied, which fixes the error 0 × 00000709 when the client machines access the print server using CNAME. You can do this with the command from the article at the link above:
reg add HKLM\SYSTEM\CurrentControlSet\Control\Print /v DnsOnWire /t REG_DWORD /d 1
After applying the command, you need to restart the Print Manager service .
I recommend to allocate a separate OU for print servers and distribute this setting using GPP .
Run the DNS snap-in on the domain controller and enable advanced mapping:
cry

Extended mapping is needed to be able to set the TTL for the entries being created.
In DNS, we create a CNAME print entry that references prn-srv01 with a 5-minute TTL value:
cry

cry

This name must be used by client machines to connect to the print server. Those. the client will connect to the addresses \\ print \ printer01, \\ print \ printer02, etc.
The smaller the TTL value, the more often customers will update the record and the faster they will “understand” that they need to switch to another print server. 5 minutes is enough for me.
If you set too low a value, you generate DNS traffic in your network,
Alternative way to add CNAME records using PowerShell: (Of course, we change lab.net to your contoso.local or whatever it is)
Import-Module DnsServer
Add-DnsServerResourceRecordCName -Name "print" -HostNameAlias "prn-srv01.lab.net" -ZoneName "lab.net" -TimeToLive 00:05:00
It should be noted that if you have several AD sites, then updating the DNS records in all locations will take longer due to intersite replication. You can force a process with the repadmin / syncall command .
Using Group Policy, we allow ordinary users to install drivers from a print server. How to do this, is written in detail here .
Create a service account in AD (I called it svc-printsync) with an unlimited password:
cry

According to the requirements of PrintBrm, this account must have full rights to the print server, so we add it to the
Configure the first server
If all the necessary printers on the main printer have already been added, then you can go directly to the section on setting up a second server.
Using the Print Management snap-in, we add the necessary printers to the server:
cry

The driver installation wizard will start. It is intuitive, then you will understand. I will pay only attention to the moment with digit capacity.
Since Windows 2012R2 comes only in x64 version, then the drivers must also be x64. If clients with x86 versions of Windows will connect to the print server, do not forget to check the appropriate box:
cry

Some driver kits contain a common inf file for both x86 and x64 systems, while others have a split.
Some more lyrics
Многие драйверы поставляются в виде инсталлятора, но, учитывая, что эти инсталляторы ставят вместе с драйверами много всякого мусора, я стараюсь следовать принципу “необходимо и достаточно” и добавлять драйверы вручную, как описано выше.
Также в целях единообразия я по максимуму стремлюсь использовать Universal-вариант драйверов (есть практически у всех нормальных вендоров). Но с ним иногда могут быть проблемы. Так, однажды встретил баг в одной из версий HP Universal Printing PCL 6, при котором PDF-документ через EasyPrint в RDP-сеансе печатался зеркально слева направо.
Можно ещё посмотреть в сторону v4-драйверов.
Также в целях единообразия я по максимуму стремлюсь использовать Universal-вариант драйверов (есть практически у всех нормальных вендоров). Но с ним иногда могут быть проблемы. Так, однажды встретил баг в одной из версий HP Universal Printing PCL 6, при котором PDF-документ через EasyPrint в RDP-сеансе печатался зеркально слева направо.
Можно ещё посмотреть в сторону v4-драйверов.
When all necessary drivers are added, we will be engaged in ports and printers. You can add them manually from the same snap-in, but I recommend creating a CSV file in Excel and feeding it to the PowerShell script. Of course, nothing prevents you from using any other spreadsheet editor or notepad instead of Excel. The main thing is that the separator and the encoding specified in the script match the separator and the encoding in the CSV file.
Also note that the driver name in the CSV file should be exactly the same as it is specified in the Print Management snap-in .
Copy-paste to help

Sample CSV file

Although I wrote above that I like when all printers have unified network names, in the example (the Printer Address field ) a vinaigrette from IP addresses and names is used in case the order in your network is
Save this table in CSV format:
cry
Примечание. Несмотря на то, что в поле “Тип файла” в качестве разделителей указаны запятые, у меня Excel разделителем сделал точку с запятой. Наверно, чтобы было интереснее и веселее.

Примечание. Несмотря на то, что в поле “Тип файла” в качестве разделителей указаны запятые, у меня Excel разделителем сделал точку с запятой. Наверно, чтобы было интереснее и веселее.
But the script itself:
CreatePrintersFromCsv.ps1
#Откуда будем загружать данные
$InputFile = 'C:\Scripts\Printers.csv'#Разделитель и кодировка должны соответствовать формату CSV-файла
$Printers = (Import-Csv $InputFile -Delimiter ";" -Encoding Default)
#Все указанные в файле драйверы должны присутствовать на целевом сервереForEach ($Printer in $Printers) {
#Текст должен соответствовать заголовкам столбцов в файле
$PrinterName = $Printer.'Имя принтера'
$ShareName = $Printer.'Имя общего ресурса'
$DriverName = $Printer.'Имя драйвера'
$PrinterAddr = $Printer.'Адрес принтера'
$Comment = $Printer.'Комментарии'
$Location = $Printer.'Размещение'#Добавляем порт
Add-PrinterPort -Name $PrinterAddr -PrinterHostAddress $PrinterAddr -SNMP 1 -SNMPCommunity 'public'#Добавляем принтер
Add-Printer -Name $PrinterName -DriverName $DriverName -PortName $PrinterAddr -Comment $Comment -Location $Location
#и расшариваем его
Set-Printer -Name $PrinterName -Shared $True -Published $False -ShareName $ShareName
}
If a tab character is used as a delimiter in your CSV, then in the script you need to set -Delimiter "` t "
Note that if during the operation of the script any printer will not be accessible from the server, then adding it to the print server will take longer ( 2-3 minutes instead of several seconds)
The result of the script:
cry

To make sure that everything works at this stage, we add a shared printer from the main print server to any of the client machines using the previously created CNAME (for example, \\ print \ printer01), and try to print something on it.
We configure the second server
Un artista copia, un gran artista roba (Pablo Picasso)
Our prn-srv02 has not yet reached the level of gran artista, so we restrict ourselves to copying.
done with a flick of the wrist
Create a simple synchronization script. I prefer PowerShell, but nobody forbids to make a warm tube batch file.
PrintSync.ps1
#Путь к утилите PrintBrm
$ProgramPath = 'C:\Windows\System32\Spool\Tools\PrintBrm.exe'#Основной и резервный серверы
$SourceServer = 'prn-srv01'
$DestServer = 'prn-srv02'#Файл, куда выгружаем настройки. Путь не должен содержать пробелы, т.к. утилита PrintBrm не понимает кавычки в пути файла
$ConfigFilePath = 'C:\Scripts\prn-config.printerExport'#Экспортируем принтеры в файл
$Arguments = "-s $SourceServer -f $ConfigFilePath -b"
Start-process $ProgramPath -ArgumentList $Arguments -Wait -PassThru
#Импортируем принтеры из файла
$Arguments = "-s $DestServer -f $ConfigFilePath -r -o force"
Start-process $ProgramPath -ArgumentList $Arguments -Wait -PassThru
#Прибираемся за собой
Del $ConfigFilePath
Put the script in a secluded place (in the example it's C: \ Scripts ) and create a task in the Scheduler.
We will run from under the previously created svc-printsync account with the highest rights:
cry

Determine the frequency of execution for themselves. I have enough time per day:
cry

On the Actions tab, we create a new PowerShell launch action:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
As arguments, set the path to the script with the following parameters:
C:\Scripts\PrintSync.ps1 -NonInteractive -WindowStyle Hidden -ExecutionPolicy Bypass
cry

The remaining parameters of the task on the tabs Conditions and Parameters are left as default.
When you save the task, you will be prompted for a password for the svc-printsync account . You haven't forgotten it, have you? If you have already forgotten (the article is a long one), then
Note
Задание не обязательно должно выполняться на резервном принт-сервере. Если у вас есть отдельный сервер для запуска регламентных процедур, можете создать задачу на нем. При этом у учётной записи svc-printsync должно быть право на вход в качестве пакетного задания на этом сервере. По умолчанию такое право есть у локальной группы Операторы архива (Backup Operators), и если в вашей среде это не изменено, то достаточно включить сервисную учётную запись в группу операторов архива того сервера, на котором будет работать задание.
The first time we start the task manually and wait for it to complete.
For my zoo, where there are about 50 printers of different types, both endangered and recently withdrawn, the synchronization procedure takes about 10 minutes. The file weighs almost 1GB.
To speed up the import / export process, you can use the -NOBIN switch , which is responsible for copying drivers. It makes sense when the park of printers consists of the same models and the necessary drivers are installed on all servers.
After completion, launch the Event Viewer snap- in , go to the Applications and Services Logs section , open the Microsoft \ Microsoft \ PrintBRM \ Administrator log and analyze it for errors and warnings.
I came across with codes 20, 22, 80 and 81. For example,
such

As is clear from the text, there was a problem when transferring a specific driver. Looking through the magazine, we compile a list of problem drivers and put them on the backup server with our own hands, or replace them with others who are not averse to traveling. I only had problems with HP, Kyocera and Konica Minolta, for drivers from other manufacturers there were no errors (maybe because they are better, and maybe because we simply don’t have them).
As a result, you need to achieve the same list of printers on the main and backup servers and the absence of errors and warnings in the logs.
Switch to reserve
cry

After a while (what did you put in the TTL?), The
Come back
If during the restoration of the main server on the backup there were configuration changes that need to be saved, run the synchronization in the other direction. To do this, in the above PrintSync.ps1 script, swap the values of the $ SourceServer and $ DestServer variables . After the transfer of changes, do not forget to return these values back, otherwise all changes in the configuration of printers on prn-srv01 will be mercilessly swept away every night by the evil will of fate.
In the DNS snap-in, we set the print value for the CNAME record to the end node value prn-srv01 - and everything returns to normal.
What is the result?
Stormy applause of the leadership, throwing up an administrator on hand, a salary increase (the author of the article is an honest 10% of the increase) ...
Well, a few thoughts in the direction of further beauty.
Unfortunately, there are not enough miracles at all, and this solution is not a full-fledged failover. If at the time of the collapse of the main print server there are non-empty print queues, then their contents most likely will sink into oblivion and someone will have to repeat sending to print.
But it will be very convenient to be transparent for users to perform routine maintenance of print servers.
You follow the recommendations of Microsoft?

Fans of automation can go further and create a script that receives the names of servers with a synchronization interval at the entrance and does the rest of the settings itself: creates a service account if necessary, a task in the scheduler, etc.
Monitoring gurus will add monitoring of the synchronization task and errors in the logs.
Fans of digging deeper can think of two-way synchronization in the spirit of AD replication with time tracking changes for each printer. PrintBrm will not help here, but nobody has canceled PowerShell!
Cherry on the cake will automatically install printers on client machines using GPP targeting the AD group. We add the user to the group - and the desired printer arrives. True, this is another story that goes beyond the article.
I hope for someone my publication will be useful. I wish everyone a smaller glitch and wait for questions and suggestions in the comments.
Only registered users can participate in the survey. Sign in , please.