Saturday 29 September 2018

SSRS Snack: Download all SSRS reports

Case
I want to download all my SSRS reports (and data sources) from my Reporting server, but not manually. Is there a solution?
My Reporting Server













Solution
The easiest way to do this is with some PowerShell scripting and the SSRS webservice. The following PowerShell script recreates the SSRS folder structure on a local drive and downloads all reports (*.rdl) and all data sources (*.rds) to the corresponding folders.

Note 1: you need full access if you want to download everything
Note 2: empty folders are not recreated locally
Note 3: It only works for SSRS 2012 and higher (webservice differs for older versions)


1) PowerShell ISE
Open PowerShell ISE and copy and paste the code below. Determine the local folder (line 7) and provide the URL of the Reporting server on line 8 (without "/reports"). For this example the SSRS server is located on a Virtual Machine in Azure.

###################################################################################
# Download Reports and DataSources from a SSRS server and create the same folder
# structure in the local download folder.
###################################################################################
# Parameters
###################################################################################
$downloadFolder = "c:\temp\ssrs\"
$ssrsServer = "http://myssrs.westeurope.cloudapp.azure.com"
###################################################################################
# If you can't use integrated security
#$secpasswd = ConvertTo-SecureString "MyPassword!" -AsPlainText -Force
#$mycreds = New-Object System.Management.Automation.PSCredential ("MyUser", $secpasswd)
#$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)/ReportServer/ReportService2010.asmx?WSDL" -Credential $mycreds

# SSRS Webserver call
$ssrsProxy = New-WebServiceProxy -Uri "$($ssrsServer)/ReportServer/ReportService2010.asmx?WSDL" -UseDefaultCredential

# List everything on the Report Server, recursively, but filter to keep Reports and DataSources
$ssrsItems = $ssrsProxy.ListChildren("/", $true) | Where-Object {$_.TypeName -eq "DataSource" -or $_.TypeName -eq "Report"}

# Loop through reports and data sources
Foreach($ssrsItem in $ssrsItems)
{
    # Determine extension for Reports and DataSources
    if ($ssrsItem.TypeName -eq "Report")
    {
        $extension = ".rdl"
    }
    else
    {
        $extension = ".rds"
    }
    
    # Write path to screen for debug purposes
    Write-Host "Downloading $($ssrsItem.Path)$($extension)";

    # Create download folder if it doesn't exist (concatenate: "c:\temp\ssrs\" and "/SSRSFolder/")
    $downloadFolderSub = $downloadFolder.Trim('\') + $ssrsItem.Path.Replace($ssrsItem.Name,"").Replace("/","\").Trim() 
    New-Item -ItemType Directory -Path $downloadFolderSub -Force > $null

    # Get SSRS file bytes in a variable
    $ssrsFile = New-Object System.Xml.XmlDocument
    [byte[]] $ssrsDefinition = $null
    $ssrsDefinition = $ssrsProxy.GetItemDefinition($ssrsItem.Path)

    # Download the actual bytes
    [System.IO.MemoryStream] $memoryStream = New-Object System.IO.MemoryStream(@(,$ssrsDefinition))
    $ssrsFile.Load($memoryStream)
    $fullDataSourceFileName = $downloadFolderSub + "\" + $ssrsItem.Name +  $extension;
    $ssrsFile.Save($fullDataSourceFileName);
}

There is also code (comment out) to provide a username and password in case you cannot use integrated security. Replace line 16 with the code on lines 11 to 13 and provide the username and password.

2) Result
Running the script in PowerShell ISE downloads all reports and data sources.
Downloading all reports

Summary
This is a 'quick & dirty' script to download all SSRS reports at once. You can adjust the script to you own needs and make it more beautiful. A upload(/deploy) script will be provided in a next blog post.













13 comments:

  1. Great Script, helps alot. Are you publishing Upload Script soon?

    ReplyDelete
  2. Hello!
    Thanks for the blog post.
    I get the below error:

    At line:8 char:26
    + ... "http://myssrs.westeurope.cloudapp.azure.com"' in expression or statement.
    + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedToken


    Pls note: I replaced class with claxxx and span with spin as I could not paste it on this blog with getting an error, "Your HTML cannot be accepted: Tag is not allowed: SPAN"
    "Your HTML cannot be accepted: Tag is not allowed: CLASS"

    How do I resolve this error, please?
    Looking foward to hearing from you

    ReplyDelete
  3. It works.. Thanks a lot... You save my time greatly.....

    ReplyDelete
  4. I hate to be one of those "it doesn't work for me" posts. But here I am.

    Our SSRS deployment requires our front end to have the Authentication Type enabled. An I had hope with this script since it contains the calls necessary to pass credentials. Which does work by the way. I am able to log in. However, I get this error message:

    Exception calling "ListChildren" with "2" argument(s): "The request failed with an empty response."

    Which according to a search, I believe that it is stating that there are no reports or folders to export. Which of course is not the case, there are ~100 reports in ~20 folders, with sub folders and subreports and nearly as many data sources.

    Any ideas are appreciated.

    ReplyDelete
  5. Muchas Gracias, fue de mucha utilidad

    ReplyDelete
  6. Worked like a charm for SSRS 2016. Just replace the URL at the top.

    ReplyDelete
  7. hi the site is not opening in my google chrome and MS edge also.....pls check the URL

    ReplyDelete
  8. That worked like a gem for SSRS 2012!

    ReplyDelete
  9. Muchas gracias funciono excelente.

    ReplyDelete
  10. does the script work for Power Bi reports ? . And, if not, What in the Code should i change

    ReplyDelete
    Replies
    1. I haven’t tested it within Power BI, but I don’t think it will work. I would try the Rest API approach https://docs.microsoft.com/en-us/rest/api/power-bi/reports/get-reports

      Delete
  11. Hi,
    Don't know if you fixed this but i had the same error and got round it by specifying each folder in the following line
    $ssrsItems = $ssrsProxy.ListChildren("/foldername", $true) | Where-Object {$_.TypeName -eq "DataSource" -or $_.TypeName -eq "Report"}

    it may be not having access to one report, but didn't find one when doing one folder at a time!

    ReplyDelete

All comments will be verified first to avoid URL spammers. यूआरएल स्पैमर से बचने के लिए सभी टिप्पणियों को पहले सत्यापित किया जाएगा।