When in accounting they replaced the printer. “We need to reconnect everyone”


If such an application in your service desk system causes a twitching eye and a drop in tone - you probably haven’t yet configured convenient centralized management of printers. It's time to fix this problem.


Rather, the article is for those who do not have this spherical corporation in a vacuum, with virtual printers, applying a pass for printing on the HP M8xx, or even Ricoh Pro 8xxx. As usual, we stock up on scripts, GPOs, and again scripts.


We collect printers in one connection point


As a first measure that makes life easier, I recommend having a print server where you can deploy all the printers in your organization. Ideally, this is a separate virtual machine, where all printers are networked and output to a separate VLAN with access only from the print server. If it is impossible to use a network printer, then in an extreme case, you can turn a computer with a USB \ LPT printer into a print server. For example, using the rawprintserver utility .


In addition to ease of maintenance, a configuration with a single print server can easily implement “knee-high” print reports by parsing the Microsoft-Windows-PrintService / Operational log. I hope that our material “ Letting Logs As We Want - Log Analysis on Windows Systems” helps with solving this problem , and as an example I will offer the following PowerShell script:


$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


The result of the script.


In addition, you can properly do the optimization of the performance of a single print server, combine printers in a cluster. In general, have fun as you like - at least monitor printers via SNMP and notify employees in advance of running out of cartridges.


Let's move on to connecting printers to users: intricate and not so good options.


We connect printers at an input


Using logon scripts is an old and proven tool, it works always and everywhere. When a user logs in, a script is triggered that connects the desired printer and sets it by default - everything is simple and stable. On cmd the script will look like:


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

You can read more about the cmd command for working with printers in the Microsoft documentation .


Vbs lovers will have to use objects already, and the printer connection will look like this:


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

Similarly, the task is solved on PowerShell:


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

You can read about the features of the Wscript.Network com-interface in the TechNet WshNetwork Object , and about managing printers using PowerShell, see the PowerShell Working with Printers documentation section .


If everything is simple with directly connecting the printer - if only the driver was on the computer - then selective connection of printers will require architectural ingenuity. I will give a couple of options that were found in the vast admin area.


Each printer has its own security group. Only she is allowed to print on the printer in its properties. Each security group has its own logon script and its own group policy with a security filter.



Need more group policies.


The option is not bad, but when you add a new printer, you have to create a new security group, a new group policy and a new script for connecting. Of course, this can be automated not without the help of our material “Immersion in Templates and Taming GPO Windows ”, but the solution still does not look the most elegant.


Another option is to create a single script that checks any attribute of the user or computer and, depending on it, connects the desired printer. The attribute may be location, description, or even membership in a security group.


The correspondence between the attribute and the printer name is either hard-coded in the body of the script, or it is written in an external data source, such as a text file or even an SQL table. This option is a little easier to maintain - in which case you need to edit only one script or an external data source.


Under the spoiler, I’ll give a variant of a similar script on 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 

Only other policies can be better policies for connecting printers.


With the advent of Group Policy Preferences or group policy preferences, it became possible to do without scripts at all. Indeed, the connection to printers can be configured in the "User Configuration - Settings - Control Panel - Printers" section.



Connect to a new or old printer.


At the same time, it is not necessary to configure policies for the number of printers in a domain using the Targeting tool on the General Settings tab. In fact, this tool resembles wmi filters in Group Policy, only it has a predefined set of options in addition to filters.



Possible targeting options.


A good option would be to configure a filter by security group. Then it will be enough to create the necessary number of security groups, configure permissions for printers on the print server and bring these printers into group policy.


When automating add-change, you can use the fact that the Group Policy preference settings themselves are located in the Group Policy folder in the Preference subfolder. For printers, this will be the Printers.xml xml file in the Printers subfolder.



The physical location of the printer settings.


If you open it, you can see that the xml structure is quite simple:


<?xml version="1.0" encoding="utf-8"?>
<Printers clsid="{1F577D12-3D1B-471e-A1B7-060317597B9C}">
<SharedPrinter clsid="{9A5E9697-9095-436d-A0EE-4D128FDFBCE5}" name="HP2055BUH2" status="HP2055BUH2" image="2" bypassErrors="1" changed="2018-03-21 13:47:25" uid="{9E6F08F9-1C6B-49EB-A985-25A722ADD9C1}">
<Properties action="U" comment="" path="\\servername\HP2055BUH2" location="" default="0" skipLocal="0" deleteAll="0" persistent="0" deleteMaps="0" port=""/>
<Filters>
<FilterGroup name="Domainname\Printer_Add_2055_Buh" localGroup="0" primaryGroup="0" userContext="1" sid="" not="0" bool="AND"/>
</Filters>
</SharedPrinter>
</Printers>

And if you want, you can carefully add / change parameters manually or with scripts. Of course, reinventing the wheel and scrubbing unwashed hands in xml is fun and entertaining, but not necessary at all - the TechNet Script Gallery already has a ready-made Add-Printer-IN-GPO script that will add printers to Group Policy with a focus on security groups.


At the end of the article I’ll tell you about one interesting way, which I somehow had to implement.


Into the piggy bank of strange connection methods - scheduled tasks


The task was received from the customer - to create a tool for automatically connecting printers to the user. At the same time, the reaction time should be minimal and no logins allowed, therefore, classic options like logon scripts and group policies were immediately dismissed.


The nuance was that users worked on terminal servers in the farm and without the farm. The goal of fiction is cunning, so I had to recall the possible options for running commands on a remote computer under different sessions - some of the options are described in our article “1000 ++ a way to run commands on a remote computer ”. The best option was with the assigned tasks.


Since I love batch files and use them when you can do without using PowerShell, I used cmd exclusively to solve the problem.


The main problem was the need to run commands to connect the printer directly in the user's session, and not knowing his password, the usual methods were not very effective. Just for this, I used the opportunity to set the username when creating the scheduled task with this command:


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

The second problem was to find the computer on which the user was working at the time of the call. I used the qwinsta utility and a list of possible computers in a text file. Of course, there are other ways - for example, to take the computer name from the Active Directory attribute or from a text file. But this procedure will require additional Logon scripts. As an example of implementation, I can advise How to: Show User's Logged On Computer Name In Active Directory .


As a result, a script appeared that takes as a parameter the name of the user and the connected printer. Next to the script, put a text file with a list of servers on which the user can work.


Full listing of the script under the spoiler.
@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 

Of course, there are companies where users themselves are able to connect to the desired printer, select it by default and not pull the IT service for this. Unfortunately, not all are so advanced.


I suggest in the comments to share how things are with network printers and their management in your organizations.