Skip to content

Commit 6bbb665

Browse files
Amtrtmclaude
andcommitted
Add VBS launcher for windowless execution and fix system tray in pkg builds
- Add launcher/RedAlert.vbs to run RedAlert.exe with hidden console window - Fix systray2 require in pkg builds by using absolute path instead of bare module name - Update MSI shortcuts (Start Menu, Startup, post-install) to launch via wscript.exe + VBS - Bump version to 1.2.0 Co-Authored-By: Claude Opus 4.6 <[email protected]>
1 parent 92e858c commit 6bbb665

8 files changed

Lines changed: 92 additions & 14 deletions

File tree

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# VBS Launcher for Windowless Execution
2+
3+
**Goal:** Hide the console window on Windows by launching RedAlert.exe via a VBS wrapper.
4+
5+
**Architecture:** A VBScript sits alongside the .exe and launches it with `vbHide` (window style 0). MSI shortcuts target `wscript.exe` with the VBS as argument.
6+
7+
## Changes
8+
9+
| File | Change |
10+
|------|--------|
11+
| `launcher/RedAlert.vbs` | New — 2-line VBS wrapper |
12+
| `scripts/build.js` | Copy VBS to dist for Windows builds |
13+
| `installer/RedAlert.wxs` | Add VBS component, point all shortcuts to wscript.exe + VBS |
14+
15+
## How It Works
16+
17+
- `wscript.exe` runs the VBS silently (no console)
18+
- VBS uses `WshShell.Run` with window style `0` (hidden) to launch RedAlert.exe
19+
- The exe runs completely in the background — only the system tray icon is visible
20+
- Start Menu shortcut, Startup shortcut, and post-install launch all use this path

installer/RedAlert.wxs

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,19 @@
1717
<MajorUpgrade DowngradeErrorMessage="A newer version of RedAlert is already installed." />
1818
<MediaTemplate EmbedCab="yes" />
1919

20+
<Icon Id="RedAlertIcon" SourceFile="$(var.DistDir)\assets\icon.ico" />
21+
<Property Id="ARPPRODUCTICON" Value="RedAlertIcon" />
22+
2023
<Directory Id="TARGETDIR" Name="SourceDir">
2124
<Directory Id="LocalAppDataFolder">
22-
<Directory Id="INSTALLFOLDER" Name="RedAlert" />
25+
<Directory Id="INSTALLFOLDER" Name="RedAlert">
26+
<Directory Id="PublicFolder" Name="public" />
27+
<Directory Id="AssetsFolder" Name="assets" />
28+
<Directory Id="DataFolder" Name="data" />
29+
<Directory Id="NodeModulesFolder" Name="node_modules">
30+
<Directory Id="Systray2Folder" Name="systray2" />
31+
</Directory>
32+
</Directory>
2333
</Directory>
2434
<Directory Id="ProgramMenuFolder">
2535
<Directory Id="AppMenuFolder" Name="RedAlert" />
@@ -34,15 +44,20 @@
3444
<Component Id="ConfigFile" Guid="c3d4e5f6-a7b8-9012-cdef-123456789012">
3545
<File Id="ConfigJson" Source="$(var.DistDir)\config.json" KeyPath="yes" />
3646
</Component>
47+
<Component Id="VbsLauncher" Guid="f6a7b8c9-d0e1-2345-abcd-456789012345">
48+
<File Id="RedAlertVbs" Source="$(var.DistDir)\RedAlert.vbs" KeyPath="yes" />
49+
</Component>
3750
</DirectoryRef>
3851

3952
<DirectoryRef Id="AppMenuFolder">
4053
<Component Id="StartMenuShortcut" Guid="d4e5f6a7-b8c9-0123-defa-234567890123">
4154
<Shortcut Id="AppShortcut"
4255
Name="RedAlert"
4356
Description="Pikud HaOref Siren Monitor"
44-
Target="[INSTALLFOLDER]RedAlert.exe"
45-
WorkingDirectory="INSTALLFOLDER" />
57+
Target="[SystemFolder]wscript.exe"
58+
Arguments="&quot;[INSTALLFOLDER]RedAlert.vbs&quot;"
59+
WorkingDirectory="INSTALLFOLDER"
60+
Icon="RedAlertIcon" />
4661
<RemoveFolder Id="CleanAppMenu" On="uninstall" />
4762
<RegistryValue Root="HKCU" Key="Software\RedAlert" Name="installed" Type="integer" Value="1" KeyPath="yes" />
4863
</Component>
@@ -52,27 +67,31 @@
5267
<Component Id="StartupShortcut" Guid="e5f6a7b8-c9d0-1234-efab-345678901234">
5368
<Shortcut Id="StartupLink"
5469
Name="RedAlert"
55-
Target="[INSTALLFOLDER]RedAlert.exe"
56-
WorkingDirectory="INSTALLFOLDER" />
70+
Target="[SystemFolder]wscript.exe"
71+
Arguments="&quot;[INSTALLFOLDER]RedAlert.vbs&quot;"
72+
WorkingDirectory="INSTALLFOLDER"
73+
Icon="RedAlertIcon" />
5774
<RegistryValue Root="HKCU" Key="Software\RedAlert" Name="autostart" Type="integer" Value="1" KeyPath="yes" />
5875
</Component>
5976
</DirectoryRef>
6077

6178
<Feature Id="MainFeature" Title="RedAlert" Level="1">
6279
<ComponentRef Id="MainExe" />
6380
<ComponentRef Id="ConfigFile" />
81+
<ComponentRef Id="VbsLauncher" />
6482
<ComponentRef Id="StartMenuShortcut" />
6583
<ComponentGroupRef Id="PublicFiles" />
6684
<ComponentGroupRef Id="AssetFiles" />
85+
<ComponentGroupRef Id="DataFiles" />
6786
<ComponentGroupRef Id="Systray2Files" />
6887
</Feature>
6988

7089
<Feature Id="AutoStart" Title="Start with Windows" Level="1">
7190
<ComponentRef Id="StartupShortcut" />
7291
</Feature>
7392

74-
<!-- Launch app after install -->
75-
<CustomAction Id="LaunchApp" FileKey="RedAlertExe" ExeCommand="" Return="asyncNoWait" />
93+
<!-- Launch app after install (via VBS to hide console window) -->
94+
<CustomAction Id="LaunchApp" Directory="INSTALLFOLDER" ExeCommand="[SystemFolder]wscript.exe RedAlert.vbs" Return="asyncNoWait" />
7695
<InstallExecuteSequence>
7796
<Custom Action="LaunchApp" After="InstallFinalize">NOT Installed OR REINSTALL</Custom>
7897
</InstallExecuteSequence>

installer/data.wxs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
3+
<Fragment>
4+
<DirectoryRef Id="DataFolder">
5+
<Component Id="cmp90F1624156D94DB94CD89CB1B0F21961" Guid="*">
6+
<File Id="filC6D5AFE09C2D9241F2ACC4A6A5132D18" KeyPath="yes" Source="$(var.DataDir)\false_alerts.json" />
7+
</Component>
8+
<Component Id="cmp4D57160C9BBE662C10416F8DAFE49B1D" Guid="*">
9+
<File Id="fil52DE1CDBE19A6970591179F28164901F" KeyPath="yes" Source="$(var.DataDir)\iran_alerts.json" />
10+
</Component>
11+
<Component Id="cmp87ED437732A26535BD11F93FF7C3BC07" Guid="*">
12+
<File Id="fil8DFA7BF9BEF767262B9D9EF98C525856" KeyPath="yes" Source="$(var.DataDir)\yemen_alerts.json" />
13+
</Component>
14+
</DirectoryRef>
15+
</Fragment>
16+
<Fragment>
17+
<ComponentGroup Id="DataFiles">
18+
<ComponentRef Id="cmp90F1624156D94DB94CD89CB1B0F21961" />
19+
<ComponentRef Id="cmp4D57160C9BBE662C10416F8DAFE49B1D" />
20+
<ComponentRef Id="cmp87ED437732A26535BD11F93FF7C3BC07" />
21+
</ComponentGroup>
22+
</Fragment>
23+
</Wix>

launcher/RedAlert.vbs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Set WshShell = CreateObject("WScript.Shell")
2+
WshShell.Run Chr(34) & Replace(WScript.ScriptFullName, WScript.ScriptName, "") & "RedAlert.exe" & Chr(34), 0, False

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "redalert",
3-
"version": "1.1.6",
3+
"version": "1.2.0",
44
"description": "",
55
"main": "index.js",
66
"directories": {

scripts/build-msi.js

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ const wxs = `<?xml version="1.0" encoding="UTF-8"?>
9393
Id="*"
9494
Name="RedAlert"
9595
Language="1033"
96-
Version="1.1.6"
96+
Version="1.2.0"
9797
Manufacturer="RedAlert Project"
9898
UpgradeCode="a1b2c3d4-e5f6-7890-abcd-ef1234567890">
9999
@@ -133,14 +133,18 @@ const wxs = `<?xml version="1.0" encoding="UTF-8"?>
133133
<Component Id="ConfigFile" Guid="c3d4e5f6-a7b8-9012-cdef-123456789012">
134134
<File Id="ConfigJson" Source="$(var.DistDir)\\config.json" KeyPath="yes" />
135135
</Component>
136+
<Component Id="VbsLauncher" Guid="f6a7b8c9-d0e1-2345-abcd-456789012345">
137+
<File Id="RedAlertVbs" Source="$(var.DistDir)\\RedAlert.vbs" KeyPath="yes" />
138+
</Component>
136139
</DirectoryRef>
137140
138141
<DirectoryRef Id="AppMenuFolder">
139142
<Component Id="StartMenuShortcut" Guid="d4e5f6a7-b8c9-0123-defa-234567890123">
140143
<Shortcut Id="AppShortcut"
141144
Name="RedAlert"
142145
Description="Pikud HaOref Siren Monitor"
143-
Target="[INSTALLFOLDER]RedAlert.exe"
146+
Target="[SystemFolder]wscript.exe"
147+
Arguments="&quot;[INSTALLFOLDER]RedAlert.vbs&quot;"
144148
WorkingDirectory="INSTALLFOLDER"
145149
Icon="RedAlertIcon" />
146150
<RemoveFolder Id="CleanAppMenu" On="uninstall" />
@@ -152,7 +156,8 @@ const wxs = `<?xml version="1.0" encoding="UTF-8"?>
152156
<Component Id="StartupShortcut" Guid="e5f6a7b8-c9d0-1234-efab-345678901234">
153157
<Shortcut Id="StartupLink"
154158
Name="RedAlert"
155-
Target="[INSTALLFOLDER]RedAlert.exe"
159+
Target="[SystemFolder]wscript.exe"
160+
Arguments="&quot;[INSTALLFOLDER]RedAlert.vbs&quot;"
156161
WorkingDirectory="INSTALLFOLDER"
157162
Icon="RedAlertIcon" />
158163
<RegistryValue Root="HKCU" Key="Software\\RedAlert" Name="autostart" Type="integer" Value="1" KeyPath="yes" />
@@ -162,6 +167,7 @@ const wxs = `<?xml version="1.0" encoding="UTF-8"?>
162167
<Feature Id="MainFeature" Title="RedAlert" Level="1">
163168
<ComponentRef Id="MainExe" />
164169
<ComponentRef Id="ConfigFile" />
170+
<ComponentRef Id="VbsLauncher" />
165171
<ComponentRef Id="StartMenuShortcut" />
166172
<ComponentGroupRef Id="PublicFiles" />
167173
<ComponentGroupRef Id="AssetFiles" />
@@ -173,8 +179,8 @@ const wxs = `<?xml version="1.0" encoding="UTF-8"?>
173179
<ComponentRef Id="StartupShortcut" />
174180
</Feature>
175181
176-
<!-- Launch app after install -->
177-
<CustomAction Id="LaunchApp" FileKey="RedAlertExe" ExeCommand="" Return="asyncNoWait" />
182+
<!-- Launch app after install (via VBS to hide console window) -->
183+
<CustomAction Id="LaunchApp" Directory="INSTALLFOLDER" ExeCommand="[SystemFolder]wscript.exe RedAlert.vbs" Return="asyncNoWait" />
178184
<InstallExecuteSequence>
179185
<Custom Action="LaunchApp" After="InstallFinalize">NOT Installed OR REINSTALL</Custom>
180186
</InstallExecuteSequence>

scripts/build.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,11 @@ for (const platform of platforms) {
104104
cpSync(join(ROOT, 'data'), join(platformDir, 'data'), { recursive: true });
105105
cpSync(join(ROOT, 'config.json'), join(platformDir, 'config.json'));
106106

107+
// Copy VBS launcher for Windows (hides console window)
108+
if (platform === 'win') {
109+
cpSync(join(ROOT, 'launcher', 'RedAlert.vbs'), join(platformDir, 'RedAlert.vbs'));
110+
}
111+
107112
// Copy bundle to platform dir if multi-platform build
108113
if (platforms.length > 1) {
109114
cpSync(BUNDLE, join(platformDir, 'bundle.cjs'));

src/tray.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,12 @@ export function createTray({ onStart, onStop }) {
4747
loadIcons();
4848

4949
// Load systray2 module (synchronous require — systray2 is CommonJS)
50+
// In pkg builds, bare 'systray2' resolves to the virtual snapshot, not the real
51+
// node_modules/ next to the exe. Use an absolute path so it finds the real module.
52+
const systray2Main = join(appDir, 'node_modules', 'systray2', 'index.js');
5053
let SysTrayModule;
5154
try {
52-
SysTrayModule = require('systray2');
55+
SysTrayModule = existsSync(systray2Main) ? require(systray2Main) : require('systray2');
5356
} catch (e) {
5457
log.error('Failed to require systray2:', e.message);
5558
throw e;

0 commit comments

Comments
 (0)