Wer mehrere Power Automate Flows sichern will, klickt sich im Maker Portal einzeln durch Export-Dialoge. Für schnelle Ad-hoc-Backups ist das mühsam. Also habe ich mir ein kleines PnP.PowerShell-Skript bauen lassen, das mir die Arbeit abnimmt: Es listet die Power-Platform-Environments zur Auswahl (Out-GridView), zeigt darin die eigenen (optional auch geteilten) Flows, und exportiert die markierten als ZIP-Pakete in eine saubere Ordnerstruktur pro Environment.
Kern ist die Kombination aus Get-PnPPowerPlatformEnvironment, Get-PnPFlow und Export-PnPFlow -AsZipPackage, verpackt in zwei interaktive Auswahlschritte. Voraussetzungen: PnP.PowerShell 3.x, PowerShell 7.x und eine eigene App-Registrierung mit den passenden Delegated Permissions.
Anmerkung: Das ist der „Quick & Dirty“-Weg — einzelne Flows als ZIP wegsichern, ohne großes Drumherum. Für alles, was Richtung sauberes Deployment zwischen Environments (Dev → Test → Prod) geht, ist das nicht der richtige Weg. Dafür gibt es in der Power Platform ein ganzes Ökosystem rund um Solutions und das PAC CLI — Stichwort ALM. Da habe ich mal reingeschaut, bin aber ehrlicherweise kein Experte und würde jedem, der es ernst meint, empfehlen, sich das direkt bei Microsoft anzuschauen. Dieses Skript ersetzt das nicht und will es auch nicht — es ist einfach ein praktisches Helferlein, wenn man mal eben ein paar Flows greifen und wegsichern will.
Das Skript
<#
.SYNOPSIS
Exportiert ausgewaehlte Power Automate Flows interaktiv als ZIP-Pakete.
.DESCRIPTION
Listet Power-Platform-Environments und darin die eigenen (optional geteilten)
Flows per Out-GridView zur Mehrfachauswahl und exportiert die markierten
Flows als ZIP in eine Ordnerstruktur pro Environment.
Voraussetzungen:
- PowerShell 7.x (PnP.PowerShell 3.x setzt PS7 voraus)
- PnP.PowerShell 3.x
- Eigene App-Registrierung in Entra ID mit Delegated Permissions
fuer die Power Platform (z. B. Flows.Read.All).
ClientId unten eintragen.
#>
param(
[string]$TenantUrl = 'contoso.sharepoint.com',
[string]$ClientId = '<DEINE-APP-REGISTRATION-CLIENT-ID>',
[string]$ExportFolder = "$env:USERPROFILE\Downloads\PowerAutomateFlowExport",
[switch]$IncludeSharedWithMe
)
$ErrorActionPreference = "Stop"
function Get-SafeFileName {
param([Parameter(Mandatory)][string]$Name)
foreach ($Char in [System.IO.Path]::GetInvalidFileNameChars()) {
$Name = $Name.Replace($Char, "_")
}
if ($Name.Length -gt 120) { $Name = $Name.Substring(0, 120) }
return $Name
}
function Get-DisplayName {
param([Parameter(Mandatory)]$Object)
if ($Object.DisplayName) { return $Object.DisplayName }
if ($Object.Properties.DisplayName) { return $Object.Properties.DisplayName }
if ($Object.Properties.EnvironmentDetails.DisplayName) { return $Object.Properties.EnvironmentDetails.DisplayName }
if ($Object.Name) { return $Object.Name }
return "Unknown"
}
if ($PSVersionTable.PSVersion.Major -lt 7) {
throw "PnP.PowerShell 3.x benoetigt PowerShell 7.x. Aktuell: $($PSVersionTable.PSVersion)"
}
if (-not (Get-Module -ListAvailable -Name PnP.PowerShell)) {
throw "PnP.PowerShell nicht gefunden. Installieren mit: Install-Module PnP.PowerShell"
}
Import-Module PnP.PowerShell -Force
New-Item -Path $ExportFolder -ItemType Directory -Force | Out-Null
Write-Host "Verbinde mit $TenantUrl ..." -ForegroundColor Cyan
$Connection = Connect-PnPOnline -Url $TenantUrl -Interactive -ClientId $ClientId -ReturnConnection
Write-Host "Lade Power-Platform-Umgebungen ..." -ForegroundColor Cyan
$Environments = Get-PnPPowerPlatformEnvironment -Connection $Connection
if (-not $Environments) {
Write-Host "Keine Umgebungen gefunden." -ForegroundColor Yellow
exit 0
}
$EnvRows = foreach ($Env in $Environments) {
[PSCustomObject]@{
DisplayName = Get-DisplayName $Env
Name = $Env.Name
Object = $Env
}
}
$SelectedEnvironments = $EnvRows |
Sort-Object DisplayName |
Out-GridView -PassThru -Title "Power-Platform-Umgebung(en) auswaehlen"
if (-not $SelectedEnvironments) {
Write-Host "Keine Umgebung ausgewaehlt. Abbruch." -ForegroundColor Yellow
exit 0
}
foreach ($EnvRow in $SelectedEnvironments) {
$Environment = $EnvRow.Object
Write-Host ""
Write-Host "Umgebung: $($EnvRow.DisplayName)" -ForegroundColor Cyan
$Flows = Get-PnPFlow -Environment $Environment -Connection $Connection
if ($IncludeSharedWithMe) {
$Flows += Get-PnPFlow -Environment $Environment -SharingStatus SharedWithMe -Connection $Connection
}
if (-not $Flows) {
Write-Host "Keine Flows gefunden." -ForegroundColor Yellow
continue
}
$FlowRows = foreach ($Flow in $Flows) {
[PSCustomObject]@{
DisplayName = Get-DisplayName $Flow
Name = $Flow.Name
Object = $Flow
}
}
$SelectedFlows = $FlowRows |
Sort-Object DisplayName |
Out-GridView -PassThru -Title "Flows aus '$($EnvRow.DisplayName)' auswaehlen"
if (-not $SelectedFlows) {
Write-Host "Keine Flows ausgewaehlt." -ForegroundColor Yellow
continue
}
$EnvironmentFolder = Join-Path $ExportFolder (Get-SafeFileName $EnvRow.DisplayName)
New-Item -Path $EnvironmentFolder -ItemType Directory -Force | Out-Null
foreach ($FlowRow in $SelectedFlows) {
$TargetFile = Join-Path $EnvironmentFolder "$(Get-SafeFileName $FlowRow.DisplayName)_$($FlowRow.Name).zip"
Write-Host "Exportiere: $($FlowRow.DisplayName)" -ForegroundColor Green
try {
Export-PnPFlow -Environment $Environment -Identity $FlowRow.Object -AsZipPackage `
-OutPath $TargetFile -Force -Connection $Connection
Write-Host " OK: $TargetFile" -ForegroundColor Green
}
catch {
Write-Host " FEHLER: $($_.Exception.Message)" -ForegroundColor Red
}
}
}
Write-Host ""
Write-Host "Fertig. Export unter: $ExportFolder" -ForegroundColor Green
Nutzung
ClientId(und ggf.TenantUrl) imparam-Block auf die eigene App-Registrierung anpassen.- Skript in PowerShell 7 starten.
- Im ersten Auswahlfenster die Environment(s) markieren, im zweiten die Flows.
- Die ZIP-Pakete landen unter
%USERPROFILE%\\Downloads\\PowerAutomateFlowExport\\<Environment>\\.
Mit -IncludeSharedWithMe werden auch geteilte Flows mit angeboten.

von