Watch the video:

(Almost) no introduction necessary
The TcNo Account Switcher is my biggest project to date. There are over 603,000 downloads from GitHub alone and reliably over 15,000 users every day. This project has solved one of my biggest pain points, juggling multiple accounts.
This project and its modular system are described in detail on the project’s Wiki

The Problem
Having an account for Steam, Epic Games, Ubisoft, EA, and so on. But juggling multiple accounts, such as an alternative accounts on each, is a lot of effort. Consider another Steam account for storing more items than the Steam inventory allows for a single account, or an account from another region, or from a friend, and so on. The account management quickly becomes a headache.
Having accounts managed from a centralized launcher is the perfect solution to this growing issue.
The Solution
The TcNo Account Switcher works by the fact that accounts stay logged-in once a user signs in. This cached state is stored somewhere, and just switching that data for data from another account allows users to be simultaneously logged into multiple accounts when this is not possible normally.
Years since this project’s release, Steam has finally incorporated a built-in account switcher, but with heavy limits, such as only being able to use up to 5 accounts.
Monitoring for file and registry changes when logging in, logging out, and closing/restarting programs like Steam allows me to quickly find where this information is stored. The process is described on the Wiki and in this video:
Watch the video:
Once data locations are found using WinMerge, Nirsoft RegistryChangesView, and SysInternals Process Monitor, they are added to the modular account switching platform system in a simple JSON
text file here on GitHub.
Features
- Statistics: Each account switch, page visit, and more is collected and displayed privately to the user. Completely anonymous usage information is added to global totals for debugging and improving the software through my private Node.js API.
- Crash Reports: Crash Reports are automatically sent to my website for processing.
- Tray integration: Accounts can be switcher from the Windows Tray on the Start Bar. No need to open the program.
- Game Account Info: Integration with third-party API sources for Apex Legends, Counter-Strike, and Overwatch lets users view in-game ranks under each account.
- Streamer Mode: Private info such as login usernames, SteamIDs and more are hidden with a simple toggle.
- Automatic Updates: This program uses delta updates, so incredibly small difference files are downloaded to patch and update the program.
- Platform Options: Steam (and a few other platforms) have their user states (e.g., Online, Invisible, Offline) adjustable through data stored on a user’s PC. This project allows easy access to that.
- Platform Backups: Right-clicking an account allows you to export and backup screenshots, game configs, and more from a user profile or transfer to another.
- Platform Cache Cleanup: With a few simple clicks, users can clean cache that builds up for platforms and even intentionally clear data, removing the history of accounts that were logged onto on a specific device (this was a surprisingly popular request).
- Protocol Support: Using
tcno:\\<command>
allows easy access to the power of the TcNo Account Switcher through third-party tools, an alternative to the CLI. - CEF and WebView2: Both Chrome Embedded and Microsoft WebView2 can be switched between, allowing more compatibility - especially on older systems.
- Themes: Custom CSS themes can be created and loaded easily
- Installer: NSIS was chosen as an installer creator, with 7-zip integration for even smaller downloads. Portable versions are also available, as this program runs in-place.
- Multilingual: Through AI/ML and generous users through CrowdIn the project is available in all major languages. Switch with a few clicks. Users are credited through use of Crowdin’s API in-app.
- Game Launcher: Launch games and other programs (autodetected/manually added) from in-app.
- Discord RPC: An optional extra to let others know you’re in-app.
Difficulties
This project is absolutely massive in scope. Here are some of the most challenging issues that I overcame:
Patch Updates
While simple in theory, getting a patch system to work reliably was difficult. Currently, with the finalized process, when I push an update, the CI/CD builds the program (AppVeyor via GitHub Actions), signs (if necessary), and differences the new binaries and files with the old ones. Differences are compressed and uploaded to an FTP server, where they are distributed by a CDN. These differences are downloaded and applied to a user’s computer through another process.
The updater gets complex when: files need to have their contents verified through hashes; differences are applied; files in areas like Program Files are changed, requiring admin and even updating the updater. All of these were worked around.
Unfortunately, some users were stuck on versions with broken updaters, and as this “just worked, they never saw the need to update. Funny, actually. I’m happy that my software was reliable enough to not update, but also a little disheartened they didn’t get to try new features. Some may still not know there’s support for launchers other than Steam.
WPF
Wow. If you’ve ever used WPF to try and ‘skin’ elements, you know how difficult it is. While the language is great for customizing components, it’s only easy to a certain degree, until you basically need to rewrite entire components. While I followed this route for a while after moving to C#, I pursued using an embedded browser to get closer to other programs using libraries like Electron. This was a great choice both for animations, customizability, and so much more.
WebView2
One of the most surprising issues was running into issues with Microsoft’s own tool set. The WebView2 component, when used with the official .NET MAUI integration, has a few quirks. The project uses a custom title bar in HTML that allows minimizing, closing, and moving the window around on the screen. However, the ability to drag and drop elements is just missing. The title bar or accounts or platforms in their respective lists have the same issue. I hit this roadblock while updating to use Blazor and Direct Injection techniques and had to revert away from .NET MAUI because of this.
You can see the MAUI behavior on the github.com/dotnet/maui issues page [2022], then moved to github.com/MicrosoftEdge/WebView2Feedback [2022] was closed as Not Planned
a year later [2023]. I followed the work as it was pushed as planned for the next version, then the next, and so on until I was forced to either replace the component entirely or revert to WPF.
Runtimes
While some runtimes auto-install on launch, using .NET Core and Microsoft WebView2 do not reliably come pre-installed, stay updated, or auto-install on launch. This process has to be handled by the programmer, or end user.
While downloading runtimes is easy and documented, automated runtime checks and installations are much better than users with preventable errors. The only way to create a program that doesn’t need runtimes is to use a much lower-level language or distribute the project with required runtimes. The latter of which ballooned download sizes, so C++
was chosen to check and install runtimes for the user.
The C++
wrapper (as any EXE in this project requires runtimes and can be launched through the CLI/Tray/Protocol and more) checks the Windows registry, compares versions, downloads, and installs required runtimes - once the user has confirmed these actions. While it is not perfect to have 2 EXEs per process, it is preferable to errors from the level of control the program wishes to give.

Data storage directories
The program needs to store settings, accounts, and more. I originally picked next to the program; however, when installed to a folder like Program Files
the program requires elevated permissions to run, such as Admin.
Moving to My Documents sounded good, as games and some programs store information there; however, users came across many issues, such as OneDrive interfering with its files.
Moving to %LocalAppData%
was eventually chosen as the best location to store files and has worked perfectly since.
Updating architecture
During the project’s development, I learned a lot about databases, and started to explore languages other than C#, HTML/CSS/JS/PHP. At a stage, I was more than comfortable using Node.js, and no longer using Apache to host my website. Instead, I was hosting everything through Nginx, on an entirely different stack now using LEMP [Linux, Nginx, MySQL, PHP] instead of WAMP [Windows, Apache, MySQL, PHP].
I had not created software that I had supported for so long; I was changing the underlying technologies before, so this was a learning experience. I moved away from PHP entirely to instead use Express.js, and serve the same endpoints, maintaining support for older versions (still in use).