Skip to content

Instantly share code, notes, and snippets.

@alirobe
Last active August 14, 2025 01:26
Show Gist options
  • Save alirobe/17864cb8336ea9dc3d4da61fb5d6a596 to your computer and use it in GitHub Desktop.
Save alirobe/17864cb8336ea9dc3d4da61fb5d6a596 to your computer and use it in GitHub Desktop.
A quick script to download all the unmanaged solutions in a D365 environment, and extracting them to folders, suitable for backing up unmanaged solutions in source control.
# Backup Solutions from Dataverse Environment
# https://gist.github.com/alirobe/17864cb8336ea9dc3d4da61fb5d6a596
### Settings ###
$skipExisting = $false # change to $true to update
### Script ###
$solutionsList = pac solution list
$solutionsList > solutions-list.txt
$firstLine = 5 # to be changed if output from pac tool changes
$existing = Get-ChildItem -Path . -Directory
$extracted = @()
if ($solutionsList.Count -lt 5 -or -not $solutionsList[4].StartsWith("Unique Name")) {
Write-Host "Unexpected output format. Ensure you are connected to the correct Dataverse organization and the solutions list is formatted correctly."
}
foreach ($line in $solutionsList[$firstLine..999]) {
$solution = $line -split ' ' | Select-Object -First 1
if($line.Trim().EndsWith("True") -or $solution -eq "Default") {
Write-Host "Skipping managed or default solution: $solution"
continue
}
if ($solution -eq $null -or $solution.Trim() -eq "" -or -not $line.Trim().EndsWith("False")) {
Write-Host "Skipping invalid solution definition in line: $line"
continue
}
if($existing.Name -contains $solution) {
if($skipExisting) {
Write-Host "Skipping existing solution: $solution (turn off skipExisting to updae)"
continue
} else {
Write-Host "Removing existing solution for update: $solution"
Remove-Item -Path ./$solution -Recurse -Force
}
}
Write-Host "Processing solution: $solution"
pac solution export --name $solution
Expand-Archive -Path "$solution.zip" -DestinationPath ./$solution
$extracted += "./$solution.zip"
}
foreach ($zip in $extracted) {
Write-Host "Cleaning up zip: $zip"
Start-Sleep -Seconds 2 # expansion can sometimes exit prematurely
Remove-Item -Path $zip
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment