Munich • Berlin • Lisbon

Electron on Windows Terminal Server: Avoiding the "Shadow Install" Trap

Cover Image for Electron on Windows Terminal Server: Avoiding the "Shadow Install" Trap

Building Electron applications is often a seamless experience—until you hit the enterprise environment. While Electron handles single-user desktop deployments beautifully, things get complicated when your customers run Windows Terminal Server (or Remote Desktop Services).

At our company, we recently encountered a critical issue where our application behaved unpredictably in these multi-user environments. We faced a "split-brain" scenario where users were running different versions of the software despite administrator interventions.

If you are building an Electron app for enterprise clients, this guide will help you configure Electron on Windows Terminal Server correctly to avoid the "shadow install" trap.

The Environment: Single User vs. Terminal Server

To understand the problem, we first need to look at the two ways our customers use our software:

  1. Standard Laptops: The user has full control (often admin rights). They install the software, receive update notifications, and click "Update." The software patches itself, and everyone is happy.
  2. Windows Terminal Server: This is common in law firms, hospitals, and security-conscious corporations.
  • Users log in remotely to a central server.
  • Admins install software system-wide (usually in C:\Program Files).
  • Users (non-admins) simply run the software. They should not be able to modify the core application files.

In the Terminal Server scenario, the "Source of Truth" must be the system-wide installation managed by the IT department.

The Problem: Electron Updater is "Too Smart"

The issue arises when you ship an update. By default, many Electron update configurations (specifically electron-updater) are designed to be resilient. They want the user to have the latest version, no matter what.

Here is the failure chain we observed:

  1. We shipped an update.
  2. The user (on a Terminal Server, without admin rights) saw the "Update Available" banner.
  3. The user clicked Install.
  4. The updater tried to write to C:\Program Files. Access Denied.
  5. The Fallback: Instead of failing, the updater thought, "Okay, I can't write to the system folder, so I will install this new version specifically for this user in their AppData folder."

The Result: Split-Brain Installations

The moment this fallback happens, you have a Shadow Install.

  • System Path: C:\Program Files\YourApp (Version 1.0, controlled by Admin)
  • User Path: C:\Users\JohnDoe\AppData\Local\YourApp (Version 1.1, controlled by User)

Windows will often prioritize the user-local version. Now, when the Admin updates the system-wide version to 1.2, the user never sees it. They are stuck launching their local "shadow" copy of version 1.1 forever. The Admin loses control, and the user is stuck on an unmaintained island.

The Solution: Enforcing System-Wide Installs

To fix Electron on Windows Terminal Server, you must disable this fallback behavior. You need to tell the installer: "If you can't install system-wide as an admin, don't install at all."

We use electron-builder. The fix lies in switching from the default "One-Click" installer to a strictly configured NSIS target.

Step 1: Update package.json

Modify your build configuration to force perMachine installation and disable oneClick.

"build": {
  "win": {
    "target": "nsis"
  },
  "nsis": {
    "oneClick": false,
    "perMachine": true,
    "allowElevation": true,
    "allowToChangeInstallationDirectory": true
  }
}

Why this works:

  • oneClick: false: This disables the silent installation that often defaults to AppData. It forces a setup wizard.
  • perMachine: true: This defaults the installation path to C:\Program Files and requires User Account Control (UAC) elevation to install.
  • allowElevation: true: Allows the installer to ask for Admin rights.

With this configuration, if a standard user tries to update, they will be prompted for an Admin password. Since they don't have one, the update cancels. This is the correct behavior for a Terminal Server. The user remains on the old version until the IT Admin runs the update for everyone.

The Cleanup: Dealing with "Zombies"

Implementing the fix above prevents future shadow copies. However, it does not remove the existing ones.

If you already have users with shadow copies in their AppData, simply installing the new system-wide version won't help. Their shortcuts likely still point to the local AppData version.

The Cleanup Strategy

We attempted to script a cleanup process within the app (e.g., "On launch, check for AppData version and self-destruct"), but we found this unreliable due to file locking and permission quirks.

The most reliable solution for affected customers is a manual or script-based cleanup by their IT department:

  1. Delete the Directory: Remove the application folder from C:\Users\<username>\AppData\Local\YourApp.
  2. Fix Shortcuts: This is the step most people forget. The user's Desktop or Start Menu shortcut might still point to the deleted AppData location. These shortcuts must be deleted or updated to point to the C:\Program Files executable.

Summary

When deploying Electron on Windows Terminal Server, you cannot rely on default behaviors intended for personal laptops.

  1. Recognize the Risk: Non-admin users updating the app creates unmanageable shadow copies.
  2. Configure NSIS: Use perMachine: true and oneClick: false in electron-builder to enforce system-wide installation.
  3. Manage Expectations: Ensure your application communicates that updates on these systems are the administrator's responsibility.

By strictly enforcing system-wide installation, you return control to the IT Admins and ensure a consistent, reproducible environment for all your users.