feat(gui): redesign kanholec GUI with modern interface and WiX v7 installer
golangci-lint / lint (push) Failing after 4s
golangci-lint / lint (push) Failing after 4s
- Complete GUI overhaul with Fyne framework * Modern dark theme with indigo/pink accent colors * 4-step setup wizard (Welcome → Server → Auth → Finish) * Dashboard with proxy list, real-time logs, and config viewer * Windows Service manager (install/start/stop/uninstall) * System tray integration with quick controls - WiX v7 MSI installer * Auto-registers as Windows Service (manual start) * Feature tree UI for optional components * Desktop shortcut and PATH options * Build script: packaging/windows/build-msi.ps1 - Build system updates * Added kanholec-windows-gui target (CGO required) * Added kanholec-windows-msi target * Separate main_gui.go entry point for GUI builds GUI binary: bin/kanholec-windows-amd64.exe (31.4 MB) MSI installer: bin/kanholec-0.69.0-amd64.msi (12.1 MB)
This commit is contained in:
@@ -0,0 +1,166 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Build kanholec MSI installer using WiX Toolset
|
||||
.DESCRIPTION
|
||||
Builds the kanholec binary (with GUI support) and packages it into
|
||||
an MSI installer using WiX v7.
|
||||
.PARAMETER Arch
|
||||
Target architecture: amd64 (default) or arm64
|
||||
.PARAMETER SkipBuild
|
||||
Skip building the Go binary (use existing one)
|
||||
.PARAMETER OutputDir
|
||||
Output directory for the MSI (default: bin/)
|
||||
.EXAMPLE
|
||||
.\build-msi.ps1
|
||||
.\build-msi.ps1 -Arch arm64
|
||||
.\build-msi.ps1 -SkipBuild
|
||||
#>
|
||||
|
||||
param(
|
||||
[ValidateSet("amd64", "arm64")]
|
||||
[string]$Arch = "amd64",
|
||||
[switch]$SkipBuild,
|
||||
[string]$OutputDir = ""
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$scriptDir = Split-Path -Parent $PSCommandPath
|
||||
$rootDir = Resolve-Path (Join-Path $scriptDir "..\..")
|
||||
|
||||
if ($OutputDir -eq "") {
|
||||
$OutputDir = Join-Path $rootDir "bin"
|
||||
}
|
||||
|
||||
$version = "0.69.0"
|
||||
$binaryName = "kanholec-windows-$Arch.exe"
|
||||
$binaryPath = Join-Path $OutputDir $binaryName
|
||||
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host " kanholec MSI Builder (WiX v7)" -ForegroundColor Cyan
|
||||
Write-Host " Version: $version | Arch: $Arch" -ForegroundColor Cyan
|
||||
Write-Host "========================================" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
|
||||
# Check WiX
|
||||
try {
|
||||
$wixVersion = & wix --version 2>&1
|
||||
Write-Host " WiX: $wixVersion" -ForegroundColor Green
|
||||
} catch {
|
||||
Write-Host " ERROR: WiX Toolset not found. Install with:" -ForegroundColor Red
|
||||
Write-Host " dotnet tool install --global wix" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Check Go
|
||||
try {
|
||||
$goVersion = & go version 2>&1
|
||||
Write-Host " Go: $goVersion" -ForegroundColor Green
|
||||
} catch {
|
||||
Write-Host " ERROR: Go not found." -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Build binary
|
||||
if (-not $SkipBuild) {
|
||||
Write-Host ""
|
||||
Write-Host " Building kanholec (GUI + CGO)..." -ForegroundColor Yellow
|
||||
|
||||
$env:CGO_ENABLED = "1"
|
||||
$env:GOOS = "windows"
|
||||
$env:GOARCH = $Arch
|
||||
|
||||
New-Item -ItemType Directory -Path $OutputDir -Force | Out-Null
|
||||
|
||||
$ldflags = "-s -w -H windowsgui"
|
||||
$tags = "kanholec,kanholec_gui"
|
||||
|
||||
& go build -trimpath -ldflags $ldflags -tags $tags -o $binaryPath ./cmd/kanholec
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host " ERROR: Go build failed" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
$env:CGO_ENABLED = ""
|
||||
$env:GOOS = ""
|
||||
$env:GOARCH = ""
|
||||
|
||||
Write-Host " Binary: $binaryPath" -ForegroundColor Green
|
||||
} else {
|
||||
if (-not (Test-Path $binaryPath)) {
|
||||
Write-Host " ERROR: Binary not found at $binaryPath" -ForegroundColor Red
|
||||
Write-Host " Build it first or remove -SkipBuild flag" -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
Write-Host " Using existing binary: $binaryPath" -ForegroundColor Green
|
||||
}
|
||||
|
||||
# Create icon if missing
|
||||
$iconPath = Join-Path $scriptDir "kanholec.ico"
|
||||
if (-not (Test-Path $iconPath)) {
|
||||
Write-Host ""
|
||||
Write-Host " Creating placeholder icon..." -ForegroundColor Yellow
|
||||
# Create a minimal valid .ico file (16x16 32-bit)
|
||||
$ico = New-Object byte[] 318
|
||||
# ICO header
|
||||
$ico[0] = 0; $ico[1] = 0 # reserved
|
||||
$ico[2] = 1; $ico[3] = 0 # type: icon
|
||||
$ico[4] = 1; $ico[5] = 0 # count: 1
|
||||
# Directory entry
|
||||
$ico[6] = 16 # width
|
||||
$ico[7] = 16 # height
|
||||
$ico[8] = 0 # colors
|
||||
$ico[9] = 0 # reserved
|
||||
$ico[10] = 1; $ico[11] = 0 # planes
|
||||
$ico[12] = 32; $ico[13] = 0 # bpp
|
||||
$ico[14] = 0; $ico[15] = 1; $ico[16] = 0; $ico[17] = 0 # size = 256
|
||||
$ico[18] = 22; $ico[19] = 0; $ico[20] = 0; $ico[21] = 0 # offset = 22
|
||||
# BMP header (40 bytes)
|
||||
$ico[22] = 40; $ico[23] = 0; $ico[24] = 0; $ico[25] = 0 # header size
|
||||
$ico[26] = 16; $ico[27] = 0; $ico[28] = 0; $ico[29] = 0 # width
|
||||
$ico[30] = 32; $ico[31] = 0; $ico[32] = 0; $ico[33] = 0 # height (2x for icon)
|
||||
$ico[34] = 1; $ico[35] = 0 # planes
|
||||
$ico[36] = 32; $ico[37] = 0 # bpp
|
||||
# Fill pixel data with blue-ish color (kanhole brand)
|
||||
for ($i = 62; $i -lt 318; $i += 4) {
|
||||
$ico[$i] = 236 # B
|
||||
$ico[$i+1] = 152 # G
|
||||
$ico[$i+2] = 56 # R
|
||||
$ico[$i+3] = 255 # A
|
||||
}
|
||||
[System.IO.File]::WriteAllBytes($iconPath, $ico)
|
||||
Write-Host " Icon: $iconPath (placeholder)" -ForegroundColor Green
|
||||
}
|
||||
|
||||
# Build MSI
|
||||
Write-Host ""
|
||||
Write-Host " Building MSI with WiX..." -ForegroundColor Yellow
|
||||
|
||||
$wixprojPath = Join-Path $scriptDir "kanholec.wixproj"
|
||||
$msiOutput = Join-Path $OutputDir "kanholec-$version-$Arch.msi"
|
||||
|
||||
Push-Location $rootDir
|
||||
try {
|
||||
& dotnet build $wixprojPath -c Release -p:Platform=x64 -o $OutputDir
|
||||
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-Host " ERROR: WiX build failed" -ForegroundColor Red
|
||||
exit 1
|
||||
}
|
||||
|
||||
$builtMsi = Get-ChildItem -Path $OutputDir -Filter "*.msi" | Sort-Object LastWriteTime -Descending | Select-Object -First 1
|
||||
if ($builtMsi) {
|
||||
if ($builtMsi.FullName -ne $msiOutput) {
|
||||
Move-Item -Path $builtMsi.FullName -Destination $msiOutput -Force
|
||||
}
|
||||
Write-Host ""
|
||||
Write-Host " MSI: $msiOutput" -ForegroundColor Green
|
||||
Write-Host " Size: $([math]::Round((Get-Item $msiOutput).Length / 1KB, 1)) KB" -ForegroundColor Green
|
||||
}
|
||||
} finally {
|
||||
Pop-Location
|
||||
}
|
||||
|
||||
Write-Host ""
|
||||
Write-Host " Done!" -ForegroundColor Cyan
|
||||
Write-Host ""
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 318 B |
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="WixToolset.Sdk/7.0.0">
|
||||
<PropertyGroup>
|
||||
<InstallerPlatform>x64</InstallerPlatform>
|
||||
<OutputName>kanholec-0.69.0</OutputName>
|
||||
<OutputType>Package</OutputType>
|
||||
<DefineConstants>Version=0.69.0</DefineConstants>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="WixToolset.UI.wixext" Version="7.0.0" />
|
||||
<PackageReference Include="WixToolset.Util.wixext" Version="7.0.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
+124
-39
@@ -1,47 +1,132 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v3/wxs">
|
||||
<Product
|
||||
<Wix xmlns="http://wixtoolset.org/schemas/v4/wxs"
|
||||
xmlns:ui="http://wixtoolset.org/schemas/v4/wxs/ui">
|
||||
|
||||
<Package
|
||||
Name="kanholec"
|
||||
Id="*"
|
||||
Manufacturer="kanhole Contributors"
|
||||
Version="0.69.0"
|
||||
UpgradeCode="A1B2C3D4-E5F6-7890-ABCD-EF1234567890"
|
||||
Language="1033"
|
||||
Codepage="1252"
|
||||
Version="0.62.0"
|
||||
Manufacturer="kanhole Contributors">
|
||||
Scope="perMachine">
|
||||
|
||||
<Package
|
||||
InstallerVersion="200"
|
||||
Compressed="yes"
|
||||
InstallScope="perMachine"
|
||||
Description="kanhole Client"
|
||||
Comments="kanholec is the client component of kanhole - a fast reverse proxy." />
|
||||
<MajorUpgrade DowngradeErrorMessage="A newer version of kanholec is already installed." />
|
||||
|
||||
<Media Id="1" Cabinet="kanholec.cab" EmbedCab="yes" />
|
||||
<MediaTemplate EmbedCab="yes" />
|
||||
|
||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
||||
<Directory Id="ProgramFiles64Folder">
|
||||
<Directory Id="INSTALLDIR" Name="kanholec">
|
||||
<Component Id="FrpcBinary" Guid="E1B2C3D4-E5F6-7890-ABCD-EF1234567894">
|
||||
<File Id="FrpcExe" Name="kanholec.exe" DiskId="1" Source="bin/kanholec-windows-amd64.exe" KeyPath="yes" />
|
||||
</Component>
|
||||
</Directory>
|
||||
</Directory>
|
||||
<Icon Id="kanholecIcon" SourceFile="kanholec.ico" />
|
||||
<Property Id="ARPPRODUCTICON" Value="kanholecIcon" />
|
||||
<Property Id="ARPHELPLINK" Value="https://github.com/kanhole/kanhole" />
|
||||
<Property Id="ARPURLINFOABOUT" Value="https://github.com/kanhole/kanhole" />
|
||||
|
||||
<Directory Id="ProgramMenuFolder">
|
||||
<Directory Id="ApplicationProgramsFolder" Name="kanholec">
|
||||
<Component Id="StartMenuShortcuts" Guid="A2B2C3D4-E5F6-7890-ABCD-EF1234567892">
|
||||
<Shortcut Id="FrpcShortcut" Name="kanholec" Target="[INSTALLDIR]kanholec.exe" WorkingDirectory="INSTALLDIR" Description="kanhole client" />
|
||||
<Shortcut Id="UninstallShortcut" Name="Uninstall kanholec" Target="[System64Folder]msiexec.exe" Arguments="/x [ProductCode]" />
|
||||
<RemoveFolder Id="RemoveApplicationProgramsFolder" On="uninstall" />
|
||||
<RegistryValue Root="HKCU" Key="Software\kanhole\kanholec" Name="installed" Type="integer" Value="1" />
|
||||
</Component>
|
||||
</Directory>
|
||||
</Directory>
|
||||
</Directory>
|
||||
|
||||
<Feature Id="Main" Title="kanholec" Description="kanhole client binary" Level="1">
|
||||
<ComponentRef Id="FrpcBinary" />
|
||||
<ComponentRef Id="StartMenuShortcuts" />
|
||||
<Feature Id="Main" Title="kanholec" Description="kanhole reverse proxy client" Level="1"
|
||||
AllowAdvertise="no">
|
||||
<ComponentGroupRef Id="BinaryFiles" />
|
||||
<ComponentGroupRef Id="ConfigFiles" />
|
||||
<ComponentGroupRef Id="Shortcuts" />
|
||||
<ComponentRef Id="ServiceComponent" />
|
||||
</Feature>
|
||||
</Product>
|
||||
|
||||
<Feature Id="DesktopShortcutFeature" Title="Desktop Shortcut" Description="Create a desktop shortcut"
|
||||
Level="1000" AllowAdvertise="no">
|
||||
<ComponentRef Id="DesktopShortcutComponent" />
|
||||
</Feature>
|
||||
|
||||
<Feature Id="PathFeature" Title="Add to PATH" Description="Add kanholec to system PATH"
|
||||
Level="1" AllowAdvertise="no">
|
||||
<ComponentRef Id="PathComponent" />
|
||||
</Feature>
|
||||
|
||||
<ui:WixUI
|
||||
Id="WixUI_FeatureTree"
|
||||
InstallDirectory="INSTALLFOLDER" />
|
||||
|
||||
<WixVariable Id="WixUILicenseRtf" Value="license.rtf" />
|
||||
|
||||
<StandardDirectory Id="ProgramFiles6432Folder">
|
||||
<Directory Id="INSTALLFOLDER" Name="kanholec" />
|
||||
</StandardDirectory>
|
||||
|
||||
<StandardDirectory Id="ProgramMenuFolder">
|
||||
<Directory Id="ApplicationProgramsFolder" Name="kanholec" />
|
||||
</StandardDirectory>
|
||||
|
||||
<StandardDirectory Id="CommonAppDataFolder">
|
||||
<Directory Id="ConfigFolder" Name="kanholec" />
|
||||
</StandardDirectory>
|
||||
|
||||
<ComponentGroup Id="BinaryFiles" Directory="INSTALLFOLDER">
|
||||
<Component Id="KanholeCBinary" Guid="E1B2C3D4-E5F6-7890-ABCD-EF1234567894">
|
||||
<File Id="kanholecExe"
|
||||
Name="kanholec.exe"
|
||||
Source="..\..\bin\kanholec-windows-amd64.exe"
|
||||
KeyPath="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
|
||||
<ComponentGroup Id="ConfigFiles" Directory="ConfigFolder">
|
||||
<Component Id="DefaultConfig" Guid="F1B2C3D4-E5F6-7890-ABCD-EF1234567895" NeverOverwrite="yes">
|
||||
<File Id="kanholecToml"
|
||||
Name="kanholec.toml"
|
||||
Source="kanholec.default.toml"
|
||||
KeyPath="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
|
||||
<ComponentGroup Id="Shortcuts" Directory="ApplicationProgramsFolder">
|
||||
<Component Id="StartMenuShortcuts" Guid="A2B2C3D4-E5F6-7890-ABCD-EF1234567892">
|
||||
<Shortcut Id="StartMenuShortcut"
|
||||
Name="kanholec"
|
||||
Target="[INSTALLFOLDER]kanholec.exe"
|
||||
WorkingDirectory="INSTALLFOLDER"
|
||||
Description="kanhole reverse proxy client"
|
||||
Icon="kanholecIcon" />
|
||||
<Shortcut Id="ConfigFolderShortcut"
|
||||
Name="Config Directory"
|
||||
Target="[ConfigFolder]"
|
||||
Description="Open kanholec config directory" />
|
||||
<Shortcut Id="UninstallShortcut"
|
||||
Name="Uninstall kanholec"
|
||||
Target="[System64Folder]msiexec.exe"
|
||||
Arguments="/x [ProductCode]"
|
||||
Description="Uninstall kanholec" />
|
||||
<RemoveFolder Id="RemoveApplicationProgramsFolder" On="uninstall" />
|
||||
<RegistryValue Root="HKCU" Key="Software\kanhole\kanholec" Name="installed" Type="integer" Value="1" KeyPath="yes" />
|
||||
</Component>
|
||||
</ComponentGroup>
|
||||
|
||||
<Component Id="DesktopShortcutComponent" Directory="DesktopFolder" Guid="B2B2C3D4-E5F6-7890-ABCD-EF1234567893">
|
||||
<Shortcut Id="DesktopShortcut"
|
||||
Name="kanholec"
|
||||
Target="[INSTALLFOLDER]kanholec.exe"
|
||||
WorkingDirectory="INSTALLFOLDER"
|
||||
Description="kanhole reverse proxy client"
|
||||
Icon="kanholecIcon" />
|
||||
<RegistryValue Root="HKCU" Key="Software\kanhole\kanholec" Name="desktop_shortcut" Type="integer" Value="1" KeyPath="yes" />
|
||||
</Component>
|
||||
|
||||
<Component Id="PathComponent" Directory="INSTALLFOLDER" Guid="C2B2C3D4-E5F6-7890-ABCD-EF1234567896">
|
||||
<Environment Id="PATH" Name="PATH" Value="[INSTALLFOLDER]" Permanent="no" Part="last" Action="set" System="yes" />
|
||||
<RegistryValue Root="HKCU" Key="Software\kanhole\kanholec" Name="path_added" Type="integer" Value="1" KeyPath="yes" />
|
||||
</Component>
|
||||
|
||||
<Component Id="ServiceComponent" Directory="INSTALLFOLDER" Guid="D2B2C3D4-E5F6-7890-ABCD-EF1234567897">
|
||||
<RegistryValue Root="HKCU" Key="Software\kanhole\kanholec" Name="service_registered" Type="integer" Value="1" KeyPath="yes" />
|
||||
<ServiceInstall
|
||||
Id="kanholecService"
|
||||
Name="kanholec"
|
||||
DisplayName="kanholec - kanhole Client"
|
||||
Description="kanhole reverse proxy client service"
|
||||
Start="demand"
|
||||
Type="ownProcess"
|
||||
ErrorControl="ignore"
|
||||
Arguments='-c "[ConfigFolder]kanholec.toml"'
|
||||
Account="LocalSystem" />
|
||||
<ServiceControl
|
||||
Id="kanholecServiceControl"
|
||||
Name="kanholec"
|
||||
Stop="both"
|
||||
Remove="uninstall"
|
||||
Wait="no" />
|
||||
</Component>
|
||||
|
||||
</Package>
|
||||
</Wix>
|
||||
|
||||
Reference in New Issue
Block a user