-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathsetup.ps1
More file actions
598 lines (507 loc) · 23.2 KB
/
setup.ps1
File metadata and controls
598 lines (507 loc) · 23.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
# Dewy Resort Workshop - Windows Setup Script
#
# This is the main entry point for Windows users to set up the workshop environment.
#
# Usage:
# .\setup.ps1 # Interactive setup (installs prerequisites + all tools)
# .\setup.ps1 -Tool workato # Setup specific tool
# .\setup.ps1 -Tool salesforce # Setup specific tool
# .\setup.ps1 -Tool all # Setup all tools
# .\setup.ps1 -SkipPrerequisites # Skip prerequisite installation
param(
[ValidateSet("workato", "salesforce", "all")]
[string]$Tool = "all",
[switch]$SkipPrerequisites
)
$ErrorActionPreference = "Stop"
Write-Host ""
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " Dewy Resort Workshop Setup (Windows)" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# Check PowerShell version
$psVersion = $PSVersionTable.PSVersion
Write-Host "PowerShell Version: $psVersion"
if ($psVersion.Major -lt 5) {
Write-Host "[WARN] PowerShell 5.0 or later is recommended" -ForegroundColor Yellow
}
Write-Host ""
function Test-Administrator {
$currentUser = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = New-Object Security.Principal.WindowsPrincipal($currentUser)
return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}
function Install-Winget {
Write-Host "Checking for winget..." -ForegroundColor Yellow
$winget = Get-Command winget -ErrorAction SilentlyContinue
if ($winget) {
Write-Host "[OK] winget is available" -ForegroundColor Green
return $true
}
Write-Host "winget not found. Attempting to install..." -ForegroundColor Yellow
# Check if running as admin
if (-not (Test-Administrator)) {
Write-Host "[ERROR] Administrator privileges required to install winget" -ForegroundColor Red
Write-Host "Please run PowerShell as Administrator and try again, or install winget manually:"
Write-Host " https://aka.ms/getwinget"
return $false
}
# Try to install App Installer (which includes winget) from Microsoft Store
try {
# Download and install the latest App Installer
$progressPreference = 'SilentlyContinue'
$latestWingetUrl = "https://aka.ms/getwinget"
$installerPath = "$env:TEMP\Microsoft.DesktopAppInstaller.msixbundle"
Write-Host "Downloading winget installer..."
Invoke-WebRequest -Uri $latestWingetUrl -OutFile $installerPath -UseBasicParsing
Write-Host "Installing winget..."
Add-AppxPackage -Path $installerPath
Remove-Item $installerPath -Force -ErrorAction SilentlyContinue
# Refresh PATH
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
$winget = Get-Command winget -ErrorAction SilentlyContinue
if ($winget) {
Write-Host "[OK] winget installed successfully" -ForegroundColor Green
return $true
}
} catch {
Write-Host "[ERROR] Failed to install winget: $($_.Exception.Message)" -ForegroundColor Red
}
Write-Host "[ERROR] Could not install winget automatically" -ForegroundColor Red
Write-Host "Please install manually from: https://aka.ms/getwinget"
return $false
}
function Get-PythonScriptsPath {
# Find Python Scripts directory - check both Roaming and Local
$possiblePaths = @(
"$env:APPDATA\Python\Python313\Scripts",
"$env:APPDATA\Python\Python312\Scripts",
"$env:APPDATA\Python\Python311\Scripts",
"$env:LOCALAPPDATA\Programs\Python\Python313\Scripts",
"$env:LOCALAPPDATA\Programs\Python\Python312\Scripts",
"$env:LOCALAPPDATA\Programs\Python\Python311\Scripts",
"$env:USERPROFILE\AppData\Roaming\Python\Python313\Scripts",
"$env:USERPROFILE\AppData\Roaming\Python\Python312\Scripts",
"$env:USERPROFILE\AppData\Roaming\Python\Python311\Scripts",
"$env:USERPROFILE\AppData\Local\Programs\Python\Python311\Scripts"
)
foreach ($path in $possiblePaths) {
if (Test-Path $path) {
return $path
}
}
return $null
}
function Test-PathContains {
param([string]$Directory)
$currentPath = [Environment]::GetEnvironmentVariable("Path", "User")
$machinePath = [Environment]::GetEnvironmentVariable("Path", "Machine")
$fullPath = "$machinePath;$currentPath"
return $fullPath -split ';' | Where-Object { $_ -eq $Directory }
}
function Add-ToUserPath {
param([string]$Directory)
Write-Host "Adding to user PATH: $Directory" -ForegroundColor Yellow
try {
$currentUserPath = [Environment]::GetEnvironmentVariable("Path", "User")
if ($currentUserPath) {
$newPath = "$currentUserPath;$Directory"
} else {
$newPath = $Directory
}
[Environment]::SetEnvironmentVariable("Path", $newPath, "User")
# Also update current session
$env:Path = "$env:Path;$Directory"
Write-Host "[OK] Added to user PATH" -ForegroundColor Green
return $true
} catch {
Write-Host "[ERROR] Failed to update user PATH: $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}
function Add-ToMachinePath {
param([string]$Directory)
# This requires elevation - spawn a new elevated process
Write-Host "Adding to system PATH requires Administrator privileges..." -ForegroundColor Yellow
$scriptBlock = @"
`$currentPath = [Environment]::GetEnvironmentVariable('Path', 'Machine')
`$newPath = "`$currentPath;$Directory"
[Environment]::SetEnvironmentVariable('Path', `$newPath, 'Machine')
Write-Host '[OK] Added to system PATH' -ForegroundColor Green
"@
try {
Start-Process powershell -Verb RunAs -ArgumentList "-Command", $scriptBlock -Wait
# Refresh current session PATH
$env:Path = [Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [Environment]::GetEnvironmentVariable("Path", "User")
return $true
} catch {
Write-Host "[ERROR] Failed to elevate privileges: $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}
function Ensure-PythonInPath {
$scriptsPath = Get-PythonScriptsPath
if (-not $scriptsPath) {
Write-Host "[WARN] Could not find Python Scripts directory" -ForegroundColor Yellow
return $true # Continue anyway, might work
}
if (Test-PathContains -Directory $scriptsPath) {
Write-Host "[OK] Python Scripts directory already in PATH" -ForegroundColor Green
return $true
}
Write-Host ""
Write-Host "Python Scripts directory not in PATH: $scriptsPath" -ForegroundColor Yellow
Write-Host ""
# Try user PATH first (no admin required)
if (Add-ToUserPath -Directory $scriptsPath) {
return $true
}
# If user PATH failed, offer to try machine PATH (requires admin)
Write-Host ""
$reply = Read-Host "Try adding to system PATH? (requires Administrator) [y/N]"
if ($reply -match '^[Yy]$') {
return Add-ToMachinePath -Directory $scriptsPath
}
Write-Host "[WARN] Python Scripts not in PATH. You may need to add it manually:" -ForegroundColor Yellow
Write-Host " $scriptsPath" -ForegroundColor Yellow
return $true # Continue anyway
}
function Install-Python {
Write-Host ""
Write-Host "Checking for Python 3.11+..." -ForegroundColor Yellow
# Check for Python
$pythonCmd = $null
foreach ($cmd in @("python", "python3", "py")) {
try {
$versionOutput = & $cmd --version 2>&1
if ($versionOutput -match "Python (\d+)\.(\d+)") {
$major = [int]$matches[1]
$minor = [int]$matches[2]
if ($major -ge 3 -and $minor -ge 11) {
$pythonCmd = $cmd
Write-Host "[OK] Python $major.$minor detected (using '$cmd')" -ForegroundColor Green
# Ensure Scripts directory is in PATH
Ensure-PythonInPath | Out-Null
return $true
} else {
Write-Host "[INFO] Python $major.$minor found but 3.11+ required" -ForegroundColor Yellow
}
}
} catch { }
}
Write-Host "Python 3.11+ not found. Installing via winget..." -ForegroundColor Yellow
try {
winget install Python.Python.3.11 --accept-source-agreements --accept-package-agreements
if ($LASTEXITCODE -ne 0) {
throw "winget install failed with exit code $LASTEXITCODE"
}
# Refresh PATH from registry
$env:Path = [Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [Environment]::GetEnvironmentVariable("Path", "User")
Write-Host "[OK] Python 3.11 installed successfully" -ForegroundColor Green
# Ensure Scripts directory is in PATH
if (-not (Ensure-PythonInPath)) {
Write-Host "[WARN] Could not add Python Scripts to PATH automatically" -ForegroundColor Yellow
Write-Host "You may need to restart PowerShell or add it manually" -ForegroundColor Yellow
}
return $true
} catch {
Write-Host "[ERROR] Failed to install Python: $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}
function Install-Git {
Write-Host ""
Write-Host "Checking for Git..." -ForegroundColor Yellow
$git = Get-Command git -ErrorAction SilentlyContinue
if ($git) {
$gitVersion = & git --version
Write-Host "[OK] $gitVersion" -ForegroundColor Green
return $true
}
Write-Host "Git not found. Installing via winget..." -ForegroundColor Yellow
try {
winget install Git.Git --accept-source-agreements --accept-package-agreements
if ($LASTEXITCODE -ne 0) {
throw "winget install failed with exit code $LASTEXITCODE"
}
# Refresh PATH
$env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path", "User")
Write-Host "[OK] Git installed successfully" -ForegroundColor Green
Write-Host "[INFO] You may need to restart PowerShell for Git to be available in PATH" -ForegroundColor Yellow
return $true
} catch {
Write-Host "[ERROR] Failed to install Git: $($_.Exception.Message)" -ForegroundColor Red
return $false
}
}
function Install-Make {
Write-Host ""
Write-Host "Checking for make..." -ForegroundColor Yellow
$makeCmd = Get-Command make -ErrorAction SilentlyContinue
if ($makeCmd) {
$makeVersion = & make --version 2>&1 | Select-Object -First 1
Write-Host "[OK] $makeVersion" -ForegroundColor Green
return $true
}
Write-Host "make not found. Installing via winget..." -ForegroundColor Yellow
try {
winget install -e --id GnuWin32.Make --accept-source-agreements --accept-package-agreements
if ($LASTEXITCODE -ne 0) {
throw "winget install failed with exit code $LASTEXITCODE"
}
# GnuWin32 Make installs to C:\Program Files (x86)\GnuWin32\bin
$makePath = "${env:ProgramFiles(x86)}\GnuWin32\bin"
# Refresh PATH from registry
$env:Path = [Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [Environment]::GetEnvironmentVariable("Path", "User")
# Check if make is now available
$makeCmd = Get-Command make -ErrorAction SilentlyContinue
if (-not $makeCmd) {
# Add GnuWin32 to PATH if not already there
if (Test-Path $makePath) {
Write-Host "Adding GnuWin32 to system PATH..." -ForegroundColor Yellow
$currentMachinePath = [Environment]::GetEnvironmentVariable("Path", "Machine")
if ($currentMachinePath -notlike "*$makePath*") {
# Need admin to modify machine PATH
if (Test-Administrator) {
$newPath = "$currentMachinePath;$makePath"
[Environment]::SetEnvironmentVariable("Path", $newPath, "Machine")
$env:Path = "$env:Path;$makePath"
Write-Host "[OK] Added $makePath to system PATH" -ForegroundColor Green
} else {
# Try user PATH instead
$currentUserPath = [Environment]::GetEnvironmentVariable("Path", "User")
$newUserPath = "$currentUserPath;$makePath"
[Environment]::SetEnvironmentVariable("Path", $newUserPath, "User")
$env:Path = "$env:Path;$makePath"
Write-Host "[OK] Added $makePath to user PATH" -ForegroundColor Green
}
}
}
}
# Verify
$makeCmd = Get-Command make -ErrorAction SilentlyContinue
if ($makeCmd) {
Write-Host "[OK] make installed successfully" -ForegroundColor Green
return $true
} else {
Write-Host "[WARN] make installed but not in PATH yet" -ForegroundColor Yellow
Write-Host "[INFO] You may need to restart PowerShell for make to be available" -ForegroundColor Yellow
return $true
}
} catch {
Write-Host "[ERROR] Failed to install make: $($_.Exception.Message)" -ForegroundColor Red
Write-Host ""
Write-Host "Alternative: Install Chocolatey and run: choco install make" -ForegroundColor Yellow
return $false
}
}
function Install-NodeJS {
Write-Host ""
Write-Host "Checking for Node.js v20..." -ForegroundColor Yellow
$nodeCmd = Get-Command node -ErrorAction SilentlyContinue
if ($nodeCmd) {
try {
$versionOutput = & node --version 2>&1
if ($versionOutput -match "v(\d+)\.(\d+)") {
$major = [int]$matches[1]
$minor = [int]$matches[2]
if ($major -eq 20) {
Write-Host "[OK] Node.js v$major.$minor detected" -ForegroundColor Green
# Also verify npm is available
$npmCmd = Get-Command npm -ErrorAction SilentlyContinue
if ($npmCmd) {
$npmVersion = & npm --version 2>&1
Write-Host "[OK] npm v$npmVersion detected" -ForegroundColor Green
}
return $true
} elseif ($major -gt 20) {
Write-Host "[WARN] Node.js v$major.$minor detected, but v20.x is required" -ForegroundColor Yellow
Write-Host "[INFO] Some features may not work correctly with newer versions" -ForegroundColor Yellow
Write-Host ""
$reply = Read-Host "Install Node.js v20 alongside existing version? [y/N]"
if ($reply -notmatch '^[Yy]') {
Write-Host "[WARN] Continuing with Node.js v$major (not recommended)" -ForegroundColor Yellow
return $true
}
} else {
Write-Host "[INFO] Node.js v$major.$minor found but v20.x required" -ForegroundColor Yellow
}
}
} catch {
Write-Host "[WARN] Could not determine Node.js version" -ForegroundColor Yellow
}
} else {
Write-Host "Node.js not found." -ForegroundColor Yellow
}
Write-Host "Installing Node.js v20 LTS via winget..." -ForegroundColor Yellow
try {
# Install Node.js 20 LTS specifically
winget install OpenJS.NodeJS.LTS --version "20.19.2" --accept-source-agreements --accept-package-agreements
if ($LASTEXITCODE -ne 0) {
# Try without specific version if exact version not available
Write-Host "[INFO] Specific version not available, trying latest v20 LTS..." -ForegroundColor Yellow
winget install OpenJS.NodeJS.LTS --accept-source-agreements --accept-package-agreements
if ($LASTEXITCODE -ne 0) {
throw "winget install failed with exit code $LASTEXITCODE"
}
}
# Refresh PATH from registry
$env:Path = [Environment]::GetEnvironmentVariable("Path", "Machine") + ";" + [Environment]::GetEnvironmentVariable("Path", "User")
# Node.js installs to Program Files by default - add explicitly if not in PATH
$nodePaths = @(
"$env:ProgramFiles\nodejs",
"${env:ProgramFiles(x86)}\nodejs",
"$env:LOCALAPPDATA\Programs\nodejs"
)
foreach ($nodePath in $nodePaths) {
if ((Test-Path $nodePath) -and ($env:Path -notlike "*$nodePath*")) {
$env:Path = "$env:Path;$nodePath"
Write-Host "[INFO] Added $nodePath to current session PATH" -ForegroundColor Yellow
}
}
# Verify installation
$nodeCmd = Get-Command node -ErrorAction SilentlyContinue
if ($nodeCmd) {
$versionOutput = & node --version 2>&1
Write-Host "[OK] Node.js $versionOutput installed successfully" -ForegroundColor Green
$npmVersion = & npm --version 2>&1
Write-Host "[OK] npm v$npmVersion available" -ForegroundColor Green
} else {
# Still not found - provide manual path info
Write-Host "[WARN] Node.js installed but not found in PATH" -ForegroundColor Yellow
Write-Host ""
Write-Host "Please restart PowerShell and run setup.ps1 again." -ForegroundColor Yellow
Write-Host "Or manually add Node.js to your PATH:" -ForegroundColor Yellow
foreach ($nodePath in $nodePaths) {
if (Test-Path $nodePath) {
Write-Host " $nodePath" -ForegroundColor Cyan
}
}
Write-Host ""
return $false
}
return $true
} catch {
Write-Host "[ERROR] Failed to install Node.js: $($_.Exception.Message)" -ForegroundColor Red
Write-Host ""
Write-Host "Alternative installation methods:" -ForegroundColor Yellow
Write-Host " 1. Download from: https://nodejs.org/en/download/ (choose v20 LTS)"
Write-Host " 2. Using nvm-windows: https://github.com/coreybutler/nvm-windows"
Write-Host ""
return $false
}
}
function Install-Prerequisites {
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " Checking Prerequisites" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
# Step 1: Check/Install winget
if (-not (Install-Winget)) {
Write-Host ""
Write-Host "[ERROR] Cannot proceed without winget" -ForegroundColor Red
return $false
}
# Step 2: Check/Install Git
if (-not (Install-Git)) {
Write-Host ""
Write-Host "[ERROR] Cannot proceed without Git" -ForegroundColor Red
return $false
}
# Step 3: Check/Install make
if (-not (Install-Make)) {
Write-Host ""
Write-Host "[WARN] make installation failed, some workshop commands may not work" -ForegroundColor Yellow
# Don't fail - make is optional for basic setup
}
# Step 4: Check/Install Python
if (-not (Install-Python)) {
Write-Host ""
Write-Host "[ERROR] Cannot proceed without Python 3.11+" -ForegroundColor Red
return $false
}
# Step 5: Check/Install Node.js v20
if (-not (Install-NodeJS)) {
Write-Host ""
Write-Host "[ERROR] Cannot proceed without Node.js v20" -ForegroundColor Red
return $false
}
Write-Host ""
Write-Host "[OK] All prerequisites satisfied" -ForegroundColor Green
Write-Host ""
return $true
}
function Show-Help {
Write-Host "Available Commands:" -ForegroundColor Cyan
Write-Host ""
Write-Host "Setup Commands:"
Write-Host " .\setup.ps1 -Tool all Setup all CLIs (workato + salesforce)"
Write-Host " .\setup.ps1 -Tool workato Setup only Workato CLI"
Write-Host " .\setup.ps1 -Tool salesforce Setup only Salesforce CLI"
Write-Host ""
Write-Host "Workato Commands:"
Write-Host " .\workato\scripts\cli\start_workato_recipes.ps1 Start all recipes"
Write-Host " .\workato\scripts\cli\stop_workato_recipes.ps1 Stop all recipes"
Write-Host ""
Write-Host "Salesforce Commands:"
Write-Host " .\vendor\salesforce\scripts\deploy.ps1 -TargetOrg <alias> Deploy to Salesforce"
Write-Host ""
Write-Host "Dev Server Commands:"
Write-Host " .\app\scripts\dev-tools\server.ps1 -Action start Start dev server"
Write-Host " .\app\scripts\dev-tools\server.ps1 -Action stop Stop dev server"
Write-Host ""
}
# Main execution
if (-not $SkipPrerequisites) {
if (-not (Install-Prerequisites)) {
Write-Host ""
Write-Host "[ERROR] Prerequisite installation failed. Cannot continue." -ForegroundColor Red
exit 1
}
}
# Run setup based on tool parameter
Write-Host "========================================" -ForegroundColor Cyan
Write-Host " Installing CLI Tools" -ForegroundColor Cyan
Write-Host "========================================" -ForegroundColor Cyan
Write-Host ""
switch ($Tool) {
"all" {
Write-Host "Setting up all vendor CLIs..." -ForegroundColor Green
Write-Host ""
Write-Host "--- Setting up Workato CLI ---" -ForegroundColor Cyan
& "$PSScriptRoot\app\scripts\setup\setup-cli.ps1" -Tool workato
if ($LASTEXITCODE -ne 0) {
Write-Host "[ERROR] Workato CLI setup failed" -ForegroundColor Red
exit 1
}
Write-Host ""
Write-Host "--- Setting up Salesforce CLI ---" -ForegroundColor Cyan
& "$PSScriptRoot\app\scripts\setup\setup-cli.ps1" -Tool salesforce
if ($LASTEXITCODE -ne 0) {
Write-Host "[ERROR] Salesforce CLI setup failed" -ForegroundColor Red
exit 1
}
}
"workato" {
Write-Host "Setting up Workato CLI..." -ForegroundColor Green
& "$PSScriptRoot\app\scripts\setup\setup-cli.ps1" -Tool workato
if ($LASTEXITCODE -ne 0) {
Write-Host "[ERROR] Workato CLI setup failed" -ForegroundColor Red
exit 1
}
}
"salesforce" {
Write-Host "Setting up Salesforce CLI..." -ForegroundColor Green
& "$PSScriptRoot\app\scripts\setup\setup-cli.ps1" -Tool salesforce
if ($LASTEXITCODE -ne 0) {
Write-Host "[ERROR] Salesforce CLI setup failed" -ForegroundColor Red
exit 1
}
}
}
Write-Host ""
Write-Host "========================================" -ForegroundColor Green
Write-Host " Setup Complete!" -ForegroundColor Green
Write-Host "========================================" -ForegroundColor Green
Write-Host ""
Show-Help