Adding printer drivers from a print server using Windows PowerShell

Managing printer drivers in a Remote Desktop Services (formerly Terminal Services) environment can be a challenge for administrators. There are many ways to ease this challenge, including third party solutions such as ThinPrint and UniPrint. When “thick” drivers are used on the RDS servers, all printer drivers must be installed locally on every server. Citrix XenApp has a printer driver replication feature which makes it possible to distribute printer drivers from a source server to one or more destination servers in a farm.

There might be situations where none of the mentioned solutions can be used for various reason, i.e. financial costs. A common way to solve this problem is to map all printer connections from a specified print server using administrative credentials during the initial setup of each RDS server. This solves the problem, but it can be time consuming as all printers that uses the same driver is being installed. Even though the driver is already installed on the local computer, it takes some time to process each printer connection.

I recently faced this challenge, as the installation of all printer connections from a few specified print servers took 30-40 minutes using a legacy script. I then wrote an advanced function in PowerShell to make the procedure more effective. This was accomplished by installing a printer connection only for unique printer drivers.
An example: A print server has 500 shared printer objects, while there is only 10 unique printer drivers. It would make more sense to add a printer connection (in order to install the driver) to 10 printer objects rather than 500, given the time consumed by installing a printer connection.

The function is available for download from here.

Sample usage and output:

image

 

image

There is a switch option added to the function called Clean. If this parameter is specified the function will also remove all mapped printer connections for the current user.

The function doesn’tt provide any log options. However, it produces PowerShell objects, so it would be easy to pipe the output to a file.
An example on how to export the output objects to a csv-file:

image

But what about printer drivers added to the print servers after the function is run on an RDS server? One way to solve this could be adding the PowerShell function to a script-file which is set up as a scheduled task to run i.e. once a day on every RDS server.  If the scheduled task is set up using Group Policy Preferences, it will be automatically created on every new RDS server that is added later on. Beside scheduling the task to run at specified intervals, the print server administrator may also invoke the scheduled task remotely on every RDS server whenever a new print driver is added to a print server. The details on how to do this is previously described in this blog-post.

Since the function might be run several times on the same computer, it also checks if the driver to be installed is already in place on the local computer. This means that after the first run, only printer drivers added to the print server after the first run is actually installed. This makes the script more effective, and depending on the number of shared printer objects on the specified print server, it shouldn'tt run for many seconds.

Coming back to the before mentioned example (~600 printer objects, ~50 unique drivers) where it took 30-40 minutes to install printer drivers from a print server, when using the Add-PrinterDriver PowerShell function the execution ran for 4 minutes. After the first run, subsequent executions ran for  20 seconds.

Manage RDS RemoteApp with Windows PowerShell

In Windows Server 2008 R2, Remote Desktop Services (formerly Terminal Services) includes a provider for managing RDS using Windows PowerShell. You may find more information along with some examples in this article on Microsoft TechNet.

One of the many things you can manage this way is the new RemoteApp-feature introduced with Windows Server 2008. In Windows Server 2008 R2, this feature got enhanced by the addition of User Assignment and Web Single Sign-On capabilities. These new features makes it possible for more and more customers to consider RDS without additional products like Citrix. One benefit using Citrix are more flexible application-management, since an published application may be available from a new farm member without adding each application manually.

Lets look at a given example: You got a farm with 16 RDS-servers, and youre leveraging the RemoteApp-feature. For each server in the farm, you must manually set up all applications in RemoteApp-manager after theyre installed. Although there is an export/import-feature in the GUI, many customers require no manual interaction in the server provisioning process. By the addition of the new PowerShell-provider for RDS, this is now possible in RemoteApp using scripting as part of either server provisioning or Group Policy.

For the average Windows sysadmin, I imagine that managing RemoteApp using the RDS PowerShell provider might be a bit tedious. To make this a little easier Ive created a Windows PowerShell module for working with RDS RemoteApp, available from here.

This module contains the following functions:

  • Get-RDSRemoteApp
  • Export-RDSRemoteApps
  • Import-RDSRemoteApps
  • New-RDSRemoteApp
  • Remove-RDSRemoteApp

The functions let you administer the same application attributes as the graphical RemoteApp Manager:

  • Displayname
  • Alias
  • Command-line arguments
  • RD Web Access availability
  • User Assignment

 

Installing the RDSRemoteApp module

Download and unzip RDSRemoteApp.zip in the following location: %userprofile%DocumentsWindowsPowerShellModulesRDSRemoteApp

Alternatively you may save the module in any of the folders in the $Env:PSMODULEPATH variable.

Using the RDSRemoteApp module

First well have a look at the RemoteApp Manager application-list in the lab-environment:

image

Start Windows PowerShell on the RDS-server and import the module (you will need to run PowerShell with Administrative privileges):

image

Since Ive leveraged the built-in help capabilities in Windows PowerShell v2 Advanced Functions, I`ll show the usage of the functions with a few screenshots from the help:

Get-RDSRemoteApp

image

New-RDSRemoteApp

image

Remove-RDSRemoteApp

image

Export-RDSRemoteApps

image

Import-RDSRemoteApps

image

Sample usage for export/import:

image

Be aware that there are several other RDS settings that may be managed using the PowerShell provider, this module only leverages the RemoteApp functionality. If someone want to create a module for managing other aspects of RDS, feel free to include my RDSRemoteApp module. And as always, suggestions for improvements and new functionality are more than welcome.

Single Sign-On to Remote Desktop Services

 

Single sign-on is an authentication method that allows users with a domain account to log on once to a client computer by using a password, and then gain access to remote servers without being asked for their credentials again. See more details here for Windows Server 2008 and here for Windows Server 2008 R2.

On the client-side SSO are currently available for Windows XP with SP3, Windows Vista and Windows 7.

 

Configure SSO on the server-side

To configure SSO on the server-side (Windows Server 2008 Terminal Services or Windows Server 2008 R2 Remote Desktop Services), set the option “Security layer” to either “Negotiate” or “SSL (TLS 1.0)”:

image

Best practice would be to configure this in a common GPO for all Remote Desktop Services servers in the domain:

image

This setting resides under Computer Configuration->Policies->Administrative templates->Windows Components->Terminal Services->Terminal Server->Security.

 

Configure SSO on the client-side

Using a common GPO would also be the best practice to deploy the client settings needed for SSO to work.
The “Allow Delegating Default Credentials” resides under Computer Configuration->Policies->System->Credentials Delegation:

image

image

Enable “Allow Delegating Default Credentials”, press the “Show”-button and either specify the domain pre-fixed with * to allow delegation to all servers in the domain, or specify specific servers:

image 

Next, create a RDP-file and deploy this file to the client computers.
Before deploying the file, open it in a text editor, e.g. Notepad, and add the following line: enablecredsspsupport:i:1
This will enable SSO for the RDP-file.

I would also recommend to sign the RDP-file with a Code Signing certificate. This can be accomplished using the utility rdpsign.exe:

image

Sample signing:

image

When a RDP-file are signed, the following will be added to the bottom of the file:

signature:s:AQABAAEAAADBCgAAMIIKvQ……..

For Windows Vista and Windows 7 clients, the configuration would now be completed when the RDP-file are deployed.

 

For Windows XP clients the following would be necessary in addition to the steps above:
-Service Pack 3 needs to be installed
-At least version 6.0 of the Remote Desktop Client
-Turn on the CredSSP Security Provider

The steps to turn on the CredSSP Security Provider are described in this kb-article.

I would recommend deploying these registry settings using Group Policy Preferences:

image

Also the RDP-file may be deployed in the same way:

image

I`ve covered the usage of Group Policy Preferences in a previous post.

Also, SSO can be combined with Remote Desktop Services Web Access. The Remote Desktop Services Team has posted an excellent post describing how to set up SSO in RDS Web Access.