Our patched standalone PC-DMIS MSI never installs the Amyuni Document Converter 500 (system printer "PC-DMIS 50 Converter"). INSTALLPDFCONVERTER is a Burn-bundle property the main MSI never reads (0 of 153 custom actions reference it; not in the Property table), and the patched-MSI strategy bypasses the bundle that would have chained the Amyuni install. The MSI only lays the installer on disk at <installdir>\PDFDriverInstallFiles\ BatFileInstallPDF50.zip and nothing runs it. Install-PCDMISPDFConverter.ps1 runs it: scans Program Files\Hexagon (and Wai) for the laid-down zip, extracts it, parses the InstallPDF50.exe invocation from the shipped bat (printer name + Wilcox licensee + license code, read not hardcoded), and runs the exe directly from the extract dir so sibling DLLs resolve. The shipped bat ends in `pause` (hangs under /qn) so we never run it. InstallPDF50.exe creates the printer then hangs (same trait as the bundle), so we poll for the printer and kill the stuck exe once it appears. Idempotent: printer already present -> exit 0. Wired as a PS1 manifest entry placed after the PC-DMIS MSIs (files must exist on disk first), no _CmmVersion (one shared printer covers every version), MarkerFile detection for one-shot at imaging. Smoke tested on the win11 VM as SYSTEM: fresh install 7.2s (printer + driver created), idempotent re-run 0.6s, both exit 0. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
142 lines
6.7 KiB
PowerShell
142 lines
6.7 KiB
PowerShell
<#
|
|
Install-PCDMISPDFConverter.ps1
|
|
|
|
Installs the PC-DMIS PDF converter (Amyuni Document Converter 500, printer name
|
|
"PC-DMIS 50 Converter").
|
|
|
|
Why this exists: our CMM image installs PC-DMIS from a patched STANDALONE MSI,
|
|
bypassing Hexagon's Burn bundle. The Amyuni PDF converter is NOT a custom action
|
|
in the main MSI (INSTALLPDFCONVERTER is a bundle property the MSI never reads).
|
|
The bundle would have run the Amyuni install as a separate chained step - which
|
|
we skip. The MSI does lay the installer down on disk at:
|
|
C:\Program Files\Hexagon\PC-DMIS <ver> 64-bit\PDFDriverInstallFiles\BatFileInstallPDF50.zip
|
|
but nothing ever executes it. This script does.
|
|
|
|
The zip ships InstallPDF50.exe + the Amyuni driver (amyuni.inf, acfpdf*.dll,
|
|
cdintf*.dll, atpdf500.cat) + InstallPDF50.bat. We do NOT run the .bat (it ends in
|
|
`pause` and hangs under /qn) - we parse its InstallPDF50.exe invocation (printer
|
|
name + Wilcox licensee + license code) and run that directly from the extracted
|
|
folder so the sibling DLLs resolve.
|
|
|
|
The converter is ONE system printer shared by every PC-DMIS version, so we install
|
|
from the first PDFDriverInstallFiles we find and stop once the printer exists.
|
|
|
|
Idempotent: if the "PC-DMIS 50 Converter" printer already exists, exits 0 without
|
|
reinstalling. Run as administrator / SYSTEM (driver install needs it).
|
|
|
|
Exit: 0 = printer present (installed or already there), 1 = failed.
|
|
#>
|
|
param(
|
|
[string]$PrinterName = 'PC-DMIS 50 Converter',
|
|
[string]$OutDir = 'C:\Logs\CMM'
|
|
)
|
|
$ErrorActionPreference = 'Continue'
|
|
New-Item -ItemType Directory -Path $OutDir -Force -ErrorAction SilentlyContinue | Out-Null
|
|
$ts = Get-Date -Format 'yyyyMMdd-HHmmss'
|
|
$log = Join-Path $OutDir "pdfconverter-$ts.log"
|
|
function Log($m){ $line = "[$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')] $m"; Write-Host $line; $line | Out-File -FilePath $log -Append -Encoding ascii }
|
|
|
|
function Test-ConverterPresent {
|
|
# Get-Printer is the authoritative check. Fall back to the printer-name key
|
|
# in the registry for old hosts where the Printing cmdlets are absent.
|
|
try { if (Get-Printer -Name $PrinterName -ErrorAction SilentlyContinue) { return $true } } catch {}
|
|
$k = 'HKLM:\SYSTEM\CurrentControlSet\Control\Print\Printers\' + $PrinterName
|
|
return (Test-Path $k)
|
|
}
|
|
|
|
Log "==== PC-DMIS PDF converter install on $env:COMPUTERNAME ===="
|
|
|
|
if (Test-ConverterPresent) {
|
|
Log "Printer '$PrinterName' already present - nothing to do."
|
|
exit 0
|
|
}
|
|
|
|
# Find the Amyuni installer the MSI laid down. PC-DMIS 2016 (vendor Wai) and
|
|
# 2019/2026 (vendor Hexagon) all install under Program Files\Hexagon, but scan
|
|
# both Hexagon and Wai trees to be safe.
|
|
$zips = @()
|
|
foreach ($root in @("$env:ProgramFiles\Hexagon","$env:ProgramFiles\Wai","${env:ProgramFiles(x86)}\Hexagon","${env:ProgramFiles(x86)}\Wai")) {
|
|
if (-not (Test-Path $root)) { continue }
|
|
$zips += Get-ChildItem -Path $root -Recurse -Filter 'BatFileInstallPDF50.zip' -ErrorAction SilentlyContinue
|
|
}
|
|
$zips = $zips | Sort-Object FullName -Unique
|
|
if (-not $zips) {
|
|
Log "ERROR: no BatFileInstallPDF50.zip found under any PC-DMIS install dir."
|
|
Log " PC-DMIS may not be installed yet, or PDFDriverInstallFiles is missing."
|
|
exit 1
|
|
}
|
|
Log ("Found {0} Amyuni installer zip(s):" -f $zips.Count)
|
|
$zips | ForEach-Object { Log " $($_.FullName)" }
|
|
|
|
Add-Type -AssemblyName System.IO.Compression.FileSystem
|
|
|
|
foreach ($zip in $zips) {
|
|
$stage = Join-Path $env:TEMP ("amyuni-pdf-" + $ts + "-" + [Guid]::NewGuid().ToString('N').Substring(0,6))
|
|
try {
|
|
New-Item -ItemType Directory -Path $stage -Force | Out-Null
|
|
[System.IO.Compression.ZipFile]::ExtractToDirectory($zip.FullName, $stage)
|
|
Log "Extracted $($zip.Name) -> $stage"
|
|
|
|
$exe = Join-Path $stage 'InstallPDF50.exe'
|
|
$bat = Join-Path $stage 'InstallPDF50.bat'
|
|
if (-not (Test-Path $exe)) { Log " no InstallPDF50.exe in zip - skipping"; continue }
|
|
|
|
# Parse InstallPDF50.bat for the exact InstallPDF50.exe arguments (printer
|
|
# name + Wilcox licensee + license code). License code can differ per
|
|
# version, so read it rather than hardcode. Strip the leading exe token.
|
|
$args = $null
|
|
if (Test-Path $bat) {
|
|
$cmd = (Get-Content $bat | Where-Object { $_ -match 'InstallPDF50\.exe' } | Select-Object -First 1)
|
|
if ($cmd) { $args = ($cmd -replace '(?i)^\s*[^"]*InstallPDF50\.exe\s*','').Trim() }
|
|
}
|
|
if (-not $args) {
|
|
# Fallback to the known-good invocation if the bat is missing/odd.
|
|
$args = '"' + $PrinterName + '" -n "Wilcox Associates, Inc."'
|
|
Log " WARN: could not parse args from bat - using fallback (no license code): $args"
|
|
} else {
|
|
Log " parsed install args from bat"
|
|
}
|
|
|
|
$psi = New-Object System.Diagnostics.ProcessStartInfo
|
|
$psi.FileName = $exe
|
|
$psi.Arguments = $args
|
|
$psi.WorkingDirectory = $stage # sibling DLLs (cdintf64.dll, acfpdf*, amyuni.inf, atpdf500.cat) must resolve
|
|
$psi.UseShellExecute = $false
|
|
$psi.CreateNoWindow = $true
|
|
$psi.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
|
|
Log " running: InstallPDF50.exe $args (cwd=$stage)"
|
|
$proc = [System.Diagnostics.Process]::Start($psi)
|
|
# InstallPDF50.exe creates the printer in a few seconds but then hangs
|
|
# (does not self-exit, same as Hexagon's Burn bundle). Poll for the
|
|
# printer instead of blocking; once it appears, kill the hung exe and
|
|
# move on. Hard cap at 90s as a backstop for a genuinely stuck install.
|
|
$deadline = (Get-Date).AddSeconds(90)
|
|
$appeared = $false
|
|
while ((Get-Date) -lt $deadline) {
|
|
if ($proc.HasExited) { Log " InstallPDF50.exe exited on its own (code $($proc.ExitCode))"; break }
|
|
if (Test-ConverterPresent) { $appeared = $true; break }
|
|
Start-Sleep -Seconds 2
|
|
}
|
|
if (-not $proc.HasExited) {
|
|
Log (" printer {0} - killing InstallPDF50.exe (it does not self-exit)" -f $(if ($appeared) { 'present' } else { 'NOT present after 90s' }))
|
|
try { $proc.Kill() } catch {}
|
|
}
|
|
|
|
Start-Sleep -Seconds 2
|
|
if (Test-ConverterPresent) {
|
|
Log "SUCCESS: printer '$PrinterName' is now present."
|
|
Remove-Item $stage -Recurse -Force -ErrorAction SilentlyContinue
|
|
exit 0
|
|
}
|
|
Log " printer not present after this attempt - trying next zip if any."
|
|
} catch {
|
|
Log " ERROR during install from $($zip.Name): $($_.Exception.Message)"
|
|
} finally {
|
|
Remove-Item $stage -Recurse -Force -ErrorAction SilentlyContinue
|
|
}
|
|
}
|
|
|
|
if (Test-ConverterPresent) { Log "Printer '$PrinterName' present."; exit 0 }
|
|
Log "ERROR: printer '$PrinterName' still not present after all attempts."
|
|
exit 1
|