Skip to content

Commit 26a3601

Browse files
committed
win32: Created script to build msi package
1 parent 1848103 commit 26a3601

10 files changed

Lines changed: 653 additions & 0 deletions

File tree

.gitignore

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
11
# Build artifacts
22
weatherwidget.exe
33
weatherwidget
4+
build/
5+
6+
# Windows resource files (generated by go-winres)
7+
*.syso
8+
9+
# Installer outputs
10+
*.msi
11+
*.msix

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ You can download the latest pre-compiled binaries for Windows and Linux from the
3636
.\weatherwidget.exe
3737
```
3838

39+
### Windows MSI Package
40+
```powershell
41+
.\installer\build-msi.ps1 -Version "0.0.4" -SkipSign
42+
```
43+
3944
### Linux
4045
1. **Install dependencies**:
4146
```bash

cmd/weatherwidget/main.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ import (
1414
"weatherwidget/internal/ui"
1515
)
1616

17+
// version is set at build time via -ldflags "-X main.version=1.0.0.0"
18+
var version = "dev"
19+
1720
func main() {
1821
fyneApp := app.NewWithID("com.weatherwidget")
1922
fyneApp.Settings().SetTheme(ui.NewWidgetTheme(theme.DefaultTheme()))

installer/AppxManifest.xml

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
3+
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
4+
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities">
5+
6+
<!--
7+
Identity:
8+
- Name: Must match your Microsoft Partner Center reservation (e.g., "12345YourPublisher.WeatherWidget")
9+
- Publisher: Must match your signing certificate subject (e.g., "CN=Your Publisher ID, O=Your Org, L=City, S=State, C=US")
10+
- Update these values after registering your app in Partner Center
11+
-->
12+
<Identity Name="YourPublisherId.WeatherWidget"
13+
Publisher="CN=YourPublisherId"
14+
Version="1.0.0.0"
15+
ProcessorArchitecture="x64" />
16+
17+
<Properties>
18+
<DisplayName>Weather Widget</DisplayName>
19+
<PublisherDisplayName>WeatherWidget</PublisherDisplayName>
20+
<Logo>assets\StoreLogo.png</Logo>
21+
<Description>A lightweight desktop weather widget that displays current conditions and forecasts.</Description>
22+
</Properties>
23+
24+
<Dependencies>
25+
<TargetDeviceFamily Name="Windows.Desktop"
26+
MinVersion="10.0.17763.0"
27+
MaxVersionTested="10.0.26100.0" />
28+
</Dependencies>
29+
30+
<Resources>
31+
<Resource Language="en-us" />
32+
</Resources>
33+
34+
<Applications>
35+
<Application Id="WeatherWidget"
36+
Executable="weatherwidget.exe"
37+
EntryPoint="Windows.FullTrustApplication">
38+
<uap:VisualElements DisplayName="Weather Widget"
39+
Description="Desktop weather widget with real-time conditions"
40+
BackgroundColor="transparent"
41+
Square150x150Logo="assets\Square150x150Logo.png"
42+
Square44x44Logo="assets\Square44x44Logo.png">
43+
<uap:DefaultTile Wide310x150Logo="assets\Wide310x150Logo.png"
44+
Square310x310Logo="assets\Square310x310Logo.png"
45+
ShortName="Weather" />
46+
</uap:VisualElements>
47+
</Application>
48+
</Applications>
49+
50+
<Capabilities>
51+
<rescap:Capability Name="runFullTrust" />
52+
<Capability Name="internetClient" />
53+
</Capabilities>
54+
</Package>

installer/Package.wxs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
WiX v4+ installer definition for Weather Widget.
4+
Per-user install to AppData\Local\WeatherWidget (no admin required).
5+
6+
Build with:
7+
wix build installer\Package.wxs -d BuildDir=. -d Version=1.0.0.0 -o WeatherWidget.msi
8+
-->
9+
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs">
10+
<Package Name="Weather Widget"
11+
Manufacturer="WeatherWidget"
12+
Version="$(var.Version)"
13+
UpgradeCode="E8F4B2A1-7C3D-4E5F-9A1B-2D3E4F5A6B7C"
14+
Compressed="yes"
15+
InstallerVersion="500"
16+
Scope="perUser">
17+
18+
<MajorUpgrade DowngradeErrorMessage="A newer version of Weather Widget is already installed." />
19+
<MediaTemplate EmbedCab="yes" />
20+
21+
<!-- Install to %LocalAppData%\WeatherWidget (per-user, no admin needed) -->
22+
<StandardDirectory Id="LocalAppDataFolder">
23+
<Directory Id="INSTALLFOLDER" Name="WeatherWidget">
24+
<Component Id="MainExecutable" Guid="A1B2C3D4-E5F6-7890-ABCD-EF1234567890">
25+
<File Id="WeatherWidgetExe"
26+
Source="$(var.BuildDir)\weatherwidget.exe"
27+
KeyPath="yes" />
28+
</Component>
29+
</Directory>
30+
</StandardDirectory>
31+
32+
<!-- Start Menu shortcut -->
33+
<StandardDirectory Id="ProgramMenuFolder">
34+
<Directory Id="ApplicationProgramsFolder" Name="Weather Widget">
35+
<Component Id="ApplicationShortcut" Guid="B2C3D4E5-F6A7-8901-BCDE-F12345678901">
36+
<Shortcut Id="ApplicationStartMenuShortcut"
37+
Name="Weather Widget"
38+
Description="Desktop weather widget"
39+
Target="[INSTALLFOLDER]weatherwidget.exe"
40+
WorkingDirectory="INSTALLFOLDER"
41+
Icon="WeatherWidgetIcon" />
42+
<RemoveFolder Id="CleanUpShortCut" On="uninstall" />
43+
<RegistryValue Root="HKCU"
44+
Key="Software\WeatherWidget"
45+
Name="installed"
46+
Type="integer"
47+
Value="1"
48+
KeyPath="yes" />
49+
</Component>
50+
</Directory>
51+
</StandardDirectory>
52+
53+
<!-- Icon for shortcuts (sourced from the .ico file directly) -->
54+
<Icon Id="WeatherWidgetIcon" SourceFile="winres\icon.ico" />
55+
56+
<Feature Id="ProductFeature" Title="Weather Widget" Level="1">
57+
<ComponentRef Id="MainExecutable" />
58+
<ComponentRef Id="ApplicationShortcut" />
59+
</Feature>
60+
61+
<!-- Optional: Launch after install -->
62+
<CustomAction Id="LaunchApplication"
63+
FileRef="WeatherWidgetExe"
64+
ExeCommand=""
65+
Return="asyncNoWait" />
66+
</Package>
67+
</Wix>

installer/README.md

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
# Weather Widget - Windows Installer Packaging
2+
3+
This directory contains everything needed to build production-ready Windows
4+
installers for the Weather Widget application.
5+
6+
## Two Packaging Options
7+
8+
| Format | Use Case | Script |
9+
|--------|----------|--------|
10+
| **MSI** | Traditional Windows installer, sideloading | `build-msi.ps1` |
11+
| **MSIX** | Microsoft Store submission (recommended) | `build-msix.ps1` |
12+
13+
## Prerequisites
14+
15+
### Required for both
16+
17+
1. **Go 1.25+** with CGO enabled (Fyne requires CGO)
18+
2. **go-winres** — embeds icon, manifest, and version info into the exe:
19+
```powershell
20+
go install github.com/tc-hib/go-winres@latest
21+
```
22+
3. **A code signing certificate** — required for production/Store builds.
23+
For Store apps, you get one through Microsoft Partner Center.
24+
25+
### For MSI builds
26+
27+
4. **WiX Toolset v4+**:
28+
```powershell
29+
dotnet tool install --global wix
30+
```
31+
32+
### For MSIX builds (Microsoft Store)
33+
34+
4. **Windows 10/11 SDK** — provides `MakeAppx.exe` and `SignTool.exe`.
35+
Install via Visual Studio Installer or the standalone SDK installer.
36+
37+
## Quick Start
38+
39+
### Build an unsigned MSI (for testing)
40+
41+
```powershell
42+
.\installer\build-msi.ps1 -Version "1.0.0.0" -SkipSign
43+
```
44+
45+
### Build a signed MSI
46+
47+
```powershell
48+
.\installer\build-msi.ps1 -Version "1.0.0.0" -CertPath ".\cert.pfx" -CertPassword "yourpassword"
49+
```
50+
51+
### Build an MSIX for Microsoft Store
52+
53+
```powershell
54+
.\installer\build-msix.ps1 -Version "1.0.0.0" -CertPath ".\cert.pfx" -CertPassword "yourpassword"
55+
```
56+
57+
Output goes to `.\build\`.
58+
59+
## Store Assets (MSIX only)
60+
61+
Before submitting to the Microsoft Store, place properly sized PNG images in
62+
`installer/store-assets/`:
63+
64+
| File | Size | Purpose |
65+
|------|------|---------|
66+
| `StoreLogo.png` | 50x50 | Store listing logo |
67+
| `Square44x44Logo.png` | 44x44 | Taskbar, Start menu |
68+
| `Square150x150Logo.png` | 150x150 | Start menu tile |
69+
| `Wide310x150Logo.png` | 310x150 | Wide Start tile |
70+
| `Square310x310Logo.png` | 310x310 | Large Start tile |
71+
72+
If these are missing, the build script creates 1x1 placeholders so the
73+
package builds, but you must replace them before Store submission.
74+
75+
## Icon File
76+
77+
Place your application icon as `winres/icon.ico`. This gets embedded into the
78+
exe and is used for the taskbar, window title, and Explorer file icon.
79+
80+
To convert a PNG to ICO, use ImageMagick:
81+
```bash
82+
magick convert icon.png -define icon:auto-resize=256,128,64,48,32,16 icon.ico
83+
```
84+
85+
## AppxManifest.xml Configuration
86+
87+
Before submitting to the Store, update these fields in `AppxManifest.xml`:
88+
89+
- `Identity Name` — your Partner Center app reservation name
90+
- `Identity Publisher` — must match your signing certificate subject exactly
91+
- `PublisherDisplayName` — your display name in the Store
92+
93+
## File Structure
94+
95+
```
96+
installer/
97+
├── AppxManifest.xml # MSIX package manifest
98+
├── Package.wxs # WiX MSI definition
99+
├── build-msi.ps1 # MSI build script
100+
├── build-msix.ps1 # MSIX build script
101+
├── store-assets/ # Store tile images (you provide these)
102+
│ ├── StoreLogo.png
103+
│ ├── Square44x44Logo.png
104+
│ ├── Square150x150Logo.png
105+
│ ├── Wide310x150Logo.png
106+
│ └── Square310x310Logo.png
107+
└── README.md # This file
108+
109+
winres/
110+
├── winres.json # Windows resource definitions
111+
└── icon.ico # Application icon (you provide this)
112+
```

0 commit comments

Comments
 (0)