Skip to content

About

Master repo for TrayAppDotNET projects

Resources

Stars

1 star

Watchers

1 watching

Forks

Latest commit

 

History

576 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TrayAppDotNET TrayAppDotNET logo

A suite of Windows 11 apps focused around one of the most under-loved pieces of UX ever.

License Latest release GitHub stars Discord members Website

Overview

These are my projects for replacing, and adding to, the Windows 11 tray system apps. For the best effect, I recommend removing the stock Windows tray icons with Windhawk.

Stock Windows 11
Stock Windows 11 tray
TrayAppDotNET
TrayAppDotNET tray
This is an incomplete example. Stock tray icons were removed with this Windhawk mod.

Project status: These apps should all be considered to be in alpha. They're exceptionally stable, but there are still large gaps in some apps that need to be completed.

Installation

Downloads Page | Grab the latest installer for whichever app(s) you'd like, or download the bundled suite. Then install it. Done.

Notes:
  • Installer_{AppName}_{version}.exe is a single-app installer.
  • Installer_TrayAppDotNET_{version}.exe is the app bundle, with a GUI selector for which apps to install.

These apps can all run portably. To these apps, there is not much difference between running portable vs being installed. All app settings and logs are saved to %LocalAppData%\TrayAppDotNET by default.

Configuration

In theory, any app settings you may need are properly exposed in the app's own settings UI. If this is not enough, the vast majority of parameters/constants for any given app are stored to and read from that app's own settings.xml file.

In the future, apps will also generate a file for UI constants. Every. single. UI constant. is defined in AXAML.

Gallery

Preview BatteryTrayAppDotNET 

Preview BrightnessTrayAppDotNET 

Control the actual brightness of external displays, as well as Windows brightness (laptops) and Windows Night Light.

I kept running into DDC failures with Twinkle Tray, and I don't like Electron. I took inspiration from the fluent layout it used, so many thanks to Xander Franfangos for that! This was the first "major" TADN app I made. There are quite a few features.

Preview

Features
  • User profiles
  • Windows Night Light integration
  • Brightness synchronization
  • Control disengagement
  • Day/Night curve
    • Auto re-engage
    • Quick-swap
    • Disengage timer
    • Graphical curve editor
    • Obliquity compensation
  • Robust DDC recovery and fast apply
  • Windows brightness support
  • Display management
    • Renaming
    • Brightness normalization
    • DDC tuning
  • Mouse wheel tray icon
    • Works with touchpad
    • No global mouse hook
  • Dynamic tray icon
    • Solar eclipse visual shows current brightness level

Preview FanControlTrayAppDotNET 

Not to be confused with the very popular "Fan Control" project. I find that app cumbersome, and I find it odd its not open source. Like Fan Control, this project is essentially a UX wrapper around LibreHardwareMonitor, and nothing more.

Preview NetworkTrayAppDotNET 

As simple as it gets. The still-embedded Win10 Windows Network flyout works great, so this little app just invokes it. Still comes with some quick-access features via its tray context menu.

Preview

Preview TaskManagerTrayAppDotNET 

A "reimplementation" of the Windows 11 Task Manager.

The official Task Manager has become far too stuttery for me. While "fixing that", some extra bells and whistles were added.

Preview

Features
  • Combined process + details view
    • Zoom + stretch
    • Dynamic sum totals
    • Multi-select
    • View options
    • Searchable columns
    • Column customization
  • Enhanced search
    • Search saving
  • Enhanced performance view
    • Preview graphs
    • Draggable device list
    • Live cursor graph hover
    • Physical memory layout
    • Single core metrics
  • Background mode
  • Modern tray icon with display modes

Preview VolumeTrayAppDotNET 

A volume mixer and audio endpoint manager.

EarTrumpet users will find this familiar. I took inspiration from it in this design. Originally, I'd modified EarTrumpet to sort its mixer bottom-up like this, to minimize mouse movement distance. Since that project seems to have been abandoned, I took a crack at the whole thing.

Preview

Features
  • Configurable flyout structure
  • Recording device support
  • Bluetooth management
  • Device management
    • Renaming
    • Defaulting
    • Visibility
  • Smooth peak meters
    • The visual indicator of the current volume level
  • Touchpad scroll tray icon
    • No global mouse hook

All apps come with the following features:

  • Flyout undocking (where applicable)
  • Searchable settings (with fuzzing)
  • Live theme customization
  • Rebindable global hotkeys (Task Manager instead has fixed table and window shortcuts plus an optional Ctrl+Shift+Esc takeover)
  • Update system
  • Crash recovery
  • Customizable tray menus (where applicable)

User documentation for every app and the shared features is in documentation/docs.

Development

I use Visual Studio 2026 with this project. Here are the necessary tools to compile it yourself.

  • The .NET SDK pinned in global.json (.NET 10)
  • Visual Studio Build Tools 17 with:
    • Desktop C++ environment
    • MSVC v143
    • Windows 11 SDK 10

This mono-repo is set up such that every app also has its own slnx file, if opening only one app is desired. Fan Control vendors LibreHardwareMonitor and its other dependencies as git submodules, so clone with --recurse-submodules (or run git submodule update --init --recursive).

# Everything, Debug (apps, Common, generators, installer factory, tests)
dotnet build TrayAppDotNET.slnx -c Debug -p:Platform=x64
dotnet test TrayAppDotNET.slnx -c Debug -p:Platform=x64 --no-build

# One app, Release: publishes Native AOT and stamps Installer_<App>_<build>.exe beside it
dotnet build VolumeTrayAppDotNET\src\VolumeTrayAppDotNET.csproj -c Release -p:Platform=x64
# Add -p:TrayAppDotNETStampAppInstaller=false to skip the installer stamping while iterating

The installer elevated-worker tests in TrayAppDotNETInstaller.Tests and Task Manager's opt-in kill-helper smoke test touch elevation; see .agents/PROJECT_MAP.md for the test projects, build files and CI workflows (.github/workflows/tests.yml runs every test project on pushes and pull requests).

Misc Details

Launch arguments

Argument Intended use Behavior
No arguments User Start the app normally under the crash watcher.
--autostart Startup shortcut Mark a sign-in launch. The Run on startup shortcut passes it, the watcher forwards it to every monitored process it starts, and apps with a Start minimized option only honor that option when it is present.
--hidden Installer Start in the notification area without showing a window, whatever the startup settings say. The installer passes it to the apps it launches when it finishes, and the watcher forwards it to every monitored process it starts. Only Task Manager opens a window at startup, so it is the only app this changes.
--settings-dir <path> User/script Use <path> instead of %LOCALAPPDATA%\TrayAppDotNET\<App> for settings.xml, logs and the app's other data files. Relative paths resolve against the working directory and environment variables such as %USERPROFILE% expand. The folder is created on first use. If the value after the flag is missing or is not a usable folder path, the app exits with code 2; a path that ends in a backslash must not be quoted. The watcher, the rendering restart, Restart from installed, the update restart and Brightness's Night Light and DDC helpers keep the override. Task Manager's elevated helpers don't receive it and write no files; the broker's log lines go to the app's own log. Turning on Run on startup from an instance with an override writes it into the startup shortcut, and a new override folder does not turn Run on startup on by itself. The single-instance rule is unchanged, so starting a second copy with a different folder still replaces the running one: it asks the running copy to exit through its normal exit path and ends it by force only after five seconds. The Windows uninstall entry passes no override, so removing settings there deletes only the default folder.
--installer or --install-gui User Open the one-page installer. Local installation is selected by default. Selecting system installation causes Windows to display a UAC prompt after Install is clicked. The window writes no settings and creates no startup shortcut.
--install-headless <scope> User/script Install without opening a window, print progress lines ([NN%] stage) and the result to the parent console or redirected standard output, then exit without starting the installed copy. <scope> is local or system. System scope causes Windows to display a UAC prompt.
--install <scope> User/script Compatibility alias for --install-headless <scope>.
--installlocal User/script Install locally without opening a window, then start the installed instance (through the desktop shell with --hidden when the caller is elevated).
--installsystem User/script Install system-wide without opening a window, display the Windows UAC prompt, then start the installed instance (through the desktop shell with --hidden when the caller is elevated).
`--desktop-shortcut <true false>` User/script
`--start-menu-shortcut <true false>` User/script
`--run-as-administrator <true false>` Installer/script
--uninstall <installDir> --scope <scope> App/Windows uninstall entry Open the uninstaller for the supplied installation. Confirming a system uninstall causes Windows to display a UAC prompt; declining it keeps the window open with the reason. The window writes no settings.
--uninstall-gui <installDir> --scope <scope> App/Windows uninstall entry Alias for --uninstall.
--uninstall-headless <scope> User/script Uninstall without opening a window, printing progress lines ([NN%] stage) to the parent console or redirected standard output. <scope> is local (or user, localappdata) or system (or programfiles); store scopes are rejected. System scope causes Windows to display a UAC prompt.
`--delete-settings <true false>` User/script
--scope <scope> App helper Select an installation for uninstall operations. Accepted values are user, local, localappdata, system, programfiles, store, and windowsstore.
--watcher App helper Run the crash watcher process. It restarts the app after a crash, stops when the app exits with code 0 or 1, and after exit code 3 while it sees Windows ending the session restarts it only once the session turns out to continue. Exit code 3 at any other time counts as a crash. Every restart counts toward the repeated-crash limit.
--monitored --watcher-pid <pid> App helper Run the monitored app process owned by the watcher with the supplied watcher PID.
--watcher-pid <pid> App helper Supplies the watcher PID to a monitored app instance.
--install-system --source <sourceExe> --build <buildNumber> App helper Continue a system installation after Windows has displayed the UAC prompt, then write system uninstall and shortcut metadata.
--sync-start-menu [--remove-scope <scope>] App helper Reconcile the Start Menu shortcuts of every profile. Refused (exit code 1) when not elevated.
`--uninstall-prepare --scope [--delete-settings <true false>] [--settings-dir ]` App helper
--progress-pipe <name> App helper Named pipe through which an elevated install or uninstall helper reports its progress stages to the process that started it.
--remove-scope <scope> App helper Scope value consumed by --sync-start-menu when removing shortcuts for an uninstalling scope.
--update-apply App helper Run by the installed exe itself: copy the downloaded package into a staging folder inside the install folder, verify its SHA-256, and replace the app's payload files as a journaled transaction after the running app exits. Windows displays a UAC prompt only when the installation directory requires elevation.
--update-restart App helper Restart the installed app after update commit or rollback, then clean the staging directory. This process is deliberately not elevated.

Architecture

  • Apps: .NET 10, Avalonia 12, compiled to Native AOT.
  • Installers: .NET Framework 4.8, WPF (Installer_<App>_<version>.exe and the suite installer; each app also has its own built-in install and uninstall windows)

AI Usage

I make use of frontier LLM's heavily in this project. For what it's worth, I am actually a software engineer; I do actually read and review what gets written, as well as use my own fingers to write code myself sometimes - not just prompts.

I am not about to spend 6 months slogging through a thousand Windows API's and ABI's just for one feature to barely work, or another 2 months refactoring the entire codebase for any number of reasons. However, the architecture and design choices are all done by me. I keep stylesheets around to somewhat enforce my own standards upon LLMs.

I allow LLMs complete reign over spamming test code. I do not write test-driven code, and any broken tests will inevitably be cleaned by an LLM. The more "coverage", the merrier.

My AI code philosophy aligns closely with Nonary's if you want to read more. | Link

Versioning

These projects don't use semver. There is no API contract to uphold, and I would prefer not assigning bizzare meaning to semvers that would cause them to look like they're flying all over.

The TrayAppDotNET version increments every single release. If an app isn't scheduled to have a new release, or has no changes, the publish workflow will go grab the previous release artifact for that app and re-publish it. This is done so it is consistently simple to download build artifacts.

Note: The installer wrapper has no published version and simply aligns itself with the latest TrayAppDotNET release. Any re-published apps will be packaged into the latest installer release.

Translation

All these apps are fully localized with resx, but not currently integrated with any translation providers (Weblate, etc.).

Localization files live in {APP}/src/Localization/Strings.{LANGUAGE}.resx.

There is a localization file for each app, the installer, and one in the Common project for strings shared across all apps.

License

GNU General Public License v3.0

About

Master repo for TrayAppDotNET projects

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages