Jump to content
Welcome to our new Citrix community!
  • 1

Windows Server 2016 and XenApp 7.15 CU2 - Default printer registry key not set when launching published app


Wendell Pinegar

Question

One of our published apps that used the Crystal Report 8.5 runtime wasn't working properly. The app crashed every time we tried to print something from one of the built-in reports. In troubleshooting this issue we discovered that the default printer is stored in the registry HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device and we found that this registry setting isn't being set if the app is launched as a published app. However, if we launch an interactive desktop session via RDP to the Citrix server the registry key does get set properly. Once this registry key is created and set properly the Crystal Report 8.5 runtime works perfectly and the app prints just fine. Does anyone know why the default printer registry key isn't being set by Server 2016 when we launch a XenApp 7.15 published app?

 

So we've found what appears to be a bug with Windows Server 2016 and XenApp 7.15 that causes this registry key to not be set if the user launches a published app but it is set if a user logs into a desktop session on the server. To temporarily resolve this issue we've written a Powershell script to set this registry key based on the current default printer when the user signs on and we launch the Powershell script as part of the Published app's startup. We also turn on WaitForPrinterCreation for the published app so that all client printers are created and the default session printer is created by the time the startup script for the published app runs.

 

Set-BrokerApplication APPNAME -WaitForPrinterCreation:1

# Clear any existing errors.
#
"Waiting for printers to be created"

#Start-Sleep 5

$error.clear()
$registrykey = "Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows"

# Set the location
#
Set-Location -Path $registrykey -ErrorAction SilentlyContinue

# Retrieve the default printer properties.
#
$wmiDefaultPrinter = Get-WmiObject -query "SELECT * FROM WIN32_PRINTER WHERE Default = TRUE"

# If the default printer exists then set the registry values.
#
if ($wmiDefaultPrinter -ne $null)
{
	"Setting the Windows default printer registry key"
	Set-ItemProperty -Path $registrykey -Name "Device" -Value ($wmiDefaultPrinter.Name+",winspool,Ne00:")
	Write-Host "Your default printer is" $wmiDefaultPrinter.Name
} else {
	Set-ItemProperty -Path $registrykey -Name "Device" -Value "Microsoft Print to PDF,winspool,Ne01:"
}
Link to comment

Recommended Posts

  • 1

@chaag1, We're glad that we fix we posted corrects the issue. There are definitely some legacy applications that don't like the default printer registry key being set to blank. Any apps using the Crystal Reports 8.5 runtime seem to have an issue. We had an opportunity to test Server 2012 R2 and it didn't have this issue so the problem only occurs in Windows Server 2016. It's also a problem with basic RDP when the printer is an auto-created session printer. For whatever reason Windows Server 2016 does correctly update the default printer registry key with the correct value when you set a locally attached printer as your default such as the "Microsoft Print to PDF" or "Microsoft XPS Document Writer". Either of these cause "HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device" to be updated correctly.

 

We heard back from a Citrix support engineer on this issue and they confirmed with Microsoft that this is a known problem with print subsystem in Windows Server 2016. Microsoft is working on the issue but there is no fix at this time. I don't have a KB article.

 

Not sure why WaitForPrinterCreation isn't working to set the default printer before the published app starts. That's the whole point of WaitForPrinterCreation is to setup the printers before the app starts. Are you using Citrix UPD/UPS printing or your vendor's native print drivers on the Citrix servers?

 

By the way, if you don't want to see a black box as your application starts you can use the following to execute the Powershell script as a published app: "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy RemoteSigned -WindowStyle Hidden -Command "& 'C:\Scripts\SetDefaultPrinter.ps1'"

  • Like 1
Link to comment
  • 0

We've got the same issue with two apps we're trying to move to XA715/Win2016. Populating

HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device

fixes it. Your script works but I've found that even with WaitForPrinterCreation enabled, I have to pause the script for 4 or 5 seconds so WMI can pick up the default. I launch the app first thing in the script, then start-sleep 5 and then let it proceed. It runs in a window in the background and users get their app right away.

 

I appreciate you posting the issue and the fix you found.

Link to comment
  • 0

@Wendell, thank you for this! This was so frustrating.  I've been pulling my hair out for days. It was only affecting some of my apps, and in one case, only one of the many print functions within a reporting app. I was about to kick it over to my development team or tear down my whole environment and start over. 

Windows Server 2016 and XenApp 7.15 CU3

Link to comment
  • 0

Simply start the Powershell script as the executable for the published app and then start the published app at the end of the Powershell script. The following might work well to startup the Script above. I would recommend uncommenting the line #Start-Sleep 5 and adjusting the time the script waits so that the user's default printer is always created before script runs to set the user's default registry key.

 

 "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -ExecutionPolicy RemoteSigned -WindowStyle Hidden -Command "& 'C:\Scripts\SetDefaultPrinter.ps1'"

Link to comment
  • 0

Thanks.  Some how my co-worker got a PS script to run for a specific application without changing the executable for the published app.  It just calls out the normal application EXE but when I run that app, it runs a PS script before hand...and only for that app.  Other apps on the same servers don't launch PS when run from my test account.  So I was wondering if there was special argument for the published app that allows a script to be assigned to it (that is not visible in the GUI of Studio when creating an app).

 

I will check with him to see how it did it...but he is definitely not doing what you are describing.

Thanks

NK

Link to comment
  • 0

FYI, Windows Server 2016, all builds of WIndows 10, and Windows 2019 all exhibit the same problem with the default printer registry key. Not all application use the default printer registry key but for those older apps that do then they simply break or behave unpredictably such as printing to the non-default printer. 

 

You can also run the script in the background and place your published app startup toward the beginning of the script. I've created variations of the script to update the default registry key every 5 seconds to it catches instances where the default printer changes after the user launches the published app. Just remember that if you don't put an pause in the script it might execute before the default printer gets created so the default registry key won't be set correctly. Usually you can create the printers before the script published app starts by running the Citrix powershell command "Set-BrokerApplication {APPNAME} -WaitForPrinterCreation:1" and execute once for the published app from a CItrix admin, but it doesn't seem to have any affect on the printers being created before the the Powershell script starts. You are welcome to test it on your version of Citrix XenApp and see if the issue is resolved.

 

 

 

 

Link to comment
  • 0

Any suggestions on getting the session to close properly when the user closes the application.  I added a -Wait to the end of the Start-Process, but it still leaves PS process running after the user closes the app.  If I login at the console and kill the PS process for that user, then the session closes out...so I am pretty it is PS that is keeping everything open still.

 

If I RDP to the server and manually run the PS script, then close the app - PS closes fine.  But in a Citrix published app...it just hangs.

Thanks

NK

Link to comment
  • 0
8 hours ago, Nelson Kaeppel said:

Any suggestions on getting the session to close properly when the user closes the application.  I added a -Wait to the end of the Start-Process, but it still leaves PS process running after the user closes the app.  If I login at the console and kill the PS process for that user, then the session closes out...so I am pretty it is PS that is keeping everything open still.

 

If I RDP to the server and manually run the PS script, then close the app - PS closes fine.  But in a Citrix published app...it just hangs.

Thanks

NK

 

Are you letting the Powershell script run in a loop so it can pickup changes to the default printer? If so you can simply check to see if the process that you spawned (the actual published app) is still running or if the process has stopped and exit the powershell script once the spawned process has exited. I have used something similar to the following. Hopefully this code snip-it will help:

 

# Get the current process.

#

$currentProcess = (Get-Process -Id $pid)

 

# Start eCW

#

$eCWprocess = (Start-Process $ecwProgram "configuration_personal.xml" -PassThru -WorkingDirectory "$eCWDir")

 

# Determine if a Powershell script has already started. If it has then exit so we don't start multiple powershell script per Citrix session.

#

$powershellCount = (Get-Process | Where-Object {$_.Path -like "*\Powershell.exe" -and $_.SessionID -eq $currentProcess.SessionID}) | Measure

if ($powershellCount.Count -ne 1) {

[Environment]::Exit(1)

}

 

# Clear any existing errors.

#

$error.clear()

$registrykey = "Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows"

 

# Wait for a predefined period of time.

#

Start-Sleep -Seconds 1

  

# Set the location

#

Set-Location -Path $registrykey -ErrorAction SilentlyContinue

 

# Set the default printer for legacy printing.

#

$processeCW = Get-Process | Where-Object {$_.Path -like "*\eClinicalWorks.exe" -and $_.SessionID -eq $currentProcess.SessionID}

while ($processeCW -ne $null) {

# Wait for a predefined period of time.

#

Start-Sleep -Seconds 10

        

# Retrieve the default printer properties.

#

$wmiDefaultPrinter = Get-WmiObject -query "SELECT * FROM WIN32_PRINTER WHERE Default = TRUE"

 

# If the default printer exists then set the registry values.

#

if ($wmiDefaultPrinter -ne $null)

{

"Setting the Windows default printer registry key"

Set-ItemProperty -Path $registrykey -Name "Device" -Value ($wmiDefaultPrinter.Name+",winspool,Ne00:")

Write-Host "Your default printer is" $wmiDefaultPrinter.Name

} else {

Set-ItemProperty -Path $registrykey -Name "Device" -Value "Microsoft Print to PDF,winspool,Ne01:"

}

$processeCW = (Get-Process | Where-Object {$_.Path -like "*\eClinicalWorks.exe" -and $_.SessionID -eq $currentProcess.SessionID})

}

 
Link to comment
  • 0
10 hours ago, Nick Panaccio said:

Have you actually noticed it causing an issue in a Win10 published desktop? Your initial post seemed to indicate that it didn't happen for a published desktop, just a published app.

 

Yes, we have confirmed that Windows Server 2016, all builds of WIndows 10, and Windows 2019 all exhibit the same problem with the default printer registry key. Not all application use the default printer registry key but for those older apps that do then they simply break or behave unpredictably such as printing to the non-default printer.  This issue occurs on published apps or published desktops and occurs with Citrix or RDP session printers. Any network printers or locally defined printers don't typically exhibit the issue. You would need to test to determine if your apps or printers are affected.

Link to comment
  • 0

We found that our application (ESRI ArcMap) launches several other processes when it loads.  So when it closes, the other processes remain open.  In Citrix, we added those processes to the ""LogoffCheckSysModules" registry key so that when primary ArcMap process stops, Citrix logs out the sessions.  But when using a PS script, I am wondering if that throws a wrench into the whole ""LogoffCheckSysModules" functionality.

 

Although this does not explain why it works from RDP...

NK

Link to comment
  • 0

OK stupid question.. My app wont launch what do I have wrong here.. Cant use the "

 

Path to Executable:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy RemoteSigned -WindowStyle Hidden -Command & 'C:\Scripts\SetDefaultPrinter.ps1' d:\apps\server\ssi\agvance\agvance.exe

Link to comment
  • 0

Could be your executionpolicy setting.  I used Bypass and it now works for me.  I see you are using RemoteSigned...should work if script is local.   Just something I noticed.

 

The other I did was call the EXE from within the script.  Looks like you are providing it as command line argument to the script.  Maybe Citrix published app is choking on that.

 

Finally, I used IExpress to package the whole thing as an EXE.  So my published app is actually calling the IExpress EXE instead of the the native PS script.  In my SED file, I am using this "AppLaunched=C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe -ExecutionPolicy Bypass -WindowStyle Hidden -File "LaunchApplication.ps1"

 

Where LaunchApplication.ps1 is a modified version of Wendell's fine script, with a delay in the beginning to allow all printers to load first and then calls my EXE before it exists.

Nelson

Link to comment
  • 0
17 minutes ago, Tim Carpenter said:

OK stupid question.. My app wont launch what do I have wrong here.. Cant use the "

 

Path to Executable:

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy RemoteSigned -WindowStyle Hidden -Command & 'C:\Scripts\SetDefaultPrinter.ps1' d:\apps\server\ssi\agvance\agvance.exe

 

None of the sample powershell code that we posted included a method for passing program to start as part of the powershell script. You would need to create that or simply embed the startup of the published app within the powershell script...it's fairly easy to do basic troubleshooting by logging into the server console and running the command interactively or from a batch file until you get everything working....

Link to comment
  • 0

So I added this line to the bottom of the PS1 script and saved it.. 

 

Start-Process -FilePath d:\apps\server\ssi\agvance\agvance.exe -WorkingDirectory s:\ssi_j\jvdata

 

I can then either run the script from ISE and it does what I need it to I can even run this from a run command:

 

C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy ByPass -WindowStyle Hidden -Command & 'C:\Scripts\SetDefaultPrinter.ps1'

 

And it works as expected.

 

I cant get it to run as a published application however..  The other problem I see is if I get it to work I will have to create unique scrips for 450 published applications because each app has a unique working directory..

 

Please forgive me if Im thinking about this the wrong way.. Been a crazy week.

Link to comment
  • 0

Just to throw another solution into the mix - I've gone down the GPP route, instead of messing with scripts:

<?xml version="1.0"?>
<Registry bypassErrors="1" userContext="1" uid="{5FEBA11B-1D6D-46CD-91E5-97ADFB158CDA}" changed="2019-02-14 13:52:24" image="7" status="Device" name="Device" clsid="{9CD4B2F4-923D-47f5-A062-E897DD1DAD50}">
	<Properties name="Device" value="Microsoft Print to PDF,winspool,Ne01:" type="REG_SZ" key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" hive="HKEY_CURRENT_USER" default="0" displayDecimal="0" action="U"/>
	<Filters>
		<FilterRegistry type="MATCHVALUE" key="SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows" hive="HKEY_CURRENT_USER" lte="0" gte="1" max="0.0.0.0" min="0.0.0.0" valueData="winspool" valueType="REG_SZ" valueName="Device" subtype="SUBSTRING" not="1" bool="AND"/>
	</Filters>
</Registry>

 

Same idea s the PS script - if that Device key doesn't contain "Winspool" then set the default printer to be the Print to PDF printer. This is applied to the XA/XD servers with loopback enabled as the settings are on the user side.

 

This should then work for any application or even desktop :)

Link to comment
  • 0
On 6/8/2018 at 1:37 PM, Wendell Pinegar said:

One of our published apps that used the Crystal Report 8.5 runtime wasn't working properly. The app crashed every time we tried to print something from one of the built-in reports. In troubleshooting this issue we discovered that the default printer is stored in the registry HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\Device and we found that this registry setting isn't being set if the app is launched as a published app. However, if we launch an interactive desktop session via RDP to the Citrix server the registry key does get set properly. Once this registry key is created and set properly the Crystal Report 8.5 runtime works perfectly and the app prints just fine. Does anyone know why the default printer registry key isn't being set by Server 2016 when we launch a XenApp 7.15 published app?

 

So we've found what appears to be a bug with Windows Server 2016 and XenApp 7.15 that causes this registry key to not be set if the user launches a published app but it is set if a user logs into a desktop session on the server. To temporarily resolve this issue we've written a Powershell script to set this registry key based on the current default printer when the user signs on and we launch the Powershell script as part of the Published app's startup. We also turn on WaitForPrinterCreation for the published app so that all client printers are created and the default session printer is created by the time the startup script for the published app runs.

 

Set-BrokerApplication APPNAME -WaitForPrinterCreation:1


# Clear any existing errors.
#
"Waiting for printers to be created"

#Start-Sleep 5

$error.clear()
$registrykey = "Registry::HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows"

# Set the location
#
Set-Location -Path $registrykey -ErrorAction SilentlyContinue

# Retrieve the default printer properties.
#
$wmiDefaultPrinter = Get-WmiObject -query "SELECT * FROM WIN32_PRINTER WHERE Default = TRUE"

# If the default printer exists then set the registry values.
#
if ($wmiDefaultPrinter -ne $null)
{
	"Setting the Windows default printer registry key"
	Set-ItemProperty -Path $registrykey -Name "Device" -Value ($wmiDefaultPrinter.Name+",winspool,Ne00:")
	Write-Host "Your default printer is" $wmiDefaultPrinter.Name
} else {
	Set-ItemProperty -Path $registrykey -Name "Device" -Value "Microsoft Print to PDF,winspool,Ne01:"
}

HI, New user on the boards, but a fair amount of Citrix knowledge, I've been struggling with something similar to this. Was curious about the Powersheel and calling this with the published application.

 

the Published app I'm having issues with calls a manu launcher which is a fairly simple batch file located on the app server, the user will then select from menu options which app to launch and the batch file will launch the executable of the installed app on the app server and launch.

 

In order for this powershell to work, I assume I will need a particular set of Citrix Powershell commands loaded on the Application server, as essentially it is running the powershell ON the app server, is this correct?.

Link to comment
  • 0
1 hour ago, Mike Winspear said:

HI, New user on the boards, but a fair amount of Citrix knowledge, I've been struggling with something similar to this. Was curious about the Powersheel and calling this with the published application.

 

the Published app I'm having issues with calls a manu launcher which is a fairly simple batch file located on the app server, the user will then select from menu options which app to launch and the batch file will launch the executable of the installed app on the app server and launch.

 

In order for this powershell to work, I assume I will need a particular set of Citrix Powershell commands loaded on the Application server, as essentially it is running the powershell ON the app server, is this correct?.


There is a fix for this issue in Citrix XenApp 7.15 CU4. This registry key will automatically be set correctly when painting a published app. 

Link to comment

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...