Skip to content

Commit f979995

Browse files
hemanandrclaude
andcommitted
Implement Issue #24: Inno Setup installer script
- Created comprehensive Inno Setup script (setup.iss) for professional Windows installation - Added PowerShell build automation script (build-installer.ps1) with error handling - Installer follows ENV-15 conventions: * Service name: ThingConnectPulseSvc with automatic startup * Directories: Program Files and ProgramData structure * User confirmation for data deletion on uninstall - Features: * Automatic service registration/unregistration * Directory structure creation with proper permissions * Default configuration file generation * Start Menu shortcuts creation * Data preservation options during uninstall - Updated README.md with installer usage documentation - Successfully tested: 10MB installer builds correctly - Acceptance criteria met: Fresh install creates working service at localhost:8080 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <[email protected]>
1 parent 7fc76cc commit f979995

File tree

4 files changed

+467
-0
lines changed

4 files changed

+467
-0
lines changed

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,45 @@ dotnet run
5151

5252
## Installation & Deployment
5353

54+
### Windows Installer
55+
56+
Build and create a professional Windows installer:
57+
58+
```bash
59+
# Build installer (includes build and packaging)
60+
.\build-installer.ps1
61+
62+
# Build installer without rebuilding (faster for testing)
63+
.\build-installer.ps1 -SkipBuild
64+
65+
# Open installer directory after build
66+
.\build-installer.ps1 -OpenInstaller
67+
```
68+
69+
The installer will:
70+
- Install to `Program Files\ThingConnect.Pulse`
71+
- Create data directories in `ProgramData\ThingConnect.Pulse`
72+
- Register and start `ThingConnectPulseSvc` Windows service
73+
- Create Start Menu shortcuts
74+
- Ask before deleting data on uninstall
75+
76+
### Development Installation
77+
78+
For development and testing:
79+
80+
```bash
81+
# Install as Windows service (development)
82+
.\install-service.ps1 install
83+
84+
# Manage service
85+
.\install-service.ps1 start|stop|status
86+
87+
# Uninstall service
88+
.\install-service.ps1 uninstall
89+
```
90+
91+
### Documentation
92+
5493
- **[Installer Conventions](./docs/installer-map.md)** - Windows service installation specification
5594
- **[Logging Configuration](./docs/logging.md)** - Structured logging setup and policies
5695

build-installer.ps1

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
# ThingConnect Pulse - Installer Build Script
2+
# Builds and packages the application using Inno Setup
3+
4+
param(
5+
[string]$Configuration = "Release",
6+
[string]$InnoSetupPath = "",
7+
[switch]$SkipBuild = $false,
8+
[switch]$OpenInstaller = $false
9+
)
10+
11+
$ErrorActionPreference = "Stop"
12+
13+
# Get script directory
14+
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
15+
$ProjectDir = Join-Path $ScriptDir "ThingConnect.Pulse.Server"
16+
$PublishDir = Join-Path $ScriptDir "publish"
17+
$InstallerDir = Join-Path $ScriptDir "installer"
18+
$SetupScript = Join-Path $ScriptDir "setup.iss"
19+
20+
Write-Host "=== ThingConnect Pulse Installer Build ===" -ForegroundColor Yellow
21+
Write-Host "Configuration: $Configuration" -ForegroundColor Cyan
22+
Write-Host "Project: $ProjectDir" -ForegroundColor Cyan
23+
Write-Host "Output: $InstallerDir" -ForegroundColor Cyan
24+
25+
# Verify prerequisites
26+
Write-Host "=== Checking Prerequisites ===" -ForegroundColor Yellow
27+
28+
# Check if .NET is available
29+
if (-not (Get-Command "dotnet" -ErrorAction SilentlyContinue)) {
30+
Write-Host "[ERROR] .NET CLI not found. Please install .NET 8.0 SDK." -ForegroundColor Red
31+
exit 1
32+
}
33+
34+
Write-Host "[OK] .NET CLI found" -ForegroundColor Green
35+
36+
# Find Inno Setup compiler
37+
if ([string]::IsNullOrEmpty($InnoSetupPath)) {
38+
# Common Inno Setup installation paths
39+
$CommonPaths = @(
40+
"${env:ProgramFiles(x86)}\Inno Setup 6\ISCC.exe",
41+
"${env:ProgramFiles}\Inno Setup 6\ISCC.exe",
42+
"${env:ProgramFiles(x86)}\Inno Setup 5\ISCC.exe",
43+
"${env:ProgramFiles}\Inno Setup 5\ISCC.exe"
44+
)
45+
46+
foreach ($Path in $CommonPaths) {
47+
if (Test-Path $Path) {
48+
$InnoSetupPath = $Path
49+
break
50+
}
51+
}
52+
}
53+
54+
if ([string]::IsNullOrEmpty($InnoSetupPath) -or -not (Test-Path $InnoSetupPath)) {
55+
Write-Host "[ERROR] Inno Setup Compiler (ISCC.exe) not found." -ForegroundColor Red
56+
Write-Host "Please install Inno Setup from: https://jrsoftware.org/isdl.php" -ForegroundColor Cyan
57+
Write-Host "Or specify the path using -InnoSetupPath parameter" -ForegroundColor Cyan
58+
exit 1
59+
}
60+
61+
Write-Host "[OK] Inno Setup found at: $InnoSetupPath" -ForegroundColor Green
62+
63+
# Verify setup script exists
64+
if (-not (Test-Path $SetupScript)) {
65+
Write-Host "[ERROR] Setup script not found: $SetupScript" -ForegroundColor Red
66+
exit 1
67+
}
68+
69+
Write-Host "[OK] Setup script found" -ForegroundColor Green
70+
71+
# Build and publish the application
72+
if (-not $SkipBuild) {
73+
Write-Host "=== Building Application ===" -ForegroundColor Yellow
74+
75+
# Clean previous publish
76+
if (Test-Path $PublishDir) {
77+
Remove-Item -Path $PublishDir -Recurse -Force
78+
Write-Host "Cleaned previous publish directory" -ForegroundColor Cyan
79+
}
80+
81+
# Restore packages
82+
Write-Host "Restoring packages..." -ForegroundColor Cyan
83+
dotnet restore $ProjectDir
84+
if ($LASTEXITCODE -ne 0) {
85+
Write-Host "[ERROR] Package restore failed" -ForegroundColor Red
86+
exit 1
87+
}
88+
Write-Host "[OK] Packages restored" -ForegroundColor Green
89+
90+
# Publish application
91+
Write-Host "Publishing application..." -ForegroundColor Cyan
92+
$PublishArgs = @(
93+
"publish", $ProjectDir,
94+
"-c", $Configuration,
95+
"-o", $PublishDir,
96+
"--self-contained", "false",
97+
"--runtime", "win-x64",
98+
"/p:PublishSingleFile=false"
99+
)
100+
101+
& dotnet @PublishArgs
102+
if ($LASTEXITCODE -ne 0) {
103+
Write-Host "[ERROR] Application publish failed" -ForegroundColor Red
104+
exit 1
105+
}
106+
Write-Host "[OK] Application published to: $PublishDir" -ForegroundColor Green
107+
} else {
108+
Write-Host "=== Skipping Build (using existing publish) ===" -ForegroundColor Yellow
109+
if (-not (Test-Path $PublishDir)) {
110+
Write-Host "[ERROR] Publish directory not found: $PublishDir" -ForegroundColor Red
111+
Write-Host "Run without -SkipBuild to build the application first" -ForegroundColor Cyan
112+
exit 1
113+
}
114+
}
115+
116+
# Verify required files exist
117+
$RequiredFiles = @(
118+
"ThingConnect.Pulse.Server.exe",
119+
"appsettings.json",
120+
"appsettings.Development.json"
121+
)
122+
123+
foreach ($File in $RequiredFiles) {
124+
$FilePath = Join-Path $PublishDir $File
125+
if (-not (Test-Path $FilePath)) {
126+
Write-Host "[ERROR] Required file missing: $File" -ForegroundColor Red
127+
exit 1
128+
}
129+
}
130+
131+
Write-Host "[OK] All required files present" -ForegroundColor Green
132+
133+
# Create installer directory
134+
if (-not (Test-Path $InstallerDir)) {
135+
New-Item -ItemType Directory -Path $InstallerDir | Out-Null
136+
Write-Host "Created installer directory" -ForegroundColor Cyan
137+
}
138+
139+
# Build installer with Inno Setup
140+
Write-Host "=== Building Installer ===" -ForegroundColor Yellow
141+
142+
Write-Host "Compiling installer..." -ForegroundColor Cyan
143+
$InnoArgs = @(
144+
"/Q", # Quiet mode
145+
$SetupScript
146+
)
147+
148+
& $InnoSetupPath @InnoArgs
149+
if ($LASTEXITCODE -ne 0) {
150+
Write-Host "[ERROR] Installer compilation failed" -ForegroundColor Red
151+
exit 1
152+
}
153+
154+
# Find the generated installer
155+
$InstallerPattern = Join-Path $InstallerDir "ThingConnect.Pulse.Setup*.exe"
156+
$GeneratedInstaller = Get-ChildItem -Path $InstallerPattern -ErrorAction SilentlyContinue | Select-Object -First 1
157+
158+
if (-not $GeneratedInstaller) {
159+
Write-Host "[ERROR] Installer not found in: $InstallerDir" -ForegroundColor Red
160+
exit 1
161+
}
162+
163+
$InstallerSize = [math]::Round($GeneratedInstaller.Length / 1MB, 2)
164+
Write-Host "[OK] Installer created: $($GeneratedInstaller.Name) - Size: $InstallerSize MB" -ForegroundColor Green
165+
166+
# Display summary
167+
Write-Host "=== Build Complete ===" -ForegroundColor Yellow
168+
Write-Host "Installer: $($GeneratedInstaller.FullName)" -ForegroundColor Cyan
169+
Write-Host "Size: $InstallerSize MB" -ForegroundColor Cyan
170+
171+
if ($OpenInstaller) {
172+
Write-Host "Opening installer directory..." -ForegroundColor Cyan
173+
Invoke-Item $InstallerDir
174+
}
175+
176+
Write-Host "[SUCCESS] Build completed successfully!" -ForegroundColor Green
177+
Write-Host ""
178+
Write-Host "To install ThingConnect Pulse:" -ForegroundColor Cyan
179+
Write-Host "1. Run the installer as Administrator" -ForegroundColor White
180+
Write-Host "2. Follow the installation wizard" -ForegroundColor White
181+
Write-Host "3. Access the web interface at http://localhost:8080" -ForegroundColor White
182+
Write-Host ""
183+
Write-Host "The installer will:" -ForegroundColor Cyan
184+
Write-Host "- Install binaries to Program Files\ThingConnect.Pulse" -ForegroundColor White
185+
Write-Host "- Create data directories in ProgramData\ThingConnect.Pulse" -ForegroundColor White
186+
Write-Host "- Register and start the ThingConnectPulseSvc Windows service" -ForegroundColor White
187+
Write-Host "- Create Start Menu shortcuts" -ForegroundColor White
10.1 MB
Binary file not shown.

0 commit comments

Comments
 (0)