Skip to content

Repository files navigation

TaskbarOrbit

A GNOME-style virtual desktop indicator that lives in the Windows taskbar.

CI Latest release Licence Platform Target framework

TaskbarOrbit rendering on five differently coloured taskbars: the active desktop as a pill, the others as dots

The active desktop is an elongated pill, the others are dots — sitting in the taskbar itself as a deskband (toolbar), not a tray icon or a floating window. It follows your taskbar's colour, so it looks the same whether that taskbar is dark, light, or tinted with your accent colour.

Built in C# / .NET Framework 4.8 on the single-file CSDeskBand library.


Read this before installing

TaskbarOrbit is experimental, and it runs inside explorer.exe.

A deskband that fails to load can leave you with no taskbar and no desktop after sign-in. That is inherent to the deskband model, not specific to this project. A recovery script ships with the installer and is described under Recovery — read that section before you install, not after.

Deskbands are a legacy extensibility point. Microsoft does not support them for new development, but they still work where the classic taskbar exists.

Screenshots

Three virtual desktops on a light and a dark taskbar. Nothing was configured between these two shots — only the Windows theme changed.

Light Dark
TaskbarOrbit on a light Windows taskbar, showing a dark pill and grey dots beside the system tray TaskbarOrbit on a dark Windows taskbar, showing a white pill and grey dots beside the system tray

The banner at the top is the same indicator on five different accent colours — the marker tones are derived from the taskbar background rather than hard-coded, so an accent-tinted taskbar works without a special case.

Compatibility

Platform Status
Windows 10 x64 Supported — the primary target
Windows 11 x64 + ExplorerPatcher or StartAllBack, set to the Windows 10 taskbar Supported
Windows 11 x64, stock taskbar Not supported — no Toolbars menu exists to host the band
32-bit Explorer, ARM64 Not supported

If the taskbar right-click menu has no Toolbars submenu, you are on a taskbar that cannot host deskbands. Nothing TaskbarOrbit does can change that.

How it works

Windows does not publicly expose virtual desktop enumerationIVirtualDesktopManager cannot list desktops. TaskbarOrbit reads the same registry data the community relies on (background):

  • HKCU\...\Explorer\VirtualDesktopsVirtualDesktopIDs, parsed as consecutive 16-byte GUIDs, giving the count and order.
  • CurrentVirtualDesktop in the same key, falling back to ...\Explorer\SessionInfo\<SessionId>\VirtualDesktops on older builds.

A 400 ms timer re-reads this and repaints only when the state actually changed.

These registry locations are not a public API contract and may move between Windows builds. When the data is missing or malformed the band renders nothing rather than guessing.

Install

Download TaskbarOrbit-Setup.exe from the Releases page.

The installer copies TaskbarOrbit.dll to C:\Program Files\TaskbarOrbit, registers it with 64-bit RegAsm /codebase, and adds a Start menu shortcut to the recovery script. It warns before installing on Windows 11 and refuses to run without the .NET Framework 4.x 64-bit runtime.

Then enable it: right-click the taskbar → ToolbarsTaskbarOrbit.

Registering does not auto-enable the band. That is deliberate — see Design notes.

Uninstall

Apps & features → TaskbarOrbit. The uninstaller unregisters the COM class, removes the CLSID directly as a fallback, and clears the settings key. Restart Explorer afterwards to clear the toolbar from the taskbar.

Recovery

If the taskbar or desktop does not come back:

  1. Ctrl + Shift + Esc opens Task Manager even with no taskbar.

  2. Run new task → tick Create this task with administrative privileges.

  3. Run the recovery script:

    C:\Program Files\TaskbarOrbit\emergency-uninstall.cmd
    

It sets the kill switch, unregisters every known copy, deletes the CLSID if RegAsm could not, and restarts Explorer.

Manually, if you would rather not trust a script:

reg add "HKCU\Software\TaskbarOrbit" /v Enabled /t REG_DWORD /d 0 /f
"%SystemRoot%\Microsoft.NET\Framework64\v4.0.30319\RegAsm.exe" /unregister "%ProgramFiles%\TaskbarOrbit\TaskbarOrbit.dll"
taskkill /f /im explorer.exe & start explorer.exe

Kill switch

HKCU\Software\TaskbarOrbitEnabled (DWORD). Set it to 0 and the band loads as an empty placeholder that does no work at all. This exists because RegAsm can only unregister an assembly it can still load — the kill switch works even when unregistration does not.

Delete the value to re-enable.

Build from source

Working on the code? Read DEVELOPMENT.md first — it covers the architecture, the shell-safety invariants you must not break, what has and hasn't been tested, and the prioritised backlog.

Requirements: Windows x64, .NET SDK, .NET Framework 4.8 targeting pack, Visual Studio 2022 Build Tools (MSBuild). Inno Setup 6 only if you want to build the installer locally.

msbuild src\TaskbarOrbit.csproj /restore /p:Configuration=Release /p:Platform=x64

Output: src\bin\x64\Release\net48\TaskbarOrbit.dll

Development loop

Explorer locks the registered DLL while the band is loaded, so use the script — it stops Explorer only when it has to, and will not restart Explorer with a DLL that failed to build or register:

# Administrator PowerShell
.\scripts\dev-rebuild.ps1              # build, re-register, reload Explorer
.\scripts\dev-rebuild.ps1 -SkipRegister  # build only, leaves the shell alone

Keep an elevated window open with scripts\emergency-uninstall.cmd ready before testing anything that touches shell startup. Test sign-out and reboot in a disposable VM, not on your working machine.

Design notes

Everything here follows from one constraint: this code runs inside the shell.

  • The band never auto-enables. CSDeskBand can ask ITrayDeskband to persist a band into the saved taskbar layout at registration time. TaskbarOrbit does not, because that arms the band on every subsequent Explorer start — including sign-in, where a failure costs you the whole shell.
  • Nothing happens in the constructor. The control is created on first request, behind a fallback to an inert placeholder. The poll timer starts on OnHandleCreated, not before.
  • Every callback is contained. Timer ticks, painting, handle creation and disposal all swallow their exceptions. A broken indicator is acceptable; a broken shell is not.
  • No network, no file I/O, no dependencies beyond the framework — a single strong-named DLL, so nothing has to be resolved at load time.
  • The COM GUID is pinned and CI fails if it changes, because it is what every existing registration points at. AssemblyVersion is pinned at 1.0.0.0 for the same reason; FileVersion carries the real release number.

Taskbar colour matching

The band follows the taskbar rather than assuming a dark theme. It resolves the background by replicating ExplorerPatcher's own GetTaskbarColor(), in the same order:

  1. High contrast — use the system window colour.
  2. Accent on Start and taskbar (ColorPrevalence) — AccentDark2 in dark mode, AccentLight2 in light mode, read from the AccentPalette blob.
  3. Otherwise#202020 dark, #F3F3F3 light.

Marker colours are then derived from that background's luminance rather than hard-coded per theme, so an accent-coloured or high-contrast taskbar gets sensible markers without a special case. The active pill uses Fluent's TextFillColorPrimary opacity (opaque white on dark, 89.4% black on light); the dots use a lower opacity chosen so the dark-theme result matches the contrast the design was tuned to by eye.

The theme is re-checked every fifth poll — a couple of seconds — because theme changes are rare and desktop switches are not.

Not implemented

Transparency. The band paints an opaque rounded rectangle. When the taskbar is acrylic (EnableTransparency), no flat colour matches it exactly and the band will read as a slightly solid patch. The real fix is painting no background at all and letting the taskbar show through, which is on the roadmap.

Roadmap

  • Transparent background, so the taskbar shows through instead of being matched.
  • Registry change notifications instead of polling.
  • Options UI for size, spacing and colours.
  • Out-of-process helper with a thin drawing-only deskband, to shrink the amount of code that can take the shell down.

Repo layout

TaskbarOrbit/
├─ src/                      # net48, x64
│  ├─ TaskbarOrbit.csproj
│  ├─ CSDeskBand.cs          # vendored, unmodified — see THIRD-PARTY-NOTICES.md
│  ├─ Deskband.cs            # COM entry point
│  ├─ MyBandControl.cs       # state + rendering
│  └─ TaskbarOrbit.snk       # strong-name key (committed on purpose)
├─ installer/TaskbarOrbit.iss
├─ scripts/
│  ├─ dev-rebuild.ps1
│  └─ emergency-uninstall.cmd
├─ .github/workflows/        # ci · release-please · publish
├─ Directory.Build.props     # version, stamped by release-please
└─ version.txt

Releases

Conventional Commits on feature branches → PR to main → release-please opens a release PR with the changelog and version bump → merging it tags the release and triggers the publish workflow, which attaches the installer, a portable zip and SHA256SUMS.txt. Releases are marked pre-release while the project is 0.x.

Contributing

Issues and pull requests are welcome. CONTRIBUTING.md covers the dev loop and, more usefully, which kinds of change are likely to be declined and why — worth two minutes before you write any code.

Bug reports are most useful with your Windows build and which taskbar you are running; the issue template asks for both. If you currently have no taskbar, run recovery first — it takes about a minute.

Security problems should go through private vulnerability reporting rather than a public issue. See SECURITY.md.

Licence

MIT — see LICENSE. Third-party code is listed in THIRD-PARTY-NOTICES.md.

Acknowledgements

  • CSDeskBand by dsafa (MIT) — the single-file deskband base this is built on.
  • AudioBand — reference for what a production-quality Windows deskband looks like.
  • The community work on virtual desktop internals, particularly Meziantou's write-up.

Releases

Packages

Used by

Contributors

Languages