Files
Harrison RavazzoloandAllen Houchins 7b7b89af7e Windows FMA - Canva Desktop (#46310)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added support for Canva Desktop on Windows with automated installation
and uninstallation workflows.
* Canva is now registered in the maintained applications library for
Windows.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46310?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Allen Houchins <allenhouchins@mac.com>
2026-05-28 13:32:10 -05:00

79 lines
2.5 KiB
PowerShell

$displayName = "Canva"
$publisher = "Canva"
$paths = @(
'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
'HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall',
'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall',
'HKCU:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall'
)
$uninstall = $null
foreach ($p in $paths) {
$items = Get-ItemProperty "$p\*" -ErrorAction SilentlyContinue | Where-Object {
$_.DisplayName -and ($_.DisplayName -eq $displayName -or $_.DisplayName -like "$displayName*") -and
($publisher -eq "" -or $_.Publisher -like "*$publisher*")
}
if ($items) { $uninstall = $items | Select-Object -First 1; break }
}
if (-not $uninstall -or -not $uninstall.UninstallString) {
Write-Host "Uninstall entry not found"
Exit 0
}
# Kill any running Canva processes before uninstalling.
Stop-Process -Name "Canva" -Force -ErrorAction SilentlyContinue
Start-Sleep -Seconds 2
$uninstallString = $uninstall.UninstallString
$exePath = ""
# Parse the uninstall string. Handle both quoted and unquoted exe paths.
if ($uninstallString -match '^"([^"]+)"(.*)') {
$exePath = $matches[1]
} elseif ($uninstallString -match '^(.+?\.exe)(.*)$') {
$exePath = $matches[1]
} else {
Write-Host "Error: Could not parse uninstall string: $uninstallString"
Exit 1
}
# Prefer the registry InstallLocation; fall back to the uninstaller's parent
# directory. _?=<installdir> must match $INSTDIR for NSIS to honor it.
$installDir = if ($uninstall.InstallLocation -and (Test-Path -LiteralPath $uninstall.InstallLocation)) {
$uninstall.InstallLocation.TrimEnd('\')
} else {
(Split-Path -Parent $exePath).TrimEnd('\')
}
$argumentList = @("/S", "_?=$installDir")
Write-Host "Uninstall executable: $exePath"
Write-Host "Uninstall arguments: $($argumentList -join ' ')"
try {
$processOptions = @{
FilePath = $exePath
ArgumentList = $argumentList
NoNewWindow = $true
PassThru = $true
Wait = $true
}
$process = Start-Process @processOptions
$exitCode = $process.ExitCode
Write-Host "Uninstall exit code: $exitCode"
# NSIS run in-place can't delete its own exe; sweep the leftover folder
# so detection sees a clean state.
if (Test-Path -LiteralPath $installDir) {
Remove-Item -LiteralPath $installDir -Recurse -Force -ErrorAction SilentlyContinue
}
Exit $exitCode
} catch {
Write-Host "Error running uninstaller: $_"
Exit 1
}