Install-FromManifest: add FileVersion detection for version-pinned upgrades
File-existence detection on NTLARS.exe couldn't tell eDNC 6.4.3 from 6.4.4 (both installers leave the same binary in place), so the enforcer skipped upgrades. FileVersion compares the vendor-stamped FileVersion field on a named binary against the manifest's DetectionValue with exact-string match. Added to all three lib copies (common, Standard, CMM). Standard manifest template flipped to FileVersion against DncMain.exe -- the eDNC main binary is more reliably version-stamped than the bundled NTLARS sub-tool. Update workflow now: drop the new vendor MSI on the SFLD share, bump Installer + DetectionValue in machineapps-manifest.json, next user logon runs Machine-Enforce which detects mismatch and installs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -123,6 +123,22 @@ function Test-AppInstalled {
|
|||||||
"File" {
|
"File" {
|
||||||
return Test-Path $App.DetectionPath
|
return Test-Path $App.DetectionPath
|
||||||
}
|
}
|
||||||
|
"FileVersion" {
|
||||||
|
# Compare a file's VersionInfo.FileVersion against the
|
||||||
|
# manifest's expected value. Used for version-pinned MSI/EXE
|
||||||
|
# installs where existence alone doesn't tell you whether
|
||||||
|
# the right release is on disk. Exact string match - the
|
||||||
|
# manifest must carry the exact version the vendor stamps
|
||||||
|
# into the binary.
|
||||||
|
if (-not (Test-Path $App.DetectionPath)) { return $false }
|
||||||
|
if (-not $App.DetectionValue) {
|
||||||
|
Write-InstallLog " FileVersion detection requires DetectionValue - treating as not installed" "WARN"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
$actual = (Get-Item $App.DetectionPath -ErrorAction Stop).VersionInfo.FileVersion
|
||||||
|
if (-not $actual) { return $false }
|
||||||
|
return ($actual -eq $App.DetectionValue)
|
||||||
|
}
|
||||||
"Hash" {
|
"Hash" {
|
||||||
# Compare SHA256 of the on-disk file against the manifest's
|
# Compare SHA256 of the on-disk file against the manifest's
|
||||||
# expected value. Used for content-versioned files that do not
|
# expected value. Used for content-versioned files that do not
|
||||||
|
|||||||
@@ -111,6 +111,23 @@ function Test-AppInstalled {
|
|||||||
"File" {
|
"File" {
|
||||||
return Test-Path $App.DetectionPath
|
return Test-Path $App.DetectionPath
|
||||||
}
|
}
|
||||||
|
"FileVersion" {
|
||||||
|
# Compare a file's VersionInfo.FileVersion against the
|
||||||
|
# manifest's expected value. Used for version-pinned MSI/EXE
|
||||||
|
# installs where existence alone doesn't tell you whether
|
||||||
|
# the right release is on disk (e.g. eDNC 6.4.3 vs 6.4.4
|
||||||
|
# both leave NTLARS.exe in the same path). Exact string
|
||||||
|
# match - the manifest must carry the exact version the
|
||||||
|
# vendor stamps into the binary.
|
||||||
|
if (-not (Test-Path $App.DetectionPath)) { return $false }
|
||||||
|
if (-not $App.DetectionValue) {
|
||||||
|
Write-InstallLog " FileVersion detection requires DetectionValue - treating as not installed" "WARN"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
$actual = (Get-Item $App.DetectionPath -ErrorAction Stop).VersionInfo.FileVersion
|
||||||
|
if (-not $actual) { return $false }
|
||||||
|
return ($actual -eq $App.DetectionValue)
|
||||||
|
}
|
||||||
"Hash" {
|
"Hash" {
|
||||||
# Compare SHA256 of the on-disk file against the manifest's
|
# Compare SHA256 of the on-disk file against the manifest's
|
||||||
# expected value. Used for content-versioned files that do not
|
# expected value. Used for content-versioned files that do not
|
||||||
|
|||||||
@@ -14,13 +14,14 @@
|
|||||||
"DetectionValue": "REPLACE_WITH_PINNED_UDC_VERSION"
|
"DetectionValue": "REPLACE_WITH_PINNED_UDC_VERSION"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"_comment": "eDNC 6.4.3. Ships with NTLARS bundled (NTLARS.exe lands at C:\\Program Files (x86)\\Dnc\\Common\\ as part of the same install), so no separate NTLARS entry is needed. SITESELECTED encodes the site (was a recurring bug in early shopfloor-setup scripts that omitted it). Adjust to your site's value if not West Jefferson. Detection uses File on the NTLARS binary: catches the case where eDNC is installed but the sub-components we actually care about are missing. DisplayVersion detection via Registry would be tighter but the x86 uninstall key path for eDNC varies across 6.x releases.",
|
"_comment": "eDNC. Ships with NTLARS bundled (NTLARS.exe lands at C:\\Program Files (x86)\\Dnc\\Common\\ as part of the same install), so no separate NTLARS entry is needed. SITESELECTED encodes the site (was a recurring bug in early shopfloor-setup scripts that omitted it). Adjust to your site's value if not West Jefferson. Detection uses FileVersion on DncMain.exe so version upgrades actually fire (File-existence detection on NTLARS would skip the upgrade because the file already exists from the prior version). Update workflow: drop the new MSI on the SFLD share, bump DetectionValue + Installer in this manifest to the new vendor-stamped FileVersion, and the next user logon installs it.",
|
||||||
"Name": "eDNC (bundles NTLARS)",
|
"Name": "eDNC (bundles NTLARS)",
|
||||||
"Installer": "eDNC-6.4.3.msi",
|
"Installer": "eDNC-6.4.3.msi",
|
||||||
"Type": "MSI",
|
"Type": "MSI",
|
||||||
"InstallArgs": "/qn /norestart ALLUSERS=1 REBOOT=ReallySuppress SITESELECTED=\"West Jefferson\"",
|
"InstallArgs": "/qn /norestart ALLUSERS=1 REBOOT=ReallySuppress SITESELECTED=\"West Jefferson\"",
|
||||||
"DetectionMethod": "File",
|
"DetectionMethod": "FileVersion",
|
||||||
"DetectionPath": "C:\\Program Files (x86)\\Dnc\\Common\\NTLARS.exe"
|
"DetectionPath": "C:\\Program Files (x86)\\Dnc\\bin\\DncMain.exe",
|
||||||
|
"DetectionValue": "6.4.3"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"_comment": "Custom eMxInfo.txt (site-specific eDNC config). No vendor installer - the secret file lives on the SFLD share alongside the eDNC MSI. Install-eMxInfo.cmd copies it to both 32-bit and 64-bit eDNC Program Files paths. Hash detection catches both 'file missing' and 'file is a stale version'. Yearly rotation procedure: drop the new eMxInfo.txt on the share, recompute its SHA256 (PowerShell: (Get-FileHash .\\eMxInfo.txt -Algorithm SHA256).Hash), paste the new hash into DetectionValue here, save. Every Machine PC catches up on the next user logon. Content-sensitive: eMxInfo.txt must NEVER be committed to git (already in .gitignore).",
|
"_comment": "Custom eMxInfo.txt (site-specific eDNC config). No vendor installer - the secret file lives on the SFLD share alongside the eDNC MSI. Install-eMxInfo.cmd copies it to both 32-bit and 64-bit eDNC Program Files paths. Hash detection catches both 'file missing' and 'file is a stale version'. Yearly rotation procedure: drop the new eMxInfo.txt on the share, recompute its SHA256 (PowerShell: (Get-FileHash .\\eMxInfo.txt -Algorithm SHA256).Hash), paste the new hash into DetectionValue here, save. Every Machine PC catches up on the next user logon. Content-sensitive: eMxInfo.txt must NEVER be committed to git (already in .gitignore).",
|
||||||
|
|||||||
@@ -111,6 +111,23 @@ function Test-AppInstalled {
|
|||||||
"File" {
|
"File" {
|
||||||
return Test-Path $App.DetectionPath
|
return Test-Path $App.DetectionPath
|
||||||
}
|
}
|
||||||
|
"FileVersion" {
|
||||||
|
# Compare a file's VersionInfo.FileVersion against the
|
||||||
|
# manifest's expected value. Used for version-pinned MSI/EXE
|
||||||
|
# installs where existence alone doesn't tell you whether
|
||||||
|
# the right release is on disk (e.g. eDNC 6.4.3 vs 6.4.4
|
||||||
|
# both leave NTLARS.exe in the same path). Exact string
|
||||||
|
# match - the manifest must carry the exact version the
|
||||||
|
# vendor stamps into the binary.
|
||||||
|
if (-not (Test-Path $App.DetectionPath)) { return $false }
|
||||||
|
if (-not $App.DetectionValue) {
|
||||||
|
Write-InstallLog " FileVersion detection requires DetectionValue - treating as not installed" "WARN"
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
$actual = (Get-Item $App.DetectionPath -ErrorAction Stop).VersionInfo.FileVersion
|
||||||
|
if (-not $actual) { return $false }
|
||||||
|
return ($actual -eq $App.DetectionValue)
|
||||||
|
}
|
||||||
"Hash" {
|
"Hash" {
|
||||||
# Compare SHA256 of the on-disk file against the manifest's
|
# Compare SHA256 of the on-disk file against the manifest's
|
||||||
# expected value. Used for content-versioned files that do not
|
# expected value. Used for content-versioned files that do not
|
||||||
|
|||||||
Reference in New Issue
Block a user