Invoke-sqmSsrsMigration
This command moves one or more report folders (a "report project") between two report servers, or to a different folder on the same server, and reports every item and every step. It works through the SSRS REST API v2.0 (SSRS 2017 and later, Power BI Report Server), so it runs the same under Windows PowerShell 5.1 and PowerShell 7. Nothing on the source is changed.
Bindings come from the source catalog, not from the RDL text. After uploading, the data sources of every report and shared dataset are set again from what the source server actually uses, with paths mapped to the destination, connection strings rewritten by
-ConnectionStringMap and stored passwords supplied by -DataSourceCredential. Afterwards the bindings are read back from the destination and compared.
Dependencies outside the project are found and taken along. Shared data sources and datasets under
/Data Sources or /Datasets that the migrated reports reference are copied to the same path on the destination; references that already point nowhere on the source are reported.
Parameters
| Parameter | Type | Required | Default | Notes |
|---|---|---|---|---|
| -SourceReportServer | string | Required | — | Source server. Accepts SRV, https://srv:8443, http://srv/ReportServer, http://srv/Reports, http://srv/ReportServer_INST or the full .../api/v2.0 URL for custom virtual directories. |
| -SourceCredential | PSCredential | Optional | current user | Windows credential for the source (NTLM/Kerberos). |
| -DestinationReportServer | string | Required | — | Destination server, same forms. May be the source server when -DestinationFolder differs. |
| -DestinationCredential | PSCredential | Optional | current user | Windows credential for the destination. |
| -SourceFolder | string[] | Optional | / | Folder(s) to migrate, recursively. |
| -DestinationFolder | string | Optional | same path | Path that replaces -SourceFolder, e.g. /Finance → /Archive/Finance. Only with a single source folder. Absolute references inside RDL/RSD content follow the move. |
| -ItemType | string[] | Optional | all | DataSource, DataSet, Report, LinkedReport, Resource, PowerBIReport, ExcelWorkbook. Folders are always created as needed. |
| -ConnectionStringMap | string[] | Optional | — | Replacements as 'OLD=>NEW', case-insensitive, for shared and embedded data sources. |
| -DataSourceCredential | PSCredential[] | Optional | — | Passwords for data sources with stored credentials, matched by the stored user name (DOM\user also matches user). Missing passwords are listed in the plan. |
| -Overwrite | switch | Switch | $false | Overwrite existing reports, datasets, resources and linked reports. The item keeps its ID, so destination subscriptions and history stay attached. Each overwritten item is backed up first. |
| -OverwriteDataSources | switch | Switch | $false | Also overwrite existing shared data sources. Separate on purpose: an existing data source on the destination usually carries the right connection and password for that environment. |
| -IncludeSecurity | switch | Switch | $false | Copy role assignments of every folder and item that breaks inheritance. Users, groups and role names must exist on the destination. |
| -SkipDependencies | switch | Switch | $false | Do not take along referenced data sources/datasets outside the source folders. |
| -SkipCertificateCheck | switch | Switch | $false | Accept untrusted HTTPS certificates. |
| -AssessOnly | switch | Switch | $false | Inventory and plan only. Changes nothing on the destination. |
| -OutputPath | string | Optional | <config>\SsrsMigration | HTML report, source export (Source\) and backup of overwritten items (DestinationBackup\). |
| -NoOpen / -NoReport | switch | Switch | $false | Do not open the report / do not write one (the export is still written). |
| -EnableException | switch | Switch | $false | Throw immediately instead of returning a result object with Status 'Failed'. |
-WhatIf and -Confirm (ConfirmImpact High). A -WhatIf run builds the complete plan, returns it in .Items and writes nothing.Execution Flow
Examples
Invoke-sqmSsrsMigration -SourceReportServer SSRSOLD -DestinationReportServer SSRSNEW -SourceFolder '/Finance' -AssessOnly
$cred = Get-Credential rpt_reader
Invoke-sqmSsrsMigration -SourceReportServer SSRSOLD -DestinationReportServer SSRSNEW `
-SourceFolder '/Finance' -ConnectionStringMap 'SQLOLD01=>SQLNEW01' `
-DataSourceCredential $cred -IncludeSecurity -Confirm:$false
Invoke-sqmSsrsMigration -SourceReportServer SSRS01 -DestinationReportServer SSRS01 `
-SourceFolder '/Finance' -DestinationFolder '/Test/Finance' -Overwrite
$r = Invoke-sqmSsrsMigration -SourceReportServer SSRSOLD -DestinationReportServer SSRSNEW `
-SourceFolder '/Finance' -Overwrite -DataSourceCredential $cred -Confirm:$false
$r.Items | Format-Table Type, DestinationPath, Action, Status, Detail -AutoSize
(Invoke-sqmSsrsMigration -SourceReportServer SSRSOLD -DestinationReportServer SSRSNEW -SourceFolder '/Finance' -AssessOnly).Subscriptions |
Format-Table Report, Description, Owner, DeliveryExtension, IsDataDriven
Notes
What this does not do. Subscriptions are listed, not copied: they carry the owner, schedule and delivery settings of the old server and have to be recreated deliberately. Also not migrated: cache, history and snapshot settings, shared schedules, report parameters changed on the server, KPIs and mobile reports.
API quirks handled, measured against SSRS 2022. A shared data source created without IsConnectionStringOverridden = true is accepted (HTTP 201) but stored with an empty connection string. CredentialRetrieval is only accepted in lower case (store; Store returns HTTP 400). Linked reports can only be created through /LinkedReports, where Path is the parent folder, while every other item type expects the full path.
PowerShell 7 and plain http. PowerShell 7 refuses Windows authentication over http:// unless -AllowUnencryptedAuthentication is set, even though NTLM/Kerberos never sends a clear-text password. Many internal report servers run without TLS, so the command sets it under PowerShell 7 for http URLs; Windows PowerShell 5.1 does not need it.