Skip to content

Build from Source

Holger Imbery edited this page May 15, 2026 · 2 revisions

Build from Source

Prerequisites

Dependency Version Where to get it
.NET 9 SDK 9.0.100 or newer https://dotnet.microsoft.com/download/dotnet/9.0
Windows App SDK runtime 2.0.1 (auto-restored by NuGet) No manual install needed for builds
Windows 10 1809 (build 17763) or later Mica backdrop requires Windows 11; gracefully skipped on Windows 10

Run dotnet --version in a terminal to confirm .NET 9 is on PATH.
The first build takes 30–90 seconds while NuGet downloads the Windows App SDK.


Build & run

cd PigeonPost
dotnet restore
dotnet build PigeonPost.csproj -c Debug -r win-x64
dotnet run --project PigeonPost.csproj -r win-x64

On first launch, Windows Defender Firewall may ask whether to allow incoming connections on port 2560. Tick Private networks and click Allow access.

LAN access from other devices (iPhone, Android, …): Windows classifies newly joined Wi-Fi networks as Public by default and blocks inbound connections even if you accepted the firewall prompt. Two steps are needed:

Step 1 — Set the Wi-Fi network to Private Settings → System → Network & Internet → Wi-Fi → <your network> → Network profile type → Private

Step 2 — Add an inbound firewall rule for port 2560 Run PowerShell as Administrator and paste:

New-NetFirewallRule -DisplayName "PigeonPost (Port 2560)" `
    -Direction Inbound -Protocol TCP -LocalPort 2560 `
    -Action Allow -Profile Private,Domain,Public

Both steps are required. The rule alone is not enough if the network profile is Public.


Publish — Velopack installer (release)

Releases are built automatically by GitHub Actions when a version tag is pushed. The workflow produces a Velopack installer + update feed and attaches them to the release.

git tag v1.2.3 -m "Release 1.2.3"
git push origin v1.2.3

The CI pipeline runs:

dotnet publish PigeonPost.csproj -c Release -r win-x64 ^
    --self-contained true ^
    /p:WindowsAppSdkSelfContained=true ^
    /p:EnableMsixTooling=true ^
    -o publish

vpk pack --packId PigeonPost --packVersion 1.2.3 ^
    --packDir publish --mainExe PigeonPost.exe ^
    --channel win-x64 --outputDir releases

Three files are uploaded to the GitHub Release:

File Purpose
PigeonPost-win-x64-Setup.exe First-time installer
PigeonPost-win-x64-full.nupkg Full update package
releases.win-x64.json Update feed — read by the in-app updater

Project layout

PigeonPost/
├── PigeonPost.csproj            # WinUI 3 + .NET 9, unpackaged
├── Program.cs                   # Custom entry point: VelopackApp.Build().Run() first
├── app.manifest                 # Per-monitor DPI awareness, Win10/11 compat IDs
├── App.xaml / App.xaml.cs       # Application bootstrap; ThemeDictionaries (Fluent Light/Dark)
├── MainWindow.xaml / .xaml.cs   # Mica window, layout, tray icon wiring, theme-change handler
├── ActivityLogWindow.xaml / .xaml.cs  # Standalone activity-log window; level/text filter
├── PeersWindow.xaml / .xaml.cs  # Peers window: collapsible Expander sections (Discovered / Saved / Add)
├── SettingsWindow.xaml / .xaml.cs     # Settings window: grouped collapsible Expander sections
├── Constants.cs                 # Port number, Downloads folder path
├── Assets/
│   ├── PigeonPost.ico           # Pigeon + envelope icon (7 sizes: 256 → 16 px)
│   ├── banner.png               # Banner image used in README
│   └── PigeonPostGUI.jpg        # GUI screenshot used in README
├── Converters/
│   ├── HexColorConverter.cs     # "#rrggbb" → SolidColorBrush (used in log list)
│   └── BoolToVisibilityConverter.cs  # bool → Visibility (update banner)
├── Models/
│   ├── LogLevel.cs              # Enum: Info / Success / Warn / Error / File / Clipboard
│   ├── LogEntry.cs              # Immutable log record; LevelBrush resolves from ThemeDictionaries
│   └── PeerEntry.cs             # Observable peer model; bearer token encrypted with DPAPI
├── Services/
│   ├── AppState.cs              # Thread-safe shared state + events
│   ├── AutostartService.cs      # HKCU Run registry; Start-with-Windows toggle
│   ├── IpMonitorService.cs      # Network-change detection (WiFi/LAN/offline/IP change)
│   ├── KeepAwakeService.cs      # SetThreadExecutionState wrapper; prevents screensaver/sleep
│   ├── ListenerService.cs       # HttpListener, clipboard ops, file upload, keep-awake; localhost fallback
│   ├── MdnsService.cs           # Bonjour advertisement + peer browsing (_pigeonpost._tcp)
│   ├── NetworkHelper.cs         # Local-IP discovery; Tailscale IP detection
│   ├── PeerKeepAliveService.cs  # Background timer; sends keepawake pings to saved peers
│   ├── PeerSendService.cs       # HTTP client for clipboard/file/keep-awake sends to peers
│   ├── SettingsService.cs       # Persists all settings to JSON; DPAPI encryption for tokens
│   └── UpdateService.cs         # Velopack update check + download + apply
└── ViewModels/
    ├── MainViewModel.cs         # MVVM: observable properties, relay commands, uptime timer;
    │                            # RefreshStatusColors() resolves Fluent brushes from resources
    └── PeersViewModel.cs        # Observable peer collections; add/edit/remove/send logic

Clone this wiki locally