Microsoft SmartScreen is a pain in the butt for developers. It pops up scary warnings for files that it doesn't recognize, telling the user that they're potentially harmful. That's why I got an Extended Validation (EV) code signing key, to sign my releases so that SmartScreen won't show scary warnings, and won't scare away potential users.

The Problem

I use an automated build server for compiling, testing and building releases. This is standard practise in the software industry. Here's where the problem starts. The code signing key works just fine when tested manually. However, the automated build process hangs right where the code should be signed.

The code signing hangs, because the build server is running as a Windows Service. In my case, it's GitLab-Runner, but I've been told that the same problem exists with Jenkins (and others). The installation instructions say to install it as a service.

The problem occurs, because the code signing key is password protected, but Windows services cannot pop up a User Interface (UI) window. Microsoft decided that Windows services cannot have a UI for security reasons. Anyway, the build process hangs when it gets to the code signing step, because it needs to show a password entry dialog, but it's running as a service and therefore cannot.

A Bad Solution

It's really tempting to embed the password in the build script. However, others will warn you "danger danger, don't do it!" The reason is that the password will leak out in the build logs, which get uploaded to GitLab/GitHub/wherever. You don't want that...

The Solution

  • Delete the GitLab-Runner (or Jenkins) Windows service you created
  • Now open up "Task Scheduler," and create a task scheduled to start when you log on. It should be run under your user context
    NOTE: Since this is a build server, you could create a special "build" user if you don't want to use your own account

Now that the build server is running in a regular user account, it'll pop up the password window when necessary. Don't worry, you won't have to enter it every time. Once is enough. The release build process can now complete.

It does have the downside that the build server is no longer 100% automated. You will need to log in and enter the code signing password again after a restart. That's no big deal, though. I personally manually trigger the release build,** so I'm there to enter any passwords as needed.

 

** Internal test version don't need to be signed; only official releases.