<!-- Add the related story/sub-task/bug number, like Resolves #123, or remove if NA --> **Related issue:** #50020 # What this does Adds **Azure Data Studio** as a Windows Fleet-maintained app. One of the 11 apps split out of #48501 that failed the FMA validator; #50016 shipped the 6 that passed. ## Why it was failing The install itself worked — the validator logged `New application detected at: C:\Program Files\Azure Data Studio`. The *script* never returned: ``` 20:08:19 INFO msg="Executing install script..." app="Azure Data Studio" 20:18:19 ERROR msg="Error executing install script: exit status 1" # exactly 10:00 later 20:18:19 INFO msg="New application detected at: C:\Program Files\Azure Data Studio" ``` Ten minutes on the nose is the validator's `executeScript` timeout. Azure Data Studio is a Visual Studio Code fork and ships the same Inno Setup script — including the **`runcode` task, which launches the app when the install finishes**. Because `Start-Process -Wait` waits for the process *and all of its descendants*, the launched app kept the script blocked forever. The fix is the switch VS Code's own FMA already uses: `/MERGETASKS=!runcode` (see [`vscode_install.ps1`](ee/maintained-apps/inputs/winget/scripts/vscode_install.ps1) and [`vscodium_install.ps1`](ee/maintained-apps/inputs/winget/scripts/vscodium_install.ps1), both of which pass validation). The script also waits on the installer process alone rather than its descendants, polls for the Add/Remove Programs entry, and stops a stray `azuredatastudio` process as a backstop in case a future build ignores the task suppression. ## Notes - Machine-scope x64 installer, per the winget manifest — Azure Data Studio publishes both user and machine scope, and Fleet installs run as SYSTEM, so machine scope is required. - Clean ARP `DisplayName` (`Azure Data Studio`), so exact name matching. Publisher `Microsoft Corporation`. - Uninstall is unchanged: the Inno uninstaller doesn't leave anything resident, and `-Wait` waiting on descendants is the desired behavior there (Inno relaunches itself from `%TEMP%`). - Ships a new catalog icon and website asset. # Checklist for submitter - [x] 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. - [x] Timeouts are implemented and retries are limited to avoid infinite loops ## Testing - [x] FMA CI validator (install → detect → uninstall) **passes** on the SYSTEM-context Windows runner — [run 30384162280](https://github.com/fleetdm/fleet/actions/runs/30384162280) (`All checks passed`) - [x] Generated output verified locally: manifest SHA matches the winget manifest, exists/patched queries reviewed for name + publisher correctness, `apps.json` is valid JSON with a description filled in. - [x] QA'd all new/changed functionality manually <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Azure Data Studio to the available Windows software catalog. * Added support for installing and uninstalling Azure Data Studio (version 1.52.0) via silent installer and uninstaller flows with completion detection. * Added an Azure Data Studio icon to the software interface for better visual identification. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
76 lines
2.7 KiB
PowerShell
76 lines
2.7 KiB
PowerShell
# Learn more about .exe install scripts:
|
|
# http://fleetdm.com/learn-more-about/exe-install-scripts
|
|
|
|
$exeFilePath = "${env:INSTALLER_PATH}"
|
|
|
|
# ADS is a VS Code fork with the same Inno script, including the "runcode" task
|
|
# that launches the app after install. -Wait waits on descendants, so that would
|
|
# block forever; "/MERGETASKS=!runcode" suppresses the launch, as in
|
|
# vscode_install.ps1. Timeouts are sized to stay under the caller's 10-minute cap.
|
|
$installTimeoutSeconds = 420
|
|
$registrationTimeoutSeconds = 120
|
|
|
|
$machineKey = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\*'
|
|
$machineKey32on64 = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
|
|
|
|
function Test-AzureDataStudioRegistered {
|
|
$null -ne (Get-ChildItem -Path @($machineKey, $machineKey32on64) -ErrorAction SilentlyContinue |
|
|
ForEach-Object { Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue } |
|
|
Where-Object { $_.DisplayName -like "Azure Data Studio*" } |
|
|
Select-Object -First 1)
|
|
}
|
|
|
|
try {
|
|
|
|
$process = Start-Process -FilePath "$exeFilePath" `
|
|
-ArgumentList "/VERYSILENT /SUPPRESSMSGBOXES /NORESTART /MERGETASKS=!runcode" `
|
|
-PassThru
|
|
# Keeps .ExitCode readable after the process ends.
|
|
$null = $process.Handle
|
|
|
|
$killed = $false
|
|
if (-not $process.WaitForExit($installTimeoutSeconds * 1000)) {
|
|
Write-Host "Installer process did not exit within ${installTimeoutSeconds}s, stopping it."
|
|
Stop-Process -Id $process.Id -Force -ErrorAction SilentlyContinue
|
|
# Reading .ExitCode while the process is alive would throw.
|
|
$null = $process.WaitForExit(30 * 1000)
|
|
$killed = $true
|
|
}
|
|
|
|
$exitCode = $null
|
|
if ($process.HasExited) {
|
|
$exitCode = $process.ExitCode
|
|
Write-Host "Install exit code: $exitCode"
|
|
} else {
|
|
Write-Host "Installer process could not be stopped; falling back to the registration check."
|
|
}
|
|
|
|
# The installer can return before the ARP entry is written.
|
|
$elapsed = 0
|
|
while (-not (Test-AzureDataStudioRegistered) -and ($elapsed -lt $registrationTimeoutSeconds)) {
|
|
Start-Sleep -Seconds 5
|
|
$elapsed += 5
|
|
Write-Host "Waiting for Azure Data Studio to register... ($elapsed seconds)"
|
|
}
|
|
|
|
# In case a future build ignores !runcode.
|
|
Stop-Process -Name "azuredatastudio" -Force -ErrorAction SilentlyContinue
|
|
|
|
if (-not (Test-AzureDataStudioRegistered)) {
|
|
Write-Host "Azure Data Studio did not register in Add/Remove Programs."
|
|
Exit 1
|
|
}
|
|
|
|
# Registration above is the success signal; a killed process's code means nothing.
|
|
if ($killed -or $null -eq $exitCode) { Exit 0 }
|
|
|
|
# 3010 (reboot required) and 1641 (reboot initiated) are successful installs.
|
|
if ($exitCode -eq 3010 -or $exitCode -eq 1641) { Exit 0 }
|
|
|
|
Exit $exitCode
|
|
|
|
} catch {
|
|
Write-Host "Error: $_"
|
|
Exit 1
|
|
}
|