It’s been a little while since I had a “nice” application problem to blog about. It’s weird but I actually enjoy looking into those issues, well probably means I’m weird which is probably right.

I use a Virtual Desktop as my primary work desktop since my day 1 at work (and all the day 1’s after).

I like it because of the flexibility it gives me to work on any device and I also feel it’s that “drinking your own Champagne” is the very best way to really see if something is good!

Today I needed to write some notes and I wanted to use Quip for that but I’ve been having intermittent issues with the Quip Desktop app. I would launch and simple show a white screen with a stalled busy indicator.


Like most persons do, I ignored it and continued in the browser version for a while but as I don’t really like to have applications in a browser (hidden between 104 other tabs) I decided I would no longer “take” this and dived into it.

My first step was to search for logfiles and in the Quip Folder (%LocalAppData\Quip\app-7.75.3) I found a file called CEF.log.

CEF stand for “Chromium Embedded Framework” and is a quite well known framework to embed a Chromium browser into a Desktop App. Just like many other apps nowadays, the Quip Desktop app is a light wrapper around a web application.

In the log file I could only see the following:

The lines all seemed to refer to GPU related things, Vulkan refers to AMD GPU’s whilst EGL refers to OpenGL/OpenVG.

So I went searching for how to disable GPU acceleration in CEF because my Virtual Desktop doesn’t have a GPU and the errors were pointing to GPU.

Unfortunately I didn’t find a config file or registry setting but I found this on the CEFSharp documentation:

Alternatively there is also a method CefSettings.DisableGpuAcceleration.

Given that Quip is a .NET application I opened the Quip main executable (quip.exe) in dnSpyEx (continuation of dnSpy).

Given that the CefSettings are passed to Cef.Initialize I searched for that function using the magnifying glass and found it in Desktop.ApplicationController. And as you can see in the screenshot below, somewhere between lines 33-35 would be a great place to inject our code to disable GPU acceleration:


Often this is a relatively easy task as dnSpy has an option to Edit the Method, inject or modify the C# code and recompile. Just right click and select Edit Method.

However sometimes dnSpy fails to compile the modified code, for example when an obfuscator has been used or due to other issues. And of course it failed on this binary as well Sad smile

Oh well, it means we can still do what we want but it’s slightly more complicated. Instead of Edit Method choose Edit IL Instructions:


Now go to the line where you want to insert the new code, I opted for between line 33 and 34. So set the cursor to line 34 before clicking Edit IL Instructions and you are already on the correct line.

Now from the menu select Add New Instruction Before Selection:


Repeat this so we have 2 lines where we can insert code, you will get 2 new lines with NOP:


Change the first NOP to LDLOC.1.

You might wonder how we know it should be LDLOC.1? Well if you look in the screenshot you can see the other calls using LDLOC.1 as well. But you can also click on the Local tab on the top and lookup the Index you need. Index 1 means you need to use LDLOC.1:


Now change the second NOP to CALLVIRT and click on the NULL and select Method:


You can of course manually type or click and select but I used the Search box and typed disablegpu and it showed me the DisableGPUAcceleration Method (make sure you have CefSharp.Core module loaded in dnSpy).


So select that and click OK. The End result should look like this:


Click OK and the new line should be visible in the code:


Finally click File | Save Module:


Make a backup of course of the original and click OK on the next dialog:


And there we go, a working Quip again and after logging in all was good!


However when I’ve found a fix, I always retry so I reverted the change and to my surprise Quip continued working.

So I started to think what happened and now I understand why, the crash happens on the login screen.

If your login is still valid (it makes you login every x days) then it doesn’t have this issue.

Apparently GPU acceleration is required for the login screen.

Because hey, who wouldn’t want to see a fancy, GPU accelerated login screen? I mean it only takes 4,5 seconds to load on my 16 core machine.

Boy sometimes I wish we would just go back and write proper Win32 apps with a real login screen and not all the fancy web stuff that keeps breaking.