Skip to content

Add Dell Display and Peripheral Manager Windows FMA - #50030

Closed
kitzy wants to merge 2 commits into
mainfrom
add-dell-dapm-windows-fma
Closed

Add Dell Display and Peripheral Manager Windows FMA#50030
kitzy wants to merge 2 commits into
mainfrom
add-dell-dapm-windows-fma

Conversation

@kitzy

@kitzy kitzy commented Jul 28, 2026

Copy link
Copy Markdown
Member

Related issue: #50020

What this does

Adds Dell Display and Peripheral Manager as a Windows Fleet-maintained app, and un-freezes it so CI actually validates it.

This app was carried at "frozen": true through #48501, which means the validator skipped it entirely (App is frozen, skipping validation...). #50020 calls for it to be un-frozen and validated, or dropped. This PR does the former.

What changed

"frozen": true is removed from the input, so the validator runs install → detect → uninstall like every other app.

Because the scripts have never actually been exercised, they're hardened up front for the two hazards this installer presents rather than waiting for CI to find them:

  • InstallShield hand-off. The setup extracts to %TEMP% and hands off to child processes, so the parent can exit before the Add/Remove Programs entry is written. The install script waits on the installer process alone (Start-Process -Wait waits for the process and all of its descendants, which is what broke five other apps in this batch), then polls for the ARP entry with a bounded window.
  • Resident background app. DDPM leaves its own app running after install, which would both block -Wait and hold file locks during uninstall. Both scripts stop it explicitly.

The uninstall script also resolves an MSI product code when the registry string is an MsiExec /X{...} command and re-runs it with /quiet /norestart — the same session-0 dialog problem fixed for Google Earth Pro in #50022 — falling back to the InstallShield uninstaller with /Silent otherwise.

Notes

  • Identity verified against the installer, not winget metadata. The setup's PE version resource reads CompanyName: Dell Technologies and ProductName: Dell Display and Peripheral Manager, matching unique_identifier and the exists query's publisher.
  • /Silent is the documented machine-scope Silent switch from the winget manifest.
  • Large installer (~425 MB). Confirmed downloadable by Go's HTTP client, which is what Fleet uses — worth noting because Dell's CDN 403s some other clients, so a curl spot-check of this URL is misleading.
  • Ships a new catalog icon and website asset.

Checklist for submitter

  • Input data is properly validated, SELECT * is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters.
  • Timeouts are implemented and retries are limited to avoid infinite loops

Testing

  • FMA CI validator (install → detect → uninstall) on the SYSTEM-context Windows runner — pending on this PR, and the point of it
  • Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries checked against the installer's PE version resource, apps.json is valid JSON with a description filled in.
  • QA'd all new/changed functionality manually

Removes frozen: true so the validator actually exercises install, detect and
uninstall. The scripts were never run in CI, so they are hardened up front for
the two hazards this installer presents: an InstallShield parent that hands off
to child processes and can exit before the ARP entry is written, and a background
app that stays resident afterwards -- both of which break Start-Process -Wait,
which waits for descendants as well as the process itself.
Copilot AI review requested due to automatic review settings July 28, 2026 00:19
@codecov

codecov Bot commented Jul 28, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 50.00000% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 67.97%. Comparing base (b64fdaa) to head (6938662).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...mponents/icons/DellDisplayAndPeripheralManager.tsx 50.00% 1 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #50030   +/-   ##
=======================================
  Coverage   67.97%   67.97%           
=======================================
  Files        3922     3923    +1     
  Lines      250032   250034    +2     
  Branches    13334    13334           
=======================================
+ Hits       169949   169954    +5     
+ Misses      64781    64778    -3     
  Partials    15302    15302           
Flag Coverage Δ
frontend 60.41% <50.00%> (+0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds the Dell Display and Peripheral Manager Windows Fleet-maintained app (FMA) and its associated UI icon so it can be installed/detected/uninstalled by the maintained-app validator and displayed with a branded icon in the Software UI.

Changes:

  • Added a new software icon component and mapped it in the SoftwarePage icon registry.
  • Added Dell Display and Peripheral Manager to the maintained apps catalog (outputs/apps.json) and introduced its Windows output manifest.
  • Added Winget input JSON and install/uninstall PowerShell scripts for the Windows FMA.

Reviewed changes

Copilot reviewed 7 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
frontend/pages/SoftwarePage/components/icons/index.ts Registers the new Dell Display and Peripheral Manager icon in the name→icon map.
frontend/pages/SoftwarePage/components/icons/DellDisplayAndPeripheralManager.tsx Adds the Dell Display and Peripheral Manager icon component.
ee/maintained-apps/outputs/dell-display-and-peripheral-manager/windows.json Introduces the generated Windows manifest + embedded install/uninstall scripts for the app.
ee/maintained-apps/outputs/apps.json Adds the app to the maintained-apps catalog list with description and slug.
ee/maintained-apps/inputs/winget/scripts/dell_dapm_uninstall.ps1 Adds uninstall script with registry lookup and MSI/InstallShield handling.
ee/maintained-apps/inputs/winget/scripts/dell_dapm_install.ps1 Adds install script with bounded waiting and ARP polling.
ee/maintained-apps/inputs/winget/dell-display-and-peripheral-manager.json Adds the Winget input definition for generating the Windows manifest.
Comments suppressed due to low confidence (1)

ee/maintained-apps/outputs/dell-display-and-peripheral-manager/windows.json:20

  • This embedded install script uses $installTimeoutSeconds=480 and then can additionally poll up to 180s for ARP registration. Since the Windows validator kills scripts after 10 minutes (cmd/maintained-apps/validate/windows.go:297), the generated output here can exceed the cap and fail validation. Please ensure the generated output is regenerated/updated so the total worst-case runtime stays under 10 minutes.
    "f60b0b6e": "# Learn more about .exe install scripts:\n# http://fleetdm.com/learn-more-about/exe-install-scripts\n\n$exeFilePath = \"${env:INSTALLER_PATH}\"\n\n# Dell Display and Peripheral Manager ships an InstallShield setup (~425 MB) that\n# extracts to %TEMP%, hands off to child processes, and leaves its own background\n# app running once installed. PowerShell's \"Start-Process -Wait\" waits for the\n# process *and all of its descendants*, so those would block this script. Wait on\n# the installer process alone, poll for the Add/Remove Programs entry (the\n# hand-off means the parent can exit before the install is finished), then stop\n# what the installer left running.\n# \"/Silent\" is the documented machine-scope Silent switch from the winget manifest.\n$installTimeoutSeconds = 480\n$pollSeconds = 15\n$leftovers = @(\"DDPM\", \"DellDisplayManager\", \"DisplayManager\")\n\n$machineKey = 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n$machineKey32on64 = 'HKLM:\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n\nfunction Test-DdpmRegistered {\n    $null -ne (Get-ChildItem -Path @($machineKey, $machineKey32on64) -ErrorAction SilentlyContinue |\n        ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue } |\n        Where-Object { $_.DisplayName -like \"Dell Display and Peripheral Manager*\" } |\n        Select-Object -First 1)\n}\n\ntry {\n\n$process = Start-Process -FilePath \"$exeFilePath\" -ArgumentList \"/Silent\" -PassThru\n# Touch .Handle so the exit code is still readable after the process ends:\n# Start-Process -PassThru otherwise returns $null for .ExitCode.\n$null = $process.Handle\n\n$elapsed = 0\nwhile (-not $process.HasExited -and ($elapsed -lt $installTimeoutSeconds)) {\n  Start-Sleep -Seconds $pollSeconds\n  $elapsed += $pollSeconds\n  Write-Host \"Installing... ($elapsed seconds, registered: $(Test-DdpmRegistered))\"\n}\n\nif (-not $process.HasExited) {\n  $registered = Test-DdpmRegistered\n  Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue\n  Start-Sleep -Seconds 2\n  foreach ($name in $leftovers) { Stop-Process -Name $name -Force -ErrorAction SilentlyContinue }\n\n  if ($registered) {\n    Write-Host \"Installer still running after ${installTimeoutSeconds}s but DDPM is registered; stopped the lingering process.\"\n    Exit 0\n  }\n\n  Write-Host \"Installer did not finish within ${installTimeoutSeconds}s and DDPM is not registered.\"\n  Exit 1\n}\n\n$exitCode = $process.ExitCode\nWrite-Host \"Install exit code: $exitCode\"\n\n# InstallShield's parent process can exit before the child finishes writing the\n# Add/Remove Programs entry, so give it a bounded window to appear.\n$elapsed = 0\nwhile (-not (Test-DdpmRegistered) -and ($elapsed -lt 180)) {\n  Start-Sleep -Seconds $pollSeconds\n  $elapsed += $pollSeconds\n  Write-Host \"Waiting for DDPM to register... ($elapsed seconds)\"\n}\n\nforeach ($name in $leftovers) { Stop-Process -Name $name -Force -ErrorAction SilentlyContinue }\n\nif (-not (Test-DdpmRegistered)) {\n  Write-Host \"Dell Display and Peripheral Manager did not register in Add/Remove Programs.\"\n  Exit 1\n}\n\n# 3010 (reboot required) and 1641 (reboot initiated) are successful installs.\nif ($exitCode -eq 3010 -or $exitCode -eq 1641) { Exit 0 }\n\nExit $exitCode\n\n} catch {\n  Write-Host \"Error: $_\"\n  Exit 1\n}\n"

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

# hand-off means the parent can exit before the install is finished), then stop
# what the installer left running.
# "/Silent" is the documented machine-scope Silent switch from the winget manifest.
$installTimeoutSeconds = 480
# itself -- would block this script. Stop those first, then wait only on the
# uninstaller and poll until the Add/Remove Programs entry clears.
$leftovers = @("DDPM", "DellDisplayManager", "DisplayManager")
$timeoutSeconds = 480
}
],
"refs": {
"d73afcc1": "$softwareName = \"Dell Display and Peripheral Manager\"\n\n# The install leaves DDPM's background app running, which holds file locks and --\n# because \"Start-Process -Wait\" waits for descendants as well as the process\n# itself -- would block this script. Stop those first, then wait only on the\n# uninstaller and poll until the Add/Remove Programs entry clears.\n$leftovers = @(\"DDPM\", \"DellDisplayManager\", \"DisplayManager\")\n$timeoutSeconds = 480\n\n$machineKey = 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n$machineKey32on64 = 'HKLM:\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\*'\n$exitCode = 0\n\nfunction Get-DdpmUninstallKey {\n Get-ChildItem -Path @($machineKey, $machineKey32on64) -ErrorAction SilentlyContinue |\n ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue } |\n Where-Object { $_.DisplayName -like \"$softwareName*\" } |\n Select-Object -First 1\n}\n\nforeach ($name in $leftovers) {\n Stop-Process -Name $name -Force -ErrorAction SilentlyContinue\n}\n\ntry {\n $key = Get-DdpmUninstallKey\n if (-not $key) {\n Write-Host \"Uninstaller for '$softwareName' not found.\"\n Exit 1\n }\n\n $uninstallString = if ($key.QuietUninstallString) { $key.QuietUninstallString } else { $key.UninstallString }\n Write-Host \"Uninstall string: $uninstallString\"\n\n # If this resolves to an MSI product, uninstall it with msiexec directly --\n # the registry string typically omits a quiet switch, which would raise an\n # invisible dialog in session 0 and silently do nothing.\n $productCode = $null\n if ($uninstallString -match '(?i)msiexec(\\.exe)?.*?[/-][xi]\\s*(\\{[0-9A-Fa-f\\-]+\\})') {\n $productCode = $Matches[2]\n } elseif ($key.PSChildName -match '^\\{[0-9A-Fa-f\\-]+\\}$') {\n $productCode = $key.PSChildName\n }\n\n if ($productCode) {\n Write-Host \"Uninstalling MSI product $productCode\"\n $process = Start-Process -FilePath \"msiexec.exe\" `\n -ArgumentList \"/x\", $productCode, \"/quiet\", \"/norestart\" `\n -PassThru -NoNewWindow\n } else {\n # InstallShield uninstaller: parse the executable path, handling quoted\n # paths, unquoted paths containing spaces, and bare tokens, then pass the\n # documented silent switch.\n $uninstallCommand = $uninstallString\n $uninstallArgs = \"/Silent\"\n if ($uninstallCommand -match '^\\s*\"([^\"]+)\"\\s*(.*)$') {\n $uninstallCommand = $Matches[1]\n if ($Matches[2]) { $uninstallArgs = \"$($Matches[2]) $uninstallArgs\".Trim() }\n } elseif ($uninstallCommand -match '(?i)^\\s*(.+?\\.exe)\\s*(.*)$') {\n $uninstallCommand = $Matches[1]\n if ($Matches[2]) { $uninstallArgs = \"$($Matches[2]) $uninstallArgs\".Trim() }\n } elseif ($uninstallCommand -match '^\\s*(\\S+)\\s*(.*)$') {\n $uninstallCommand = $Matches[1]\n if ($Matches[2]) { $uninstallArgs = \"$($Matches[2]) $uninstallArgs\".Trim() }\n }\n\n Write-Host \"Uninstall command: $uninstallCommand\"\n Write-Host \"Uninstall args: $uninstallArgs\"\n $process = Start-Process -FilePath $uninstallCommand -ArgumentList $uninstallArgs -PassThru\n }\n\n # Touch .Handle so the exit code is still readable after the process ends:\n # Start-Process -PassThru otherwise returns $null for .ExitCode.\n $null = $process.Handle\n\n if (-not $process.WaitForExit($timeoutSeconds * 1000)) {\n Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue\n Write-Host \"Uninstall timed out after $timeoutSeconds seconds\"\n Exit 1603\n }\n\n $exitCode = $process.ExitCode\n Write-Host \"Uninstall exit code: $exitCode\"\n} catch {\n Write-Host \"Error: $_\"\n Exit 1\n}\n\nforeach ($name in $leftovers) {\n Stop-Process -Name $name -Force -ErrorAction SilentlyContinue\n}\n\n$elapsed = 0\nwhile ((Get-DdpmUninstallKey) -and ($elapsed -lt 180)) {\n Start-Sleep -Seconds 5\n $elapsed += 5\n Write-Host \"Waiting for the uninstall to finish... ($elapsed seconds)\"\n}\n\nif (Get-DdpmUninstallKey) {\n Write-Host \"'$softwareName' is still registered after the uninstall.\"\n Exit 1\n}\n\n# 3010 (reboot required) and 1641 (reboot initiated) are successful uninstalls.\nif ($exitCode -eq 3010 -or $exitCode -eq 1641) { Exit 0 }\n\nExit $exitCode\n",
Comment on lines +1 to +6
{
"name": "Dell Display and Peripheral Manager",
"slug": "dell-display-and-peripheral-manager/windows",
"package_identifier": "Dell.DisplayAndPeripheralManager",
"unique_identifier": "Dell Display and Peripheral Manager",
"program_publisher": "Dell Technologies",
The winget manifest's /Silent produced exit code -2147213312 (0x80042000) with
nothing installed. This is an InstallShield setup, whose silent switch is /S --
also what ManageEngine's silent-install reference documents for DDPM 2.2.2.8.
Adds Dell's /CreateDebugLog so a further failure is diagnosable from the CI log
rather than needing another blind cycle.
Copilot AI review requested due to automatic review settings July 28, 2026 00:33
@github-actions

Copy link
Copy Markdown
Contributor

Script Diff Results

ee/maintained-apps/outputs/dell-display-and-peripheral-manager/windows.json

=== Install // f60b0b6e -> ac21302d ===

--- /tmp/old.crQD0i	2026-07-28 00:34:42.893574485 +0000
+++ /tmp/new.9h1wnu	2026-07-28 00:34:42.893574485 +0000
@@ -10,16 +10,33 @@
 # the installer process alone, poll for the Add/Remove Programs entry (the
 # hand-off means the parent can exit before the install is finished), then stop
 # what the installer left running.
-# "/Silent" is the documented machine-scope Silent switch from the winget manifest.
+# Switch choice: the winget manifest lists "/Silent", but that produced exit code
+# -2147213312 (0x80042000) with nothing installed. This is an InstallShield setup,
+# whose actual silent switch is "/S" -- which is also what ManageEngine's silent
+# install reference documents for DDPM 2.2.2.8. "/CreateDebugLog" is Dell's own
+# logging switch, so a future failure is diagnosable from the CI log.
 $installTimeoutSeconds = 480
 $pollSeconds = 15
 $leftovers = @("DDPM", "DellDisplayManager", "DisplayManager")
 
+$dellLog = Join-Path $env:TEMP "ddpm-install.log"
+
 $machineKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*'
 $machineKey32on64 = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
+$userKey = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*'
+
+function Write-DellLog {
+    if (Test-Path $dellLog) {
+        Write-Host "--- DDPM install log (last 60 lines) ---"
+        Get-Content $dellLog -Tail 60 | ForEach-Object { Write-Host $_ }
+        Write-Host "--- end of DDPM install log ---"
+    } else {
+        Write-Host "No DDPM install log was written at $dellLog."
+    }
+}
 
 function Test-DdpmRegistered {
-    $null -ne (Get-ChildItem -Path @($machineKey, $machineKey32on64) -ErrorAction SilentlyContinue |
+    $null -ne (Get-ChildItem -Path @($machineKey, $machineKey32on64, $userKey) -ErrorAction SilentlyContinue |
         ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue } |
         Where-Object { $_.DisplayName -like "Dell Display and Peripheral Manager*" } |
         Select-Object -First 1)
@@ -27,7 +44,9 @@
 
 try {
 
-$process = Start-Process -FilePath "$exeFilePath" -ArgumentList "/Silent" -PassThru
+$process = Start-Process -FilePath "$exeFilePath" `
+  -ArgumentList "/S /CreateDebugLog=`"$dellLog`"" `
+  -PassThru
 # Touch .Handle so the exit code is still readable after the process ends:
 # Start-Process -PassThru otherwise returns $null for .ExitCode.
 $null = $process.Handle
@@ -51,6 +70,7 @@
   }
 
   Write-Host "Installer did not finish within ${installTimeoutSeconds}s and DDPM is not registered."
+  Write-DellLog
   Exit 1
 }
 
@@ -70,6 +90,7 @@
 
 if (-not (Test-DdpmRegistered)) {
   Write-Host "Dell Display and Peripheral Manager did not register in Add/Remove Programs."
+  Write-DellLog
   Exit 1
 }
 

=== Uninstall // d73afcc1 -> 4219524c ===

--- /tmp/old.tdYhHh	2026-07-28 00:34:42.918574524 +0000
+++ /tmp/new.LaMel9	2026-07-28 00:34:42.919574525 +0000
@@ -50,9 +50,11 @@
     } else {
         # InstallShield uninstaller: parse the executable path, handling quoted
         # paths, unquoted paths containing spaces, and bare tokens, then pass the
-        # documented silent switch.
+        # documented silent switch. "/S" is InstallShield's silent switch and what
+        # ManageEngine's DDPM reference documents for uninstall as well; the winget
+        # manifest's "/Silent" is not recognised by this installer.
         $uninstallCommand = $uninstallString
-        $uninstallArgs = "/Silent"
+        $uninstallArgs = "/S"
         if ($uninstallCommand -match '^\s*"([^"]+)"\s*(.*)$') {
             $uninstallCommand = $Matches[1]
             if ($Matches[2]) { $uninstallArgs = "$($Matches[2]) $uninstallArgs".Trim() }

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 7 out of 8 changed files in this pull request and generated 2 comments.

Comment on lines +38 to +43
function Test-DdpmRegistered {
$null -ne (Get-ChildItem -Path @($machineKey, $machineKey32on64, $userKey) -ErrorAction SilentlyContinue |
ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue } |
Where-Object { $_.DisplayName -like "Dell Display and Peripheral Manager*" } |
Select-Object -First 1)
}
Comment on lines +14 to +19
function Get-DdpmUninstallKey {
Get-ChildItem -Path @($machineKey, $machineKey32on64) -ErrorAction SilentlyContinue |
ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue } |
Where-Object { $_.DisplayName -like "$softwareName*" } |
Select-Object -First 1
}
@kitzy

kitzy commented Jul 28, 2026

Copy link
Copy Markdown
Member Author

Closing: Dell DAPM is being dropped from #50020 with a documented reason. Un-freezing it produced the first real validator evidence for this app — it aborts at exit code 0x80042000 before installing anything, identically for both /Silent and /S, because DDPM does not support Windows Server and the runner is Windows Server 2025. Full evidence on the issue.

@kitzy kitzy closed this Jul 28, 2026
@kitzy
kitzy deleted the add-dell-dapm-windows-fma branch July 28, 2026 16:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants