What about Printer Drivers

What about Printer Drivers

After reading a question on the Technet community about how to deploy printers with a printer driver to Azure Ad joined devices, I realized I only created a blog about the wonderful Microsoft Universal Cloud Print solution! So here we go!

I will divide this blog into multiple Parts/options to deploy your printers.

  1. Introduction
  2. Installing Printers and Drivers with the PnPutil
  3. Installing All Printers and Drivers with Printbrm.exe
  4. Install HP Printers with the Universal Printer Driver.
  5. Install Printer Drivers with PrnDrvr.vbs
  6. The Execution Policy

1. Introduction

Of course, transforming to a modern workplace will also mean you need to do something with your existing Print solution. One of the best solutions would probably be to start using the Microsoft Universal Print solution. In one of my first blogs I was telling you how you could configure this and what my wishes were for this fantastic product:

But what, if you don’t have the possibility to migrate your printers to this solution right away? I know how it works! A customer calls and he/she suddenly wants to deploy a new printer to all of their devices and they don’t want to hear they need to move their printers to cloud-based solutions first. So what can you do? Telling the customer: No No?

The best option would be to install the printer first and arrange a meeting with the customer to urge them to move their printers to a cloud-based solution.

So for now the printer has to be installed. Are we letting the customer do this manually as I showed you in this blog? P.S I am also showing you how to solve the Printer Nightmare issue in this blog

Or are we going to make sure the Printer and drivers are installed without any user interaction?

2.Installing Printers and Drivers with PnpUtil

In this option, we are going to use the PnPutil tool to “Stage” the Printer Driver to the Windows Driver Store. The driver needs to be “staged” (Copied to the Driver Store AKA /Add-driver) before we can make use of it to install the printer driver (Add-PrinterDriver). After we have staged and installed the required drivers, we can install the printer itself!

Let start with downloading the driver first, so we can begin!

Step 1: Download the driver

In this example, I want to deploy a Toshiba printer, so I downloaded the Universal printer drivers from Toshiba first and placed them inside the folder c:\intune\toshiba

After the zip file finished downloading, I extracted the whole zip file to start searching for the inf file (installation file) After I found the correct folder with the inf file in it, I copied it to the whole folder to c:\intune\toshiba\

To be 100% sure I had all the files needed, I moved this whole folder inc all the content to the c:\intune\toshiba root folder. When you don’t want to copy all of the content, you could check out the inf file and search for: “SourceDisksNames

As shown above, it will tell you which additional files you need.

Please note, you always need to have the *.Inf file (installation file with driver information) and the *.cat file (security catalog to determine if it’s a valid signed driver). So next to the inf and cat file you will need that *.cab file

I renamed the folder that I copied earlier, to one with some fewer characters. I decided to just rename the folder to drivers. I guess that name says it all and it’s way shorter..

Step 2: Creating the Install script

Before we can create the installation script we need to have some additional information. So again, open the *.inf file in the folder you extracted earlier.

We need to have the exact Printer Driver Name. As shown above, it was an easy find! So let’s build the install.ps1 PowerShell script

Install.ps1

###############################
#TOSHIBA Universal Printer 2  #
################################
$PSScriptRoot = Split-Path -Parent -Path $MyInvocation.MyCommand.Definition
$drivername = "TOSHIBA Universal Printer"
$portName = "IP_192.168.40.251"
$PortAddress = "IP_192.168.40.251"

###################
#Staging Drivers   #
###################
C:\Windows\SysNative\pnputil.exe /add-driver "$psscriptroot\Drivers\eSf6u.inf" /install

#######################
#Installing Drivers   #
#######################

Add-PrinterDriver -Name $drivername

##########################################################
#Install Printerport | check if the port already exist   #
##########################################################
$checkPortExists = Get-Printerport -Name $portname -ErrorAction SilentlyContinue
if (-not $checkPortExists) 
{
Add-PrinterPort -name $portName -PrinterHostAddress $PortAddress
}

####################################
#Check if PrinterDriver Exists     #
####################################
$printDriverExists = Get-PrinterDriver -name $DriverName -ErrorAction SilentlyContinue


##################
#Install Printer #
##################
if ($printDriverExists)
{
Add-Printer -Name "Toshiba HoofdKantoor" -PortName $portName -DriverName $DriverName
}
else
{
Write-Warning "Printer Driver not installed"
}



SLEEP 360

Did you notice the part where I am mentioning Sysnative instead of System32? If you want to read all about this, please read this blog:

And of course, we need to specify a nice uninstall.ps1, that’s going to be a lot easier!

Uninstall.ps1

remove-printerPort -Name "192.168.40.251" 
SLEEP 360
remove-printers "Toshiba Hoofdkantoor"

3. Creating the Intunewinapp

Now we have everything we need, we need to create the intunewinapp, so download the tool and zip it like shown below:

When we have created the intunewinapp we still need to publish it.

4. Execution Policy

To do so, open Intune and start creating a new Win32 app with the settings I show below:

Program

Please make sure you add the “-Executionpolicy Bypass” switch. I will tell you more about the execution policy in part 6!

Detection Rules

Of course, we need to specify detection rules. We need to make sure when the printer is not installed it will be installed. The best method would be to choose a registry detection rule. But how do we know what key we must use? That’s easy… just open the registry and browse to this registry key to find your printer:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers\

You will notice all printers are listed here. We can use the same value as we configured in the install.ps1 as printer name. In this example, I am using: Toshiba Hoofdkantoor

As shown above, I am making use of the “detection method“: String Comparision to find the Registry Value: “Name” and detect if it is the same as “Toshiba Hoofdkantoor”. You can check out the registry value “Name” in the registry key I mentioned above to be 100% you get it right.

Assign the win32app to the correct users/groups/devices as required (or available if you want the let the end-user install the printer themselves when they really need it )

Results:

After the Win32 App finished installing, we notice a new printer has been installed. Let’s check it out!

Looking at the printer port, it has the proper TCP/IP port attached to it

And of course, it has exactly the same printer driver which we specified to be installed!

4.Finetuning

Of course, we don’t want every page to be printed in color, so change the color setting to $false to make sure you will save some money.

I also disable the duplex option and specify the paper size in this example. You can add this part to the end of the install.ps1 script to make sure the printer settings are changed when the printer is installed.

Set-PrintConfiguration -PrinterName “Toshiba hoofdkantoor” -PaperSize A4 -color $false -duplexingmode onesided

3.Installing Printers and Drivers with Printbrm.exe

Just like PnPutil, it’s a nice build-in utility… so why not use it? A big difference with the PnPutil.exe is that with this nice tool you can export ALL Printers and their corresponding drivers to one big Printerexport file.

printbrm.exe -B -F c:\test.printerexport

Please beware: PrintBRM is not be included in the Windows PATH but will be found at c:\windows\System32\spool\tools\printbrm.exe

So when creating your PowerShell script and converting to an Intunewin App together with the Printerexport, please make sure you define the full path to the PrintBRM tool! Your restore command would be c:\windows\System32\spool\tools\printbrm.exe -R -F .\exportfile.printerexport -O

Now create the IntuneWinApp and upload it to Intune

4.Install Hp Printers with the Universal Printer Driver

Someone mentioned in the comments that it’s also possible to use the HP universal printer driver (install.exe) to make sure the Printer and drivers are installed correctly.

First, you will need to download the Universal Printer Driver from the Hp website or this link.

Make sure you extract the files to a folder named HP.

Now create a PowerShell script and name that one install.ps1

$PortName = "PortName"
$PortAddress = "xxx.xxx.xxx.xxx"
$NewPrinter = "PrinterName"
$checkPortExists = Get-Printerport -Name $portname -ErrorAction SilentlyContinue
if (-not $checkPortExists) {Add-PrinterPort -name $portName -PrinterHostAddress $PortAddress}

.\hp\install.exe /n "$NewPrinter" /sm "$PortName" /h /q /nd /u

Sleep -Seconds 30

The install switches are: /h = hide installer /q = Quiet no user interaction /nd = Not default /u = Don’t install driver if already present.

Convert that folder to an Intunewinfile (so the .\hp\ folder is also included). Upload this file to Intune and make sure you configure the install command like this: Start-Process PowerShell -Verb RunAs” .\install.ps1

Of course, with every Win32App you will need to have a detection rule…. You could set up one by using the registry to detect if the printer already exists by specifying this key:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers\PrinterName (change the printer name to match the one from the script)

5. Install Printer Drivers with PrnDrvr.vbs

Another cool possibility is to just use the old PrnDrvr.vbs file and combine it with Cscript. This Prndrvr.vbs can be used to install or delete a driver. This file can be found in your Printing_Admin_Scripts folder like shown below

Of course, before we can add the Driver, we also need to add the Printer Port first, just like we did with the HP universal driver.


$PortName = "PortName"
$PortAddress = "xxx.xxx.xxx.xxx"
$NewPrinter = "PrinterName"
$checkPortExists = Get-Printerport -Name $portname -ErrorAction SilentlyContinue
if (-not $checkPortExists) {Add-PrinterPort -name $portName -PrinterHostAddress $PortAddress}

And now we can use Cscript to call upon the visual basic script file to install the driver.

cscript "C:\Windows\System32\Printing_Admin_Scripts\en-US\prndrvr.vbs" -a -m "Canon Generic Plus PCL6" -i ".\GPlus_PCL6_Driver_V250_32_64_00\x64\Driver\CNP60MA64.INF" -h ".\GPlus_PCL6_Driver_V250_32_64_00\x64\Driver" -v 3

Add-Printer -Name $newprinters -PortName $portname  -DriverName "Canon Generic Plus PCL6"

When you combine both of these scripts to one PowerShell script and add the Driver to the folder you can convert it to a nice Win32app and deploy it with Intune to your devices

6. PowerShell Execution Policy

Because I have been getting some questions about the PowerShell Execution Policy, I will try to get some stuff clarified about the executionpolicy!

1. IntuneWinapp/Win32 App

When you have configured a new Intunewinapp/Win32App, and you want to make sure your PowerShell script is going to be executed successfully. You need to make sure this PowerShell Script is executed with the proper policy to bypass the execution policy. You can so by simply execute Powershell.exe -ExecutionPolicy ByPass -File “.\full-script-path\script.ps1”

When using this option Microsoft tells us this: “Nothing is blocked and there will be no warnings or prompts”

2. PowerShell Scripts

When you have deployed a new PowerShell Script to Intune the Intune Management Extension (IME) will make sure this PowerShell script is executed on the device.

The IME doesn’t require any change whatsoever to the PowerShell Execution policy on the device. The IME will take care of the correct execution of your PowerShell scripts.

3. Set-ExecutionPolicy at the Top!

When you have the bright idea to push a PowerShell script with a set-executionpolicy at the top of it to change the execution policy, that isn’t going to work! Because the PowerShell execution policy is checked before the script is run so changing it within the script has no value or meaning. It really sounds like the chicken and the egg situation?

4. Changing the MachinePolicy

Also changing the execution MachinePolicy on devices with the use of a PowerShell script deployed by the IME and using Set-ExecutionPolicy is not going to work

As shown above, the PowerShell command is not able to modify the MachinePolicy. Changing the MachinePolicy for Execution Policy is only allowed with the use of a Group Policy only. (by default)

Why I am mentioning the by default? As you “could” change it with the use of Regedit as the Group Policy just equals some registry values

Conclusion

When migrating to a full based cloud solution you will need to migrate your printer solutions also. Microsoft Universal Print should be your end goal but in the meantime, you could take a few baby steps and make sure some printers are still installed when necessary.

16 thoughts on “What about Printer Drivers

  1. Thank you for posting this. I’m trying to do exactly what you described. For some reason my app is still failing. Not sure what is causing the failure. I’m having a hard time finding the exact logs I should look at to troubleshoot the problem.

    1. WHen the app is failed installing, the intune management log would be the first place to start. There are a millions reasons why, the app failed to install..
      If you post/send me the script etc I could test if for you to see what happens

  2. In the post PrintNightmare world most of the ability to install drivers using powershell commands have fail. I have resorted using PowerShell to create the Port. Because most of our printers are HP and Universal Print Driver compatable I was able to use the Install.exe from the Basic Driver with Install from HP.

    My IntuneWin package consisted of the Driver files and the Install and Uninstall PS Scripts. I ran this Install Powers shell scrip with the Install command of: powershell -executionPolicy bypass -Command “Start-Process PowerShell -Verb RunAs” .\install.ps1
    ___________
    Script:
    $PortName = “West_Local”
    $PortAddress = “xxx.xxx.xxx.xxx”
    $NewPrinter = “West_Local”
    $checkPortExists = Get-Printerport -Name $portname -ErrorAction SilentlyContinue
    if (-not $checkPortExists) {Add-PrinterPort -name $portName -PrinterHostAddress $PortAddress}

    .\install.exe /n”$NewPrinter” /sm”$PortName” /h /q /nd /u

    Sleep -Seconds 30
    _____________________________________
    The install switches are /h = hide installer /q = Quiet no user interaction /nd = Not default /u = Don’t install driver if already present.

    I did Sleep for 30 seconds because with out it the detection fails because it tries to detect before the install is complete.

    Detection is the presence in the registry = HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Print\Printers\West_Local

    This works everytime.

    1. There are multiple methods to push printer drivers to the devices indeed… I will add your solution to the blog… so people can choose which option they prefer (of don’t have hp printers 🙂 )
      Can you post the link to the proper install.exe file?

  3. I’m doing exactly the same thing as you discribe in your blog but the install script woun’t start at devices with execution policy set do “restricted”.
    As soon as I set the execution policy on the machine to “unrestricted” the install works perfect.
    But the default value for the execution policy is “restricted” so the install woun’t run on any unmodified machine.

    Have you any ideas to this?

      1. Hi,

        How did you configured the Intune install cmd? did you add the -executionpolicy bypass to it? Like I am describing in part 6 of the blog?

  4. Hi I am having trouble installing and getting it to work tried two methods from the blog and both failed :(.

    Is this correct what I have done

    $PortName = “10.240.45.145”
    $PortAddress = “10.240.45.145”
    $NewPrinter = “WPA Printer”
    $checkPortExists = Get-Printerport -Name $portname -ErrorAction SilentlyContinue
    if (-not $checkPortExists) {Add-PrinterPort -name $portName -PrinterHostAddress $PortAddress}

    .\hp\install.exe /n “$NewPrinter” /sm “$PortName” /h /q /nd /u

    Sleep -Seconds 30

    if anyone can guide me I will be gratefuly

  5. With the latest release i was not able to get this working properly…

    #Install HP Universal Printing PCL 6
    pnputil.exe /add-driver “$psscriptroot\hpcu255u.inf” /install
    Add-PrinterDriver -Name “HP Universal Printing PCL 6”

    #Install Printerport with check if the port already exist
    $portName = “IP_192.168.111.84”
    $PortAddress = “192.168.111.84”
    $checkPortExists = Get-Printerport -Name $portname -ErrorAction SilentlyContinue
    if (-not $checkPortExists) {
    Add-PrinterPort -name $portName -PrinterHostAddress $PortAddress
    }

    #Install Printer
    Add-Printer -Name “HP LaserJet MFP M130fn” -DriverName “HP Universal Printing PCL 6” -PortName $portName

    SLEEP 360
    This worked for me!

  6. Was perfect! Thank you for this!

    I had to tweak the uninstall as it failed. This worked for me:

    remove-printer “(Printer Name)”
    SLEEP 360
    remove-printerPort -Name “IP_(IP of your Printer)”

  7. I followed your how to.
    But the printer is not installed.
    In the event log (powershell) I can see:
    The file “C:Windows\IMECache\….\install.ps1” cannot be loaded because the execution of scripts is disabled on this system. Please see “about_Execution_Policies” for more details.
    full quallified error-id = UnauthorizedAccess

    I definitely used
    powershell.exe -Executionpolicy -Bypass .\install.ps1
    as installation command.

    Do I have to change the script execution settings somewhere else as well? Where?

    Thanks in advance

    1. Hi, could you change the
      powershell.exe -Executionpolicy -Bypass .\install.ps1

      To

      Powershell.exe -ExecutionPolicy ByPass -File “.\full-script-path\script.ps1”

Leave a Reply

Your email address will not be published. Required fields are marked *

  +  14  =  18