Refactored CMM/01-Setup-CMM.ps1 from local-file installer to network-
share-based pattern. CMM apps live on a file share instead of being
pre-staged locally or pulled from Azure Blob.
Framework:
1. Reads share path from site-config.json CMM profile (cmmSharePath),
falls back to West Jefferson default
2. Scans HKLM:\SOFTWARE\GE\SFLD\Credentials\* for a credential entry
whose TargetHost matches the share's server name
3. Mounts the share as S: using net use with the stored creds
4. (Placeholder) Install apps from the share
5. Disconnects the share
The Get-SFLDCredential helper function is generic and will be reused by
Genspect/Keyence scripts when their share-based installs are built. It
matches credentials by TargetHost field, supporting exact match and
domain-suffix matching.
App install blocks are commented out as placeholders — uncomment when
PC-DMIS, CLM License, and other Hexagon app details are finalized.
Added cmmSharePath to site-config.json CMM profile.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
174 lines
6.9 KiB
PowerShell
174 lines
6.9 KiB
PowerShell
# 01-Setup-CMM.ps1 - CMM-specific setup (runs after Shopfloor baseline)
|
|
#
|
|
# Installs Hexagon CMM applications from a network share using credentials
|
|
# stored in the SFLD registry by SetupCredentials.ps1 (PPKG phase).
|
|
#
|
|
# Unlike Standard PC apps (which are pre-staged locally via preinstall.json
|
|
# or pulled from Azure Blob via DSC), CMM apps live on a file share and
|
|
# are installed directly from there. The share credentials come from the
|
|
# PPKG's YAML config and are already in the registry by the time this
|
|
# script runs.
|
|
#
|
|
# The share path and app list are read from site-config.json's CMM profile
|
|
# when available, with hardcoded West Jefferson defaults as fallback.
|
|
#
|
|
# PLACEHOLDER: specific app installers (PC-DMIS, CLM License, etc.) are
|
|
# not yet finalized. The framework below handles credential lookup, share
|
|
# mounting, and has slots for each install step.
|
|
|
|
Write-Host "=== CMM Setup ==="
|
|
|
|
# --- Load site config + PC profile ---
|
|
. "$PSScriptRoot\..\Shopfloor\lib\Get-PCProfile.ps1"
|
|
|
|
# --- Configuration ---
|
|
# Share path for Hexagon CMM installers. Read from profile config,
|
|
# fall back to the known West Jefferson path.
|
|
$defaultSharePath = '\\tsgwp00525.wjs.geaerospace.net\shared\dt\shopfloor\cmm\hexagon\machineapps'
|
|
|
|
$sharePath = $defaultSharePath
|
|
if ($pcProfile -and $pcProfile.cmmSharePath) {
|
|
$sharePath = $pcProfile.cmmSharePath
|
|
} elseif ($siteConfig -and $siteConfig.pcProfiles -and $siteConfig.pcProfiles.CMM -and $siteConfig.pcProfiles.CMM.cmmSharePath) {
|
|
$sharePath = $siteConfig.pcProfiles.CMM.cmmSharePath
|
|
}
|
|
|
|
Write-Host " Share: $sharePath"
|
|
|
|
# ============================================================================
|
|
# Credential lookup - reads from HKLM:\SOFTWARE\GE\SFLD\Credentials\*
|
|
# Written by SetupCredentials.ps1 during the PPKG phase. We scan all
|
|
# credential entries and find one whose TargetHost matches the share's
|
|
# server name.
|
|
# ============================================================================
|
|
function Get-SFLDCredential {
|
|
param([string]$ServerName)
|
|
|
|
$basePath = 'HKLM:\SOFTWARE\GE\SFLD\Credentials'
|
|
if (-not (Test-Path $basePath)) {
|
|
Write-Warning "SFLD credential registry not found at $basePath"
|
|
return $null
|
|
}
|
|
|
|
$entries = Get-ChildItem -Path $basePath -ErrorAction SilentlyContinue
|
|
foreach ($entry in $entries) {
|
|
$props = Get-ItemProperty -Path $entry.PSPath -ErrorAction SilentlyContinue
|
|
if (-not $props) { continue }
|
|
|
|
$targetHost = $props.TargetHost
|
|
if (-not $targetHost) { continue }
|
|
|
|
# Match by hostname (with or without domain suffix)
|
|
if ($targetHost -eq $ServerName -or
|
|
$targetHost -like "$ServerName.*" -or
|
|
$ServerName -like "$targetHost.*") {
|
|
return @{
|
|
Username = $props.Username
|
|
Password = $props.Password
|
|
TargetHost = $targetHost
|
|
KeyName = $entry.PSChildName
|
|
}
|
|
}
|
|
}
|
|
|
|
Write-Warning "No SFLD credential found for server '$ServerName'"
|
|
return $null
|
|
}
|
|
|
|
# ============================================================================
|
|
# Mount the share
|
|
# ============================================================================
|
|
# Extract server name from UNC path: \\server\share\... -> server
|
|
$serverName = ($sharePath -replace '^\\\\', '') -split '\\' | Select-Object -First 1
|
|
|
|
$cred = Get-SFLDCredential -ServerName $serverName
|
|
$driveLetter = 'S:'
|
|
|
|
if ($cred) {
|
|
Write-Host " Credential: $($cred.KeyName) (user: $($cred.Username))"
|
|
} else {
|
|
Write-Host " No credential found for $serverName - attempting guest/current-user access"
|
|
}
|
|
|
|
# Disconnect any stale mapping
|
|
net use $driveLetter /delete /y 2>$null | Out-Null
|
|
|
|
$mountOk = $false
|
|
if ($cred -and $cred.Username -and $cred.Password) {
|
|
$result = & net use $driveLetter $sharePath /user:$($cred.Username) $($cred.Password) /persistent:no 2>&1
|
|
if ($LASTEXITCODE -eq 0) {
|
|
Write-Host " Mounted $sharePath as $driveLetter"
|
|
$mountOk = $true
|
|
} else {
|
|
Write-Warning " net use failed (exit $LASTEXITCODE): $result"
|
|
}
|
|
} else {
|
|
# Try without explicit credentials (rely on CredMan or current user)
|
|
$result = & net use $driveLetter $sharePath /persistent:no 2>&1
|
|
if ($LASTEXITCODE -eq 0) {
|
|
Write-Host " Mounted $sharePath as $driveLetter (no explicit creds)"
|
|
$mountOk = $true
|
|
} else {
|
|
Write-Warning " net use failed (exit $LASTEXITCODE): $result"
|
|
}
|
|
}
|
|
|
|
if (-not $mountOk) {
|
|
Write-Warning "Cannot access $sharePath - skipping CMM app installs."
|
|
Write-Host "=== CMM Setup Complete (share unavailable) ==="
|
|
exit 0
|
|
}
|
|
|
|
# ============================================================================
|
|
# Install apps from the share
|
|
#
|
|
# PLACEHOLDER: uncomment and adjust when app details are finalized.
|
|
# Each block follows the pattern:
|
|
# 1. Find installer on the share
|
|
# 2. Run it with silent args
|
|
# 3. Check exit code
|
|
# 4. Log result
|
|
# ============================================================================
|
|
|
|
$installRoot = $driveLetter
|
|
|
|
# --- Example: CLM Tools (license manager, install first) ---
|
|
# $clm = Get-ChildItem -Path $installRoot -Filter "CLM_*.exe" -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
# if ($clm) {
|
|
# Write-Host "Installing CLM Tools: $($clm.Name)..."
|
|
# $p = Start-Process -FilePath $clm.FullName -ArgumentList "-q -norestart" -Wait -PassThru
|
|
# Write-Host " CLM Tools exit code: $($p.ExitCode)"
|
|
# } else {
|
|
# Write-Warning "CLM Tools installer not found (expected CLM_*.exe)"
|
|
# }
|
|
|
|
# --- Example: PC-DMIS 2016 ---
|
|
# $pcdmis16 = Get-ChildItem -Path $installRoot -Filter "Pcdmis2016*x64.exe" -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
# if ($pcdmis16) {
|
|
# Write-Host "Installing PC-DMIS 2016: $($pcdmis16.Name)..."
|
|
# $p = Start-Process -FilePath $pcdmis16.FullName -ArgumentList "-q INSTALLPDFCONVERTER=0 INSTALLOFFLINEHELP=0 HEIP=0 -norestart" -Wait -PassThru
|
|
# Write-Host " PC-DMIS 2016 exit code: $($p.ExitCode)"
|
|
# } else {
|
|
# Write-Warning "PC-DMIS 2016 installer not found"
|
|
# }
|
|
|
|
# --- Example: PC-DMIS 2019 R2 ---
|
|
# $pcdmis19 = Get-ChildItem -Path $installRoot -Filter "Pcdmis2019*x64.exe" -ErrorAction SilentlyContinue | Select-Object -First 1
|
|
# if ($pcdmis19) {
|
|
# Write-Host "Installing PC-DMIS 2019 R2: $($pcdmis19.Name)..."
|
|
# $p = Start-Process -FilePath $pcdmis19.FullName -ArgumentList "-q INSTALLPDFCONVERTER=0 INSTALLOFFLINEHELP=0 HEIP=0 -norestart" -Wait -PassThru
|
|
# Write-Host " PC-DMIS 2019 exit code: $($p.ExitCode)"
|
|
# } else {
|
|
# Write-Warning "PC-DMIS 2019 installer not found"
|
|
# }
|
|
|
|
Write-Host " (no apps configured yet - uncomment install blocks when ready)"
|
|
|
|
# ============================================================================
|
|
# Cleanup
|
|
# ============================================================================
|
|
Write-Host "Disconnecting $driveLetter..."
|
|
net use $driveLetter /delete /y 2>$null | Out-Null
|
|
|
|
Write-Host "=== CMM Setup Complete ==="
|