-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInstall-FloatingLicenseServer.ps1
More file actions
605 lines (537 loc) · 28.4 KB
/
Copy pathInstall-FloatingLicenseServer.ps1
File metadata and controls
605 lines (537 loc) · 28.4 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
599
600
601
602
603
604
605
#Requires -Version 5.1
<#
.SYNOPSIS
Automated setup for SpinFire Insight Floating License Manager (FLM).
.DESCRIPTION
This script:
1. Downloads and installs the SpinFire Floating License Manager if not already present.
2. Locates customer license files (license.al + sfpflv2.dat) from the setup folder.
3. Copies license files into the FLM install directory.
4. Registers lmgrd as a Windows Service (auto-start on boot).
5. Configures Windows Firewall inbound rules for lmgrd.exe and spinfired.exe.
6. Starts the license server service.
Must be run as Administrator (the script will self-elevate if needed).
A full setup log is saved to the Desktop as FLM-Install-<timestamp>.log.
.NOTES
SpinFire Insight Floating License Manager
TechSoft3D Support: spinfiresupport@techsoft3d.com
#>
# -- SELF-ELEVATION -------------------------------------------------------------
# Relaunch as Administrator if not already elevated.
$currentPrincipal = [Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()
$isAdmin = $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if (-not $isAdmin) {
if ($PSCommandPath) {
Write-Host "`n[!] Requesting Administrator privileges - please approve the UAC prompt.`n" -ForegroundColor Yellow
# -NoExit keeps the elevated window open if the script crashes before its own pause
Start-Process powershell.exe `
-ArgumentList "-NoProfile -ExecutionPolicy Bypass -NoExit -File `"$PSCommandPath`"" `
-Verb RunAs
} else {
Write-Host "[X] This script must be run as Administrator." -ForegroundColor Red
Write-Host " Right-click the script and choose 'Run as Administrator', or use Run-Setup.bat." -ForegroundColor Yellow
Read-Host 'Press Enter to exit'
}
exit
}
# -- TRANSCRIPT / LOGGING -------------------------------------------------------
# Write log to the same folder as the script so it's easy to find and share.
# Falls back to $env:TEMP if the script directory isn't writable.
$timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$logFile = "$PSScriptRoot\FLM-Install-$timestamp.log"
try { Start-Transcript -Path $logFile -Append | Out-Null } catch {
$logFile = "$env:TEMP\FLM-Install-$timestamp.log"
try { Start-Transcript -Path $logFile -Append | Out-Null } catch {}
}
# -- GLOBAL ERROR TRAP ---------------------------------------------------------
# Catches any unhandled terminating error so the window never vanishes silently.
trap {
Write-Host "`n`n !! UNEXPECTED ERROR !!" -ForegroundColor Red
Write-Host " $($_.Exception.Message)" -ForegroundColor Red
Write-Host " At: $($_.InvocationInfo.PositionMessage)" -ForegroundColor Red
Write-Host "`n Full log saved to: $logFile" -ForegroundColor Yellow
try { Stop-Transcript | Out-Null } catch {}
Read-Host "`n Press Enter to close"
break
}
# -- CONFIGURATION --------------------------------------------------------------
$FLM_DOWNLOAD_URL = 'https://downloads.spinfire.com/FloatingLicenseServer/SpinFireFloatingLicenseServer.x64.exe'
$FLM_SERVICE_NAME = 'SpinFire License Server'
$FLM_PORT = 27000
$FLM_LICENSE_FILE = 'license.al'
$FLM_DATA_FILE = 'sfpflv2.dat'
$FLM_LMGRD = 'lmgrd.exe'
$FLM_VENDOR_DAEMON = 'spinfired.exe'
# Candidate install paths (checked in order)
$FLM_REQUIRED_VERSION = '11.19.8.0'
# SpinFire FLM is always installed here; other lmtools installations are not modified
$FLM_INSTALL_DIR = 'C:\Program Files\Tech Soft 3D\Floating License Manager'
# -- HELPER FUNCTIONS -----------------------------------------------------------
function Write-Step { param([string]$Msg) Write-Host "`n[>] $Msg" -ForegroundColor Cyan }
function Write-OK { param([string]$Msg) Write-Host " [OK] $Msg" -ForegroundColor Green }
function Write-Warn { param([string]$Msg) Write-Host " [!] $Msg" -ForegroundColor Yellow }
function Write-Fail { param([string]$Msg) Write-Host " [X] $Msg" -ForegroundColor Red }
# -- BANNER ---------------------------------------------------------------------
Clear-Host
Write-Host ''
Write-Host ' ========================================================' -ForegroundColor Cyan
Write-Host ' SpinFire Insight - Floating License Manager Setup' -ForegroundColor Cyan
Write-Host ' ========================================================' -ForegroundColor Cyan
Write-Host " Setup log will be saved to: $logFile" -ForegroundColor DarkGray
Write-Host ''
# -- PRE-FLIGHT: CHECK FOR CONFLICTING FLEXLM VERSIONS ------------------------
# If another application has already registered a FlexLM service on this machine
# using a DIFFERENT version of lmgrd, we must stop here before making any changes.
# Mixing FlexLM versions on the same machine is unsupported and can break both
# applications. The user must uninstall the conflicting version first.
$lmtoolsRegBase = 'HKLM:\SOFTWARE\FLEXlm License Manager'
$existingOtherServices = Get-ChildItem $lmtoolsRegBase -ErrorAction SilentlyContinue |
Where-Object { $_.PSChildName -ne $FLM_SERVICE_NAME }
if ($existingOtherServices) {
foreach ($svc in $existingOtherServices) {
$svcProps = Get-ItemProperty $svc.PSPath -ErrorAction SilentlyContinue
$svcLmgrd = $svcProps.Lmgrd
if ($svcLmgrd -and (Test-Path $svcLmgrd)) {
$vi = (Get-Item $svcLmgrd -ErrorAction SilentlyContinue).VersionInfo
$ver = "$($vi.FileMajorPart).$($vi.FileMinorPart).$($vi.FileBuildPart).$($vi.FilePrivatePart)"
if ($ver -ne $FLM_REQUIRED_VERSION) {
Write-Host ''
Write-Fail "Conflicting FlexLM installation detected - no changes have been made."
Write-Host ''
Write-Host " Service : $($svc.PSChildName)" -ForegroundColor Yellow
Write-Host " lmgrd : $svcLmgrd" -ForegroundColor Yellow
Write-Host " Version : $ver" -ForegroundColor Yellow
Write-Host " Required : $FLM_REQUIRED_VERSION" -ForegroundColor Yellow
Write-Host ''
Write-Host ' SpinFire Insight requires FlexLM v{0}.' -f $FLM_REQUIRED_VERSION -ForegroundColor Yellow
Write-Host ' Another application on this machine is using a different version.' -ForegroundColor Yellow
Write-Host ''
Write-Host ' To proceed:' -ForegroundColor White
Write-Host " 1. Uninstall the conflicting FlexLM / license server for '$($svc.PSChildName)'." -ForegroundColor White
Write-Host ' 2. Re-run this setup script - it will perform a clean installation.' -ForegroundColor White
Write-Host ''
Write-Host ' For assistance: spinfiresupport@techsoft3d.com' -ForegroundColor Yellow
Read-Host "`nPress Enter to exit"
try { Stop-Transcript | Out-Null } catch {}
exit 1
}
}
}
}
# -- STEP 1: DETECT EXISTING FLM INSTALLATION ----------------------------------
Write-Step 'Checking for existing Floating License Manager installation...'
$flmInstallDir = $FLM_INSTALL_DIR
$lmgrdExe = Join-Path $flmInstallDir $FLM_LMGRD
$spinfiredExe = Join-Path $flmInstallDir $FLM_VENDOR_DAEMON
$flmAlreadyInstalled = $false
if (Test-Path $lmgrdExe) {
$vi = (Get-Item $lmgrdExe -ErrorAction SilentlyContinue).VersionInfo
$installedVersion = "$($vi.FileMajorPart).$($vi.FileMinorPart).$($vi.FileBuildPart).$($vi.FilePrivatePart)"
if ($installedVersion -eq $FLM_REQUIRED_VERSION) {
Write-OK "FLM v$FLM_REQUIRED_VERSION already installed at: $flmInstallDir"
$flmAlreadyInstalled = $true
} else {
Write-Warn "FLM found at expected path but version is $installedVersion (required: $FLM_REQUIRED_VERSION)."
Write-Host ''
Write-Host " Version $FLM_REQUIRED_VERSION is required to run SpinFire Insight licenses 2026.1.0+." -ForegroundColor Yellow
Write-Host " The correct version can be downloaded and installed automatically." -ForegroundColor Yellow
Write-Host ''
$answer = Read-Host ' Download and install the correct version now? (Y/N) [default: Y]'
if ($answer -match '^[Nn]') {
Write-Host ''
Write-Host " Setup cancelled. Please install FLM version $FLM_REQUIRED_VERSION and re-run." -ForegroundColor Yellow
Read-Host "`nPress Enter to exit"
try { Stop-Transcript | Out-Null } catch {}
exit 0
}
}
} else {
Write-Warn 'Floating License Manager not found at expected path. Proceeding with download and install.'
}
# -- STEP 2: DOWNLOAD AND INSTALL FLM (if needed) ------------------------------
if (-not $flmAlreadyInstalled) {
Write-Step 'Downloading Floating License Manager installer...'
$installerPath = Join-Path $env:TEMP 'SpinFireFloatingLicenseServer.x64.exe'
try {
Write-Host " Source: $FLM_DOWNLOAD_URL" -ForegroundColor DarkGray
$webClient = New-Object System.Net.WebClient
$webClient.DownloadFile($FLM_DOWNLOAD_URL, $installerPath)
Write-OK "Download complete."
} catch {
Write-Fail "Download failed: $($_.Exception.Message)"
Write-Host "`n Manual download: $FLM_DOWNLOAD_URL" -ForegroundColor Yellow
Write-Host " Download the installer, run it manually, then re-run this script." -ForegroundColor Yellow
Read-Host "`nPress Enter to exit"
try { Stop-Transcript | Out-Null } catch {}
exit 1
}
Write-Step 'Installing Floating License Manager (silent)...'
$installed = $false
# The FLM installer is an InstallShield bootstrapper ("Setup Launcher Unicode").
# InstallShield silent install: /s tells the bootstrapper to run silently;
# /v passes arguments directly to the inner MSI (/qn = no UI).
# NOTE: Do NOT use -Verb RunAs here -- the script is already running elevated
# (self-elevated at startup). Double-elevation causes "operation canceled" errors.
try {
Write-Host ' Running silent install (InstallShield /s /v"/qn")...' -ForegroundColor DarkGray
$proc = Start-Process -FilePath $installerPath -ArgumentList '/s /v"/qn"' -Wait -PassThru -ErrorAction Stop
if ($proc.ExitCode -in @(0, 1, 3010)) {
Write-OK "Installer completed (exit code $($proc.ExitCode))."
$installed = $true
} else {
Write-Warn "Installer returned exit code $($proc.ExitCode)."
}
} catch {
Write-Warn "Installer failed: $($_.Exception.Message)."
}
Remove-Item $installerPath -ErrorAction SilentlyContinue
if (-not $installed) {
Write-Fail 'Silent installation failed with all attempted switches.'
Write-Host "`n Manual steps:" -ForegroundColor Yellow
Write-Host " 1. Download: $FLM_DOWNLOAD_URL" -ForegroundColor Yellow
Write-Host " 2. Run the installer manually." -ForegroundColor Yellow
Write-Host " 3. Re-run this script to complete configuration." -ForegroundColor Yellow
Read-Host "`nPress Enter to exit"
try { Stop-Transcript | Out-Null } catch {}
exit 1
}
# Wait for install to settle, then verify canonical path and version
Start-Sleep -Seconds 3
if (-not (Test-Path $lmgrdExe)) {
Write-Fail 'Could not locate lmgrd.exe at expected path after installation.'
Write-Host "`n Expected: $lmgrdExe" -ForegroundColor Yellow
Write-Host " Please install manually from: $FLM_DOWNLOAD_URL" -ForegroundColor Yellow
Read-Host "`nPress Enter to exit"
try { Stop-Transcript | Out-Null } catch {}
exit 1
}
$vi = (Get-Item $lmgrdExe -ErrorAction SilentlyContinue).VersionInfo
$installedVersion = "$($vi.FileMajorPart).$($vi.FileMinorPart).$($vi.FileBuildPart).$($vi.FilePrivatePart)"
if ($installedVersion -ne $FLM_REQUIRED_VERSION) {
Write-Fail "FLM version mismatch after installation."
Write-Host " Required : $FLM_REQUIRED_VERSION" -ForegroundColor Yellow
Write-Host " Installed: $installedVersion" -ForegroundColor Yellow
Write-Host " Please contact TechSoft3D support: spinfiresupport@techsoft3d.com" -ForegroundColor Yellow
Read-Host "`nPress Enter to exit"
try { Stop-Transcript | Out-Null } catch {}
exit 1
}
Write-OK "FLM v$FLM_REQUIRED_VERSION installed at: $flmInstallDir"
}
# -- STEP 3: LOCATE LICENSE FILES ----------------------------------------------
Write-Step "Locating license files ($FLM_DATA_FILE required, $FLM_LICENSE_FILE optional)..."
$licSourceFile = $null
$datSourceFile = $null
# License files must be in the same folder as this script
$autoDat = Join-Path $PSScriptRoot $FLM_DATA_FILE
$autoLic = Join-Path $PSScriptRoot $FLM_LICENSE_FILE
if (Test-Path $autoDat) {
$datSourceFile = $autoDat
Write-OK "Found $FLM_DATA_FILE in setup folder."
if (Test-Path $autoLic) {
$licSourceFile = $autoLic
Write-OK "Found $FLM_LICENSE_FILE in setup folder."
} else {
Write-Warn "$FLM_LICENSE_FILE not found - it will be skipped (not required for the license server)."
}
} else {
Write-Fail "$FLM_DATA_FILE not found in the setup folder."
Write-Host ''
Write-Host " Please place $FLM_DATA_FILE (and optionally $FLM_LICENSE_FILE)" -ForegroundColor Yellow
Write-Host " in the same folder as this script:" -ForegroundColor Yellow
Write-Host " $PSScriptRoot" -ForegroundColor Yellow
Write-Host " Then re-run Setup." -ForegroundColor Yellow
Read-Host "`nPress Enter to exit"
try { Stop-Transcript | Out-Null } catch {}
exit 1
}
# Validate sfpflv2.dat content (this is the file with the SERVER line)
$datValidation = Get-Content -Path $datSourceFile -Raw -ErrorAction Stop
if ($datValidation -notmatch '(?im)^SERVER\s+') {
Write-Fail "$FLM_DATA_FILE does not appear to be a valid license file (missing SERVER line)."
Write-Host " Please contact TechSoft3D support: spinfiresupport@techsoft3d.com" -ForegroundColor Yellow
Read-Host "`nPress Enter to exit"
try { Stop-Transcript | Out-Null } catch {}
exit 1
}
Write-OK "License files validated."
# -- STEP 4: CHECK HOSTNAME AND MAC ADDRESS (from sfpflv2.dat line 1) ----------
# sfpflv2.dat first line format: SERVER <hostname> <macaddress>
# e.g.: SERVER rh00vmgfps01 0050569321d2
$currentHostname = $env:COMPUTERNAME
$datContent = Get-Content -Path $datSourceFile -TotalCount 1 -ErrorAction SilentlyContinue
$hostnameOk = $false
$macOk = $false
$licHostname = $null
$licMac = $null
if ($datContent -match '^\s*SERVER\s+(\S+)\s+(\S+)(?:\s+(\d+))?') {
$licHostname = $Matches[1]
$licMac = $Matches[2].ToLower() -replace '[:\-]', ''
# Override default lmgrd port if specified on SERVER line
if ($Matches[3]) {
$FLM_PORT = [int]$Matches[3]
Write-OK "Detected lmgrd port from license file: $FLM_PORT"
}
# Normalize current machine MAC addresses (strip separators, lowercase)
$currentMacs = Get-NetAdapter -ErrorAction SilentlyContinue |
Where-Object { $_.Status -eq 'Up' } |
ForEach-Object { $_.MacAddress.ToLower() -replace '[:\-]', '' }
$hostnameOk = ($licHostname -eq 'ANY' -or $licHostname -eq $currentHostname)
$macOk = ($currentMacs -contains $licMac)
Write-Host ''
Write-Host ' License file binding:' -ForegroundColor White
Write-Host " Hostname : $licHostname $(if ($hostnameOk) { '[OK] matches' } else { '[!!] MISMATCH' })" -ForegroundColor $(if ($hostnameOk) { 'Green' } else { 'Yellow' })
Write-Host " MAC addr : $licMac $(if ($macOk) { '[OK] matches' } else { '[!!] MISMATCH' })" -ForegroundColor $(if ($macOk) { 'Green' } else { 'Yellow' })
Write-Host " This machine: $currentHostname" -ForegroundColor White
if (-not $hostnameOk -or -not $macOk) {
Write-Host ''
Write-Warn 'One or more license bindings do not match this machine.'
Write-Host ' The license file was generated for a specific hostname and MAC address.' -ForegroundColor Yellow
Write-Host ' If the license server fails to start, the license file needs to be' -ForegroundColor Yellow
Write-Host ' re-issued for this machine. Contact TechSoft3D support:' -ForegroundColor Yellow
Write-Host ' spinfiresupport@techsoft3d.com' -ForegroundColor Yellow
Write-Host ''
$proceed = Read-Host ' Continue anyway? (Y/N) [default: Y]'
if ($proceed -match '^[Nn]') {
Write-Host ' Setup cancelled. Please request a new license file and re-run.' -ForegroundColor Yellow
try { Stop-Transcript | Out-Null } catch {}
exit 0
}
}
} else {
Write-Warn "Could not parse SERVER line from $FLM_DATA_FILE - skipping binding check."
}
# Parse VENDOR line for optional fixed port (e.g. "VENDOR spinfired PORT=65000")
$vendorPort = $null
$datAllLines = Get-Content -Path $datSourceFile -ErrorAction SilentlyContinue
foreach ($line in $datAllLines) {
if ($line -match '^\s*VENDOR\s+\S+\s+.*PORT\s*=\s*(\d+)') {
$vendorPort = [int]$Matches[1]
Write-OK "Detected vendor daemon fixed port: $vendorPort"
break
}
}
# -- STEP 5: COPY LICENSE FILES ------------------------------------------------
Write-Step 'Copying license files to FLM install directory...'
$destLicFile = Join-Path $flmInstallDir $FLM_LICENSE_FILE
$destDatFile = Join-Path $flmInstallDir $FLM_DATA_FILE
$debugLogPath = Join-Path $flmInstallDir 'lmgrd_debug.log'
try {
Copy-Item -Path $datSourceFile -Destination $destDatFile -Force -ErrorAction Stop
Write-OK "Copied $FLM_DATA_FILE -> $destDatFile"
if ($licSourceFile) {
Copy-Item -Path $licSourceFile -Destination $destLicFile -Force -ErrorAction Stop
Write-OK "Copied $FLM_LICENSE_FILE -> $destLicFile"
} else {
Write-Warn "$FLM_LICENSE_FILE not provided - skipping (not required for license server)."
}
} catch {
Write-Fail "Failed to copy license files: $($_.Exception.Message)"
Read-Host "`nPress Enter to exit"
try { Stop-Transcript | Out-Null } catch {}
exit 1
}
# -- STEP 6: REGISTER LMGRD AS WINDOWS SERVICE --------------------------------
Write-Step "Registering '$FLM_SERVICE_NAME' as a Windows Service..."
$existingSvc = Get-Service -Name $FLM_SERVICE_NAME -ErrorAction SilentlyContinue
if ($existingSvc) {
Write-Warn "Service '$FLM_SERVICE_NAME' already exists. Removing for re-registration..."
try {
if ($existingSvc.Status -ne 'Stopped') {
Stop-Service -Name $FLM_SERVICE_NAME -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 3
}
& sc.exe delete $FLM_SERVICE_NAME | Out-Null
Start-Sleep -Seconds 2
Write-OK "Existing service removed."
} catch {
Write-Warn "Could not cleanly remove existing service: $($_.Exception.Message)"
}
}
# Build the service binary path: quoted exe + arguments
$svcBinPath = "`"$lmgrdExe`" -c `"$destDatFile`" -l `"$debugLogPath`""
try {
# New-Service passes BinaryPathName directly to SCM - most reliable quoting
New-Service `
-Name $FLM_SERVICE_NAME `
-BinaryPathName $svcBinPath `
-DisplayName $FLM_SERVICE_NAME `
-StartupType Automatic `
-Description 'SpinFire Insight Floating License Manager' `
-ErrorAction Stop | Out-Null
Write-OK "Service '$FLM_SERVICE_NAME' registered."
} catch {
Write-Warn "New-Service failed: $($_.Exception.Message). Trying sc.exe..."
try {
# sc.exe requires the binPath value as a single argument with inner escaped quotes
$proc = Start-Process 'sc.exe' `
-ArgumentList "create `"$FLM_SERVICE_NAME`" binPath= `"$svcBinPath`" start= auto DisplayName= `"$FLM_SERVICE_NAME`"" `
-Wait -PassThru -NoNewWindow -ErrorAction Stop
if ($proc.ExitCode -ne 0) { throw "sc.exe exited with code $($proc.ExitCode)" }
Write-OK "Service registered via sc.exe."
} catch {
Write-Fail "Service registration failed: $($_.Exception.Message)"
Write-Host "`n Manual alternative:" -ForegroundColor Yellow
Write-Host " Open lmtools.exe, go to 'Service/License File' tab, and configure manually." -ForegroundColor Yellow
Read-Host "`nPress Enter to exit"
try { Stop-Transcript | Out-Null } catch {}
exit 1
}
}
# -- STEP 6b: REGISTER SERVICE IN LMTOOLS (FLEXlm registry) -------------------
# lmtools.exe reads services from HKLM\SOFTWARE\FLEXlm License Manager\<name>
# The Windows Service registration above is separate - without this, lmtools
# shows no configuration even though the server runs correctly.
# The registry key is SHARED across all FlexLM applications - we only touch
# our own subkey and leave every other service's subkey untouched.
Write-Step 'Registering service in lmtools (FLEXlm registry)...'
# $lmtoolsRegBase already set at top of script (pre-flight check)
$lmtoolsRegPath = "$lmtoolsRegBase\$FLM_SERVICE_NAME"
try {
if (-not (Test-Path $lmtoolsRegBase)) {
New-Item -Path $lmtoolsRegBase -Force | Out-Null
}
New-Item -Path $lmtoolsRegPath -Force | Out-Null
# Value names confirmed by capturing what lmtools v11.19.8.0 writes on "Save Service":
# Lmgrd = path to lmgrd.exe
# License = path to license file
# LMGRD_LOG_FILE = path to debug log
# Services = 1 (use Windows service)
# start = 1 (start server at power up)
# cmdlineparams = '' (extra lmgrd args)
# Service = service name pointer (within subkey)
Set-ItemProperty -Path $lmtoolsRegPath -Name 'Lmgrd' -Value $lmgrdExe
Set-ItemProperty -Path $lmtoolsRegPath -Name 'License' -Value $destDatFile
Set-ItemProperty -Path $lmtoolsRegPath -Name 'LMGRD_LOG_FILE' -Value $debugLogPath
Set-ItemProperty -Path $lmtoolsRegPath -Name 'Services' -Value '1'
Set-ItemProperty -Path $lmtoolsRegPath -Name 'start' -Value '1'
Set-ItemProperty -Path $lmtoolsRegPath -Name 'cmdlineparams' -Value ''
Set-ItemProperty -Path $lmtoolsRegPath -Name 'Service' -Value $FLM_SERVICE_NAME
# Only update the parent "last active service" pointer if nothing else owns it,
# so we don't change another application's default selection in lmtools.
$existingPointer = (Get-ItemProperty -Path $lmtoolsRegBase -Name 'Service' -ErrorAction SilentlyContinue).Service
if (-not $existingPointer -or $existingPointer -eq $FLM_SERVICE_NAME) {
Set-ItemProperty -Path $lmtoolsRegBase -Name 'Service' -Value $FLM_SERVICE_NAME
}
Write-OK "lmtools registry entry created: $lmtoolsRegPath"
} catch {
Write-Warn "Could not write lmtools registry entry: $($_.Exception.Message)"
Write-Warn "lmtools.exe will not show the service automatically - configure it manually."
}
# -- STEP 7: START THE SERVICE -------------------------------------------------
Write-Step "Starting service '$FLM_SERVICE_NAME'..."
# Warn if another process is already holding port 27000 (another FlexLM server).
# lmgrd will fail silently if the port is taken.
$portInUse = netstat -ano 2>$null | Select-String ":$FLM_PORT\s"
if ($portInUse) {
Write-Warn "Port $FLM_PORT is already in use by another process."
Write-Host " Another FlexLM license server may be running on this machine." -ForegroundColor Yellow
Write-Host " If lmgrd fails to start, check for port conflicts and ensure" -ForegroundColor Yellow
Write-Host " each license server uses a unique port." -ForegroundColor Yellow
}
# Only kill orphaned processes if the service is not already running.
# If it IS running (re-run scenario), killing would disrupt active license checkouts.
$preStartStatus = (Get-Service -Name $FLM_SERVICE_NAME -ErrorAction SilentlyContinue).Status
if ($preStartStatus -ne 'Running') {
foreach ($procName in @('lmgrd', 'spinfired')) {
$running = Get-Process -Name $procName -ErrorAction SilentlyContinue
if ($running) {
Write-Warn "Found running $procName.exe from a previous session - stopping it..."
$running | ForEach-Object { Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue }
Write-OK "Stopped orphaned $procName.exe."
}
}
Start-Sleep -Seconds 2
}
if ($preStartStatus -eq 'Running') {
Write-OK "Service is already running - skipping start."
} else {
try {
Start-Service -Name $FLM_SERVICE_NAME -ErrorAction Stop
Start-Sleep -Seconds 5
} catch {
# lmgrd may detach from SCM after launch (FlexLM behavior) causing a false failure.
# Verify by checking whether lmgrd.exe is actually running as a process.
Start-Sleep -Seconds 3
$lmgrdRunning = Get-Process -Name 'lmgrd' -ErrorAction SilentlyContinue
if ($lmgrdRunning) {
Write-OK "lmgrd.exe is running (pid $($lmgrdRunning.Id)) - license server is operational."
Write-Warn "Windows Service status may show Stopped - this is normal for this version of FlexLM."
} else {
Write-Warn "Could not start service: $($_.Exception.Message)"
Write-Warn "Check the debug log for details: $debugLogPath"
}
}
$svcStatus = (Get-Service -Name $FLM_SERVICE_NAME -ErrorAction SilentlyContinue).Status
$lmgrdProc = Get-Process -Name 'lmgrd' -ErrorAction SilentlyContinue
if ($svcStatus -eq 'Running' -or $lmgrdProc) {
Write-OK "License server is operational. (Service: $svcStatus)"
} else {
Write-Warn "Service status: $svcStatus - lmgrd process not detected. Check the debug log."
Write-Warn "Debug log: $debugLogPath"
}
}
# -- STEP 8: CONFIGURE WINDOWS FIREWALL ----------------------------------------
Write-Step 'Configuring Windows Firewall inbound rules...'
# Rules for program executables
$programRules = @(
[pscustomobject]@{ Name = 'SpinFire_LMGRD'; Path = $lmgrdExe; Desc = 'SpinFire lmgrd license daemon' }
[pscustomobject]@{ Name = 'SpinFire_Vendor'; Path = $spinfiredExe; Desc = 'SpinFire vendor daemon (spinfired)' }
)
foreach ($rule in $programRules) {
$existing = Get-NetFirewallRule -DisplayName $rule.Name -ErrorAction SilentlyContinue
if ($existing) {
Write-OK "Firewall rule '$($rule.Name)' already exists - skipping."
continue
}
if (-not (Test-Path $rule.Path)) {
Write-Warn "'$($rule.Path)' not found - skipping firewall rule."
continue
}
try {
New-NetFirewallRule `
-DisplayName $rule.Name `
-Description $rule.Desc `
-Direction Inbound `
-Action Allow `
-Program $rule.Path `
-Profile Any `
-ErrorAction Stop | Out-Null
Write-OK "Firewall rule added: $($rule.Name)"
} catch {
Write-Warn "Could not add rule '$($rule.Name)': $($_.Exception.Message)"
}
}
# Program-based rules cover all ports used by lmgrd and spinfired - no port-specific rules needed.
# -- SUMMARY --------------------------------------------------------------------
$finalStatus = (Get-Service -Name $FLM_SERVICE_NAME -ErrorAction SilentlyContinue).Status
Write-Host ''
Write-Host ' ========================================================' -ForegroundColor Cyan
Write-Host ' Setup Complete - Summary' -ForegroundColor Cyan
Write-Host ' ========================================================' -ForegroundColor Cyan
Write-Host " Install directory : $flmInstallDir"
Write-Host " License file : $destLicFile"
Write-Host " Data file : $destDatFile"
Write-Host " Debug log : $debugLogPath"
Write-Host " Service name : $FLM_SERVICE_NAME"
Write-Host " Service status : $finalStatus"
Write-Host " Port : $FLM_PORT (TCP)"
if ($vendorPort) {
Write-Host " Vendor daemon port : $vendorPort (TCP)"
} else {
Write-Host " Vendor daemon port : dynamic (pinned via PORT= in $FLM_DATA_FILE recommended)" -ForegroundColor Yellow
}
Write-Host ''
Write-Host " Clients connect to : $FLM_PORT@$currentHostname"
Write-Host ''
Write-Host ' Firewall rules added:'
Write-Host " - SpinFire_LMGRD (lmgrd.exe - all ports)"
Write-Host " - SpinFire_Vendor (spinfired.exe - all ports)"
Write-Host ''
Write-Host " Setup log : $logFile"
Write-Host ''
Write-Host ' For support: spinfiresupport@techsoft3d.com' -ForegroundColor Yellow
Write-Host ' ========================================================' -ForegroundColor Cyan
Write-Host ''
try { Stop-Transcript | Out-Null } catch {}
Read-Host 'Press Enter to close'