In our Citrix XenApp 6.5 environment we started having a couple applications encounter an issue where they would experience some serious graphical artifacts. What was supposed to look like this:
Would look like this:
Here’s a short video demonstrating this issue:
Or sometimes it would show the windows *behind* the artifacted image. That is, instead of the ‘White’ you see in my image, the application behind it shows through.
When investigating this we found there was a couple symptoms that we were going to experience these artifacts.
- The window would become ‘frosted’ or ‘ghosted’ (as seen in Spy++ or AutoIt Window Info)
- The application would switch to ‘Not Responding’
- If you completed the task ‘Edit’ quickly there would be no artifacting (time was important)
- When ‘timing’ the switch from ‘normal’ to frosted or ghosted window it would be around 5-7 seconds.
So what’s going on here?
For this particular instance, the application is launching MSPaint with some modified properties. It sets Paint to ‘Always On Top’, which in itself isn’t an issue, but then it purposefully locks the UI so you must complete the drawing and close paint before continuing. This is how the vendor designed this application to operate with this workflow.
And what’s Windows doing? It turns out, Windows is trying to alert you that your program is non-responsive! Windows has a built in feature to ‘Frost/Ghost’ the window of a non-responsive UI to prevent you from entering input that won’t be received. The ghosting effect is time sensitive! So that explains why if we opened and closed our document quickly their would be no artifacting but if we manipulated it for some time the artifacts would appear. The time limit for monitoring unresponsiveness is 5 seconds. DWM.exe is the process responsible for creating the ‘Frost’ window and when responsive returns, it appears it does a poor job telling the application to repaint all affected Windows.
Microsoft recommends a couple ‘fixes’ which is really a programmatic way to ‘disable’ the ghosting feature. The two methods Microsoft suggests is to create a NoGhost application compatibility fix or have the programmer use ‘DisableProcessWindowsGhosting’. But there is a 3rd method.
The 5 second time limit is programmable. If we extend the timeout we don’t need to configure ‘NoGhost’ compatibility fixes for each app or go back to the vendor. The timer is global and affects every application and window. Unfortunately, I know of no way to permanently disable it, but we can set a high enough value to prevent it from appearing.
So what do we have to do to ‘resolve’ this?
My preferred choice was to use Group Policy Preferences (Registry) and set a new value for HKCU\Control Panel\Desktop /v HungAppTimeout /t REG_SZ /d 120000
This sets the timeout to 2 minutes as opposed to 5 seconds. Now when our program is used we get this result:
No More Artifacts.
When I was investigating this I found I could get the artifacting to occur in both ICA and RDP but not when on the console. The frustrating thing about this issue is that it was not consistent. Because of the 5 second default time limit, the program(s) we had that would ‘artifact’ would sometimes complete their UI locking job faster than 5 seconds, but sometimes not. This lead to reports of artifacting occurring more often ‘during the peak work hours’ when the application/server/user load was the most. This makes sense as the higher load undoubtedly lead to everything being slower, the database, server, etc. leading to the application waiting longer and thus exceeding the timeout. I did find through the course of troubleshooting this issue that it seemed to ‘go away’ when I was trying to replicate after hours, which is frustrating to only have a slice of time to try and resolve this during peak hours.
Fortunately, after implementing the HungAppTimeout registry key the artifacts for several application ‘went away’.
Lastly, contrary to this article you do NOT need to restart for this value to take effect. WinLogon.exe reads the HungAppTimeout value and then configures DWM accordingly when your profile loads. So for this value to take effect you only need to log on with this value already residing in your user’s registry hive.