, , , ,

In my final post on this subject, I’ll write about what I eventually did to solve the problem of printing to a printer within the VDI.  Please read the previous two posts for background information: Part1 and Part2.

The first thing I did was to share out the printer on the physical PC as “LabelPrinter$”.  Since I have a Group Policy object to turn a PC into a VDI physical “kiosk” machine, I wanted this to be automated.  This was done with the following Computer Startup script:

On Error Resume Next


Set objSWbemServices = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\CIMV2")
strWQL = "SELECT * FROM Win32_Printer WHERE Shared = False"
Set colPrinters = objSWbemServices.ExecQuery(strWQL,,WBEMFLAGRETURNWHENCOMPLETE)
For Each objPrinter In colPrinters
	If objPrinter.Name = "Label Printer" Then
		objPrinter.Shared = True
		objPrinter.ShareName = "LabelPrinter$"
	End If


The script looks for all non-shared printers and then if it’s called “Label Printer”, shares the printer out with sharename “LabelPrinter$”. Note that after writing the changes to the two properties of the WMI Win32_Printer instance, it’s necessary to call the “Put_” method of that instance to commit these changes to the WMI Repository and make them take effect.


The solution for inside the virtual machines takes advantage of a little trick you can do. You probably know that the command line’s NET USE command can be used to map a drive letter to the UNC path of a fileshare. What is less obvious is that you can also map a printer port to the UNC path of a printshare the same way.  Another necessary piece of the puzzle is that VMware View exposes the name of the current underlying physical PC to the VM through the environment variable ViewClient_Machine_Name.

In the virtual machine base image, the printer “Label Printer” has been installed with relevant driver settings as though it were installed on port LPT2:  Of course, this normally points nowhere and any jobs sent to it will just sit there.  The virtual machines then have a Group Policy Object that on Connect or Reconnect run the following little VBScript:

On Error Resume Next


Set objWshNet = WScript.CreateObject("WScript.Network")
strKioskPC = objWshShell.ExpandEnvironmentStrings("%ViewClient_Machine_Name%")

objWshNet.RemovePrinterConnection "LPT2:", FORCE_REMOVE
objWshNet.AddPrinterConnection "LPT2:", "\\" & strKioskPC & "\LabelPrinter$"


Any existing LPT2: is disconnected and then the AddPrinterConnection() method of the WScript.Network object does the equivalent of a NET USE to map LPT2: to the UNC path of the printer we shared on the physical PC from which we’re currently connected to the VM. The following screenshot shows the printer that’s in the base image and assigned to LPT2: highlighted, along with the details of the Port and UNC plumbing that makes this work.
VM-LabelPrinterYou’ll also see that VMware’s ThinPrint has pulled the underlying physical printer into the VM as well, along with its usual numerical suffix (“Label Printer#:1”). This isn’t a problem.

I can now move from one physical “kiosk” PC to another and LPT2: just merrily gets repointed to my local printer as I go. The printer installed on the VM doesn’t seem to mind at all about this change occurring repeatedly under its nose. Indeed, if I submit a print job to it while connected from a physical PC with no shared label printer at all, the job sits in the queue in the VM and prints out next time I connect to that VM from a PC that does have one on!


Having worked out all this complexity, when we finally created our Production VDI with the newer VMware View v6.2.2, ThinPrint brought in the printer names unaltered off the physical PC with no suffices, so I didn’t need to do any of this after all!  Oh well, it had been an interesting exercise!