Skip to content

Commit 5333fca

Browse files
committed
fix: Add startup launcher for tray autostart
1 parent 590cda2 commit 5333fca

8 files changed

Lines changed: 418 additions & 111 deletions

File tree

.github/workflows/release.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ jobs:
3131
New-Item -ItemType Directory -Force -Path $packageDir | Out-Null
3232
3333
Copy-Item -LiteralPath "out\SuperLightBattery.exe" -Destination $packageDir
34+
Copy-Item -LiteralPath "out\SuperLightBatteryLauncher.exe" -Destination $packageDir
3435
Copy-Item -LiteralPath "out\SuperLightBatteryInstaller.exe" -Destination $packageDir
3536
Copy-Item -LiteralPath "README.md" -Destination $packageDir
3637
Copy-Item -LiteralPath "LICENSE" -Destination $packageDir
@@ -42,9 +43,7 @@ jobs:
4243
SuperLightBattery $tag
4344
4445
Assets:
45-
- SuperLightBattery-$tag-win-x64.zip: recommended download; contains the app, installer, README, and license.
46-
- SuperLightBattery.exe: standalone CLI/tray executable.
47-
- SuperLightBatteryInstaller.exe: tiny per-user installer/launcher; requires SuperLightBattery.exe next to it when installing.
46+
- SuperLightBattery-$tag-win-x64.zip: recommended download; contains the launcher, tray/CLI app, installer, README, and license.
4847
"@ | Set-Content -LiteralPath (Join-Path $dist "release-notes.md") -Encoding UTF8
4948
5049
- name: Create GitHub release
@@ -56,7 +55,5 @@ jobs:
5655
$tag = $env:GITHUB_REF_NAME
5756
gh release create $tag `
5857
"dist/SuperLightBattery-$tag-win-x64.zip" `
59-
"out/SuperLightBattery.exe" `
60-
"out/SuperLightBatteryInstaller.exe" `
6158
--title $tag `
6259
--notes-file "dist/release-notes.md"

README.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@
22

33
A tiny Windows battery indicator for Logitech LIGHTSPEED mice — no G HUB, no service, no telemetry.
44

5-
SuperLightBattery shows the battery level of a Logitech LIGHTSPEED mouse (PRO X Superlight family and similar HID++ 2.0 devices) in the system tray. Two small executables, statically linked, no background framework. Tested on Windows 11.
5+
SuperLightBattery shows the battery level of a Logitech LIGHTSPEED mouse (PRO X Superlight family and similar HID++ 2.0 devices) in the system tray. Small native binaries, statically linked, no background framework. Tested on Windows 11.
66

77
## Install
88

99
1. Download the latest release zip from the [Releases](https://github.com/Lken-cmd/SuperLightBattery/releases) page.
10-
2. Unzip it anywhere. Keep `SuperLightBattery.exe` and `SuperLightBatteryInstaller.exe` next to each other.
10+
2. Unzip it anywhere. Keep `SuperLightBattery.exe`, `SuperLightBatteryLauncher.exe`, and `SuperLightBatteryInstaller.exe` next to each other.
1111
3. Run `SuperLightBatteryInstaller.exe`.
1212
4. Click **Install**. The tray icon appears, and the app starts automatically at every logon from then on.
1313

14-
No admin rights are required. Files go to `%LOCALAPPDATA%\SuperLightBattery` and one value under `HKCU\Software\Microsoft\Windows\CurrentVersion\Run`.
14+
No admin rights are required. Files go to `%LOCALAPPDATA%\SuperLightBattery` and a `SuperLightBattery` shortcut is added to the current user's Startup folder.
1515

1616
## Use
1717

@@ -39,7 +39,7 @@ Run the installer again and click **Uninstall**, or:
3939
SuperLightBatteryInstaller.exe --uninstall
4040
```
4141

42-
This deletes the files, removes the registry entry, and stops the running tray. If a file is locked because the tray is still active, the installer schedules it for deletion at next reboot.
42+
This deletes the files, removes the startup shortcut, cleans up any old registry startup entry, and stops the running tray. If a file is locked because the tray is still active, the installer schedules it for deletion at next reboot.
4343

4444
## CLI
4545

@@ -49,7 +49,6 @@ For scripting and one-off checks, `SuperLightBattery.exe` has a small CLI:
4949
SuperLightBattery.exe --list-devices # list candidate Logitech HID interfaces
5050
SuperLightBattery.exe --probe # test HID++ communication and battery feature
5151
SuperLightBattery.exe --once # print a single JSON snapshot and exit
52-
SuperLightBattery.exe --tray # run the tray app (default)
5352
```
5453

5554
`--once` example output:
@@ -103,31 +102,32 @@ The build writes:
103102

104103
```text
105104
out\SuperLightBattery.exe
105+
out\SuperLightBatteryLauncher.exe
106106
out\SuperLightBatteryInstaller.exe
107107
```
108108

109-
Both binaries are statically linked against the MSVC CRT (`/MT`), come in around 190 KB and 160 KB, and depend only on core Windows DLLs (`kernel32`, `user32`, `gdi32`, `shell32`, `setupapi`, `hid`, `advapi32`, `comctl32`). The icon is regenerated from `assets/generate-icon.ps1` if missing.
109+
The app and installer are statically linked against the MSVC CRT (`/MT`); the small startup launcher is CRT-free. The binaries depend only on core Windows DLLs (`kernel32`, `user32`, `gdi32`, `shell32`, `setupapi`, `hid`, `advapi32`, `comctl32`, `ole32`). The icon is regenerated from `assets/generate-icon.ps1` if missing.
110110

111111
## Troubleshooting
112112

113113
**The tray icon shows "unavailable" and the menu has nothing useful.**
114114
Run `SuperLightBattery.exe --probe` from a terminal. It will list which Logitech HID collections are detected and which (if any) answer HID++. Make sure the receiver is plugged in and the mouse is paired and on.
115115

116-
**A console window flashes when I run `SuperLightBattery.exe --tray` directly.**
117-
The tray binary is a console-subsystem app; the autostart entry hides the console by going through `SuperLightBatteryInstaller.exe --launch-tray`, which spawns the tray with `CREATE_NO_WINDOW`. For a console-free manual launch, use the installer or `--launch-tray`.
116+
**Why are there two app executables?**
117+
`SuperLightBattery.exe` is the real tray and CLI app. `SuperLightBatteryLauncher.exe` is the tiny windowless startup launcher shown by Startup Apps.
118118

119119
**Icon looks blurry on a high-DPI display.**
120120
The tray icon renders at the shell's requested pixel size with 4× supersampling and is per-monitor DPI aware. If it still looks soft, open an issue and include your DPI scaling (Settings → System → Display → Scale).
121121

122-
**Installer says "SuperLightBattery.exe must sit next to the installer."**
123-
The two executables need to be in the same folder. The release zip ships them that way already; re-download the full archive if they got separated.
122+
**Installer says a SuperLightBattery file must sit next to the installer.**
123+
The tray/CLI app, startup launcher, and installer need to be in the same folder. The release zip ships them that way already; re-download the full archive if they got separated.
124124

125125
**Tray won't exit during uninstall.**
126126
The installer posts `WM_CLOSE` to the tray window and waits briefly. If the tray was unresponsive at that moment, exit it manually from its right-click menu and run uninstall again. The locked files were already scheduled for deletion at next reboot.
127127

128128
## Releases
129129

130-
Tagged releases (`v*`) trigger a GitHub Actions build on `windows-latest` that zips both binaries plus the README and LICENSE and publishes a GitHub Release.
130+
Tagged releases (`v*`) trigger a GitHub Actions build on `windows-latest` that zips the binaries plus the README and LICENSE and publishes a GitHub Release.
131131

132132
```powershell
133133
git tag v1.0.0

assets/installer.manifest

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,13 @@
22
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
33
<assemblyIdentity version="1.0.0.0" processorArchitecture="*" name="SuperLightBatteryInstaller" type="win32"/>
44
<description>SuperLightBattery installer</description>
5+
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
6+
<security>
7+
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
8+
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
9+
</requestedPrivileges>
10+
</security>
11+
</trustInfo>
512
<dependency>
613
<dependentAssembly>
714
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*"/>

build.ps1

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,17 @@ $IconGenerator = Join-Path $AssetsDir "generate-icon.ps1"
1212
$InstallerIconPath = Join-Path $AssetsDir "SuperLightBatteryInstaller.ico"
1313
$InstallerIconGenerator = Join-Path $AssetsDir "generate-installer-icon.ps1"
1414

15-
$ToolSource = Join-Path $Root "src\superlightbattery.c"
16-
$ToolRc = Join-Path $Root "src\app.rc"
17-
$ToolRes = Join-Path $OutDir "app.res"
18-
$ToolExe = Join-Path $OutDir "SuperLightBattery.exe"
19-
$ToolObj = Join-Path $OutDir "superlightbattery.obj"
15+
$AppSource = Join-Path $Root "src\superlightbattery.c"
16+
$AppRc = Join-Path $Root "src\app.rc"
17+
$AppRes = Join-Path $OutDir "app.res"
18+
$AppExe = Join-Path $OutDir "SuperLightBattery.exe"
19+
$AppObj = Join-Path $OutDir "superlightbattery.obj"
20+
21+
$LauncherSource = Join-Path $Root "src\launcher.c"
22+
$LauncherRc = Join-Path $Root "src\launcher.rc"
23+
$LauncherRes = Join-Path $OutDir "launcher.res"
24+
$LauncherExe = Join-Path $OutDir "SuperLightBatteryLauncher.exe"
25+
$LauncherObj = Join-Path $OutDir "launcher.obj"
2026

2127
$InstallerSource = Join-Path $Root "src\installer.c"
2228
$InstallerRc = Join-Path $Root "src\installer.rc"
@@ -91,20 +97,29 @@ function New-ClArgs {
9197
[string]$Obj,
9298
[string]$Res,
9399
[string[]]$Libs,
94-
[string[]]$LinkArgs = @()
100+
[string[]]$CompileArgs = @(),
101+
[string[]]$LinkArgs = @(),
102+
[switch]$NoGl,
103+
[switch]$NoLtcg
95104
)
96105

97106
$args = @(
98107
"/nologo",
99108
"/std:c11",
100109
"/W4",
101110
"/O1",
102-
"/GL",
103111
"/Gw",
104112
"/Gy",
105113
"/MT",
106114
"/DUNICODE",
107-
"/D_UNICODE",
115+
"/D_UNICODE"
116+
)
117+
118+
if (-not $NoGl) {
119+
$args += "/GL"
120+
}
121+
$args += $CompileArgs
122+
$args += @(
108123
"/Fo:`"$Obj`"",
109124
"/Fe:`"$Exe`"",
110125
"`"$Source`"",
@@ -114,34 +129,51 @@ function New-ClArgs {
114129
)
115130

116131
$args += $LinkArgs
117-
$args += @("/LTCG", "/OPT:REF", "/OPT:ICF", "/INCREMENTAL:NO")
132+
if (-not $NoLtcg) {
133+
$args += "/LTCG"
134+
}
135+
$args += @("/OPT:REF", "/OPT:ICF", "/INCREMENTAL:NO")
118136
$args += $Libs
119137
return ($args -join " ")
120138
}
121139

122-
$toolRcArgs = New-RcArgs -Source $ToolRc -Output $ToolRes
140+
$appRcArgs = New-RcArgs -Source $AppRc -Output $AppRes
141+
$launcherRcArgs = New-RcArgs -Source $LauncherRc -Output $LauncherRes
123142
$installerRcArgs = New-RcArgs -Source $InstallerRc -Output $InstallerRes
124143

125-
$toolArgs = New-ClArgs `
126-
-Source $ToolSource `
127-
-Exe $ToolExe `
128-
-Obj $ToolObj `
129-
-Res $ToolRes `
144+
$appArgs = New-ClArgs `
145+
-Source $AppSource `
146+
-Exe $AppExe `
147+
-Obj $AppObj `
148+
-Res $AppRes `
149+
-LinkArgs @("/SUBSYSTEM:CONSOLE") `
130150
-Libs @("setupapi.lib", "hid.lib", "shell32.lib", "user32.lib", "gdi32.lib")
131151

152+
$launcherArgs = New-ClArgs `
153+
-Source $LauncherSource `
154+
-Exe $LauncherExe `
155+
-Obj $LauncherObj `
156+
-Res $LauncherRes `
157+
-CompileArgs @("/GS-") `
158+
-LinkArgs @("/SUBSYSTEM:WINDOWS", "/ENTRY:LauncherEntry", "/NODEFAULTLIB") `
159+
-NoGl `
160+
-NoLtcg `
161+
-Libs @("kernel32.lib", "user32.lib")
162+
132163
$installerArgs = New-ClArgs `
133164
-Source $InstallerSource `
134165
-Exe $InstallerExe `
135166
-Obj $InstallerObj `
136167
-Res $InstallerRes `
137168
-LinkArgs @("/SUBSYSTEM:WINDOWS") `
138-
-Libs @("shell32.lib", "user32.lib", "advapi32.lib", "gdi32.lib", "comctl32.lib")
169+
-Libs @("shell32.lib", "ole32.lib", "uuid.lib", "user32.lib", "advapi32.lib", "gdi32.lib", "comctl32.lib")
139170

140-
$cmd = "`"$vsdevcmd`" -arch=x64 -host_arch=x64 >NUL 2>NUL && rc $toolRcArgs && rc $installerRcArgs && cl $toolArgs && cl $installerArgs"
171+
$cmd = "`"$vsdevcmd`" -arch=x64 -host_arch=x64 >NUL 2>NUL && rc $appRcArgs && rc $launcherRcArgs && rc $installerRcArgs && cl $appArgs && cl $launcherArgs && cl $installerArgs"
141172
cmd.exe /d /s /c $cmd
142173
if ($LASTEXITCODE -ne 0) {
143174
exit $LASTEXITCODE
144175
}
145176

146177
Write-Host "Built out\SuperLightBattery.exe"
178+
Write-Host "Built out\SuperLightBatteryLauncher.exe"
147179
Write-Host "Built out\SuperLightBatteryInstaller.exe"

0 commit comments

Comments
 (0)