Skip to content

Instantly share code, notes, and snippets.

@EitanBlumin
Last active August 28, 2024 05:58
Show Gist options
  • Save EitanBlumin/e3b34d4c2de793054854e0e3d43f4349 to your computer and use it in GitHub Desktop.
Save EitanBlumin/e3b34d4c2de793054854e0e3d43f4349 to your computer and use it in GitHub Desktop.
Powershell script to deploy SSRS reports from a folder (all rds and rdl files)
Param
(
[string] $SourceFolder = "C:\SSRS\My-Reports",
[string] $TargetReportServerUri = "http://localhost:8081/ReportServer",
[PSCredential] $Credential,
[switch] $CustomAuthentication,
[string] $ApiVersion,
[string] $TargetFolder = "/My-Reports/Sample-Reports",
[switch] $Recursive,
[string] $OverrideDataSourcePathForAll, #= "/My-Reports/Data Sources/ProdDS",
[string] $logFileFolderPath = "C:\SSRS_deployment_log",
[string] $logFilePrefix = "ssrs_deploy_",
[string] $logFileDateFormat = "yyyyMMdd_HHmmss",
[int] $logFileRetentionDays = 30
)
Process {
#region initialization
function Get-TimeStamp {
Param(
[switch]$NoWrap,
[switch]$Utc
)
$dt = Get-Date
if ($Utc -eq $true) {
$dt = $dt.ToUniversalTime()
}
$str = "{0:MM/dd/yy} {0:HH:mm:ss}" -f $dt
if ($NoWrap -ne $true) {
$str = "[$str]"
}
return $str
}
if ($logFileFolderPath -ne "")
{
if (!(Test-Path -PathType Container -Path $logFileFolderPath)) {
Write-Output "$(Get-TimeStamp) Creating directory $logFileFolderPath" | Out-Null
New-Item -ItemType Directory -Force -Path $logFileFolderPath | Out-Null
} else {
$DatetoDelete = $(Get-Date).AddDays(-$logFileRetentionDays)
Get-ChildItem $logFileFolderPath | Where-Object { $_.Name -like "*$logFilePrefix*" -and $_.LastWriteTime -lt $DatetoDelete } | Remove-Item | Out-Null
}
$logFilePath = $logFileFolderPath + "\$logFilePrefix" + (Get-Date -Format $logFileDateFormat) + ".LOG"
# attempt to start the transcript log, but don't fail the script if unsuccessful:
try
{
Start-Transcript -Path $logFilePath -Append
}
catch [Exception]
{
Write-Warning "$(Get-TimeStamp) Unable to start Transcript: $($_.Exception.Message)"
$logFileFolderPath = ""
}
}
#endregion initialization
#region install-modules
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
if (Get-PSRepository -Name "PSGallery") {
Write-Verbose "$(Get-TimeStamp) PSGallery already registered"
}
else {
Write-Information "$(Get-TimeStamp) Registering PSGallery"
Register-PSRepository -Default
}
if (Get-Module -ListAvailable -Name PowerShellGet) {
Write-Verbose "$(Get-TimeStamp) PowerShellGet already installed"
}
else {
Write-Information "$(Get-TimeStamp) Installing PowerShellGet"
Install-Module PowerShellGet -RequiredVersion 2.2.4 -Force -SkipPublisherCheck -Scope CurrentUser -ErrorAction Stop -AllowClobber | Out-Null
Import-Module PowerShellGet -Force -Scope Local | Out-Null
}
if ((Get-PSRepository -Name "PSGallery").Trusted) {
Write-Verbose "$(Get-TimeStamp) PSGallery already Trusted"
} else {
Write-Information "$(Get-TimeStamp) Marking PSGallery as Trusted..."
Set-PSRepository -Name "PSGallery" -InstallationPolicy Trusted
}
# replace the array below with any modules that your script depends on.
# you can remove this region if your script doesn't need importing any modules.
$modules = @("ReportingServicesTools")
foreach ($module in $modules) {
if (Get-Module -ListAvailable -Name $module) {
Write-Verbose "$(Get-TimeStamp) $module already installed"
}
else {
Write-Information "$(Get-TimeStamp) Installing $module"
Install-Module $module -Force -SkipPublisherCheck -Scope CurrentUser -ErrorAction Stop | Out-Null
Import-Module $module -Force -Scope Local | Out-Null
}
}
#Write-Output "Requesting RSTools..."
#Invoke-Expression (Invoke-WebRequest https://aka.ms/rstools)
#endregion install-modules
#region main
$ErrorActionPreference = "Stop"
if ($SourceFolder -eq "" -or $SourceFolder -eq $null) {
$SourceFolder = $(Get-Location).Path + "\"
}
if ($TargetFolder -eq "" -or $TargetFolder -eq $null) {
$TargetFolder = "/"
}
if (!$SourceFolder.EndsWith("\"))
{
$SourceFolder = $SourceFolder + "\"
}
Write-Output "====================================================================================="
Write-Output " Deploying SSRS Reports"
Write-Output "Target Server: $TargetReportServerUri"
$ProxyParams = @{
ReportServerUri = $TargetReportServerUri
CustomAuthentication = $CustomAuthentication
}
if ($Credential -ne $null) {
Write-Output "Username: $($Credential.UserName)"
$ProxyParams.Credential = $Credential
}
if ($ApiVersion -ne $null) {
Write-Output "ApiVersion: $ApiVersion"
$ProxyParams.ApiVersion = $ApiVersion
}
Write-Output "====================================================================================="
$Proxy = New-RsWebServiceProxy @ProxyParams
$SourceFoldersList = @()
$SourceFoldersList += $SourceFolder
if ($Recursive) {
Get-ChildItem -Recurse -Directory -Path $SourceFolder | ForEach-Object {
$SourceFoldersList += $_.FullName
}
}
$SourceFoldersList | ForEach-Object {
$currSourceFolder = $_
if (!$currSourceFolder.EndsWith("\"))
{
$currSourceFolder = $currSourceFolder + "\"
}
if ($currSourceFolder -ne $SourceFolder) {
$currTargetFolder = $TargetFolder + "/" + [Regex]::Replace($currSourceFolder,$SourceFolder.Replace('\','\\'),'').Replace('\','/')
} else {
$currTargetFolder = $TargetFolder
}
Write-Output "====================================================================================="
Write-Output "Source Folder: $currSourceFolder"
Write-Output "Target Folder: $currTargetFolder"
Write-Output "=============="
if ($currTargetFolder -ne "/") {
if ($currTargetFolder.StartsWith("/")) {
$currTargetFolder = $currTargetFolder.Remove(0,1)
}
Write-Output "$(Get-TimeStamp) Creating Folder: $currTargetFolder"
New-RsFolder -Proxy $Proxy -Path / -Name $currTargetFolder -Verbose -ErrorAction SilentlyContinue
}
if (!$currTargetFolder.StartsWith("/")) {
$currTargetFolder = $currTargetFolder.Insert(0, "/")
}
Write-Output "$(Get-TimeStamp) Deploying Data Source files from: $currSourceFolder"
DIR $currSourceFolder -Filter *.rds | % { $_.FullName } | Write-RsCatalogItem -Proxy $Proxy -Destination $currTargetFolder -Verbose -Overwrite
Write-Output "$(Get-TimeStamp) Deploying Data Set files from: $currSourceFolder"
DIR $currSourceFolder -Filter *.rsd | % { $_.FullName } | Write-RsCatalogItem -Proxy $Proxy -Destination $currTargetFolder -Verbose -Overwrite
Write-Output "$(Get-TimeStamp) Deploying Report Definition files from: $currSourceFolder"
DIR $currSourceFolder -Filter *.rdl | % { $_.FullName } | Write-RsCatalogItem -Proxy $Proxy -Destination $currTargetFolder -Verbose -Overwrite
if ($OverrideDataSourcePathForAll -ne $null -and $OverrideDataSourcePathForAll -ne "") {
Write-Output "$(Get-TimeStamp) Fixing Data Source references to: $OverrideDataSourcePathForAll"
Get-RsFolderContent -Proxy $Proxy -RsFolder $currTargetFolder | ForEach {
$CurrReport = $_
Get-RsItemReference -Proxy $Proxy -Path $CurrReport.Path | Where ReferenceType -eq "DataSource" | ForEach {
$CurrReference = $_
if ($CurrReference.Reference -ne $OverrideDataSourcePathForAll) {
Write-Output "$(Get-TimeStamp) UPDATING: Data Source $($CurrReference.Name) in report $($CurrReport.Path)"
Set-RsDataSourceReference -Proxy $Proxy -Path $CurrReport.Path -DataSourceName $CurrReference.Name -DataSourcePath $OverrideDataSourcePathForAll
} else {
Write-Output "$(Get-TimeStamp) Data Source $($CurrReference.Name) in report $($CurrReport.Path) already set correctly."
}
}
}
}
}
#endregion main
#region finalization
if ($logFileFolderPath -ne "") { Stop-Transcript }
#endregion finalization
}
@kadiyala82
Copy link

kadiyala82 commented Aug 22, 2024

Hello EItanBlumin

First of all thanks for replying. I just used the updated script, but I got below error.

                         Deploying SSRS Reports

Target Server:
ApiVersion:

PS>TerminatingError(New-RsWebServiceProxy): "Cannot validate argument on parameter 'ApiVersion'. The argument "" does not belong to the set "2005,2006,2010" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again."

TerminatingError(New-RsWebServiceProxy): "Cannot validate argument on parameter 'ApiVersion'. The argument "" does not belong to the set "2005,2006,2010" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again."
New-RsWebServiceProxy : Cannot validate argument on parameter 'ApiVersion'. The argument "" does not belong to
the set "2005,2006,2010" specified by the ValidateSet attribute. Supply an argument that is in the set and
then try the command again.
At X:\Deploy SSRS Reports.ps1:149 char:32

  • $Proxy = New-RsWebServiceProxy @ProxyParams
  •                            ~~~~~~~~~~~~
    
    • CategoryInfo : InvalidData: (:) [New-RsWebServiceProxy], ParentContainsErrorRecordException
    • FullyQualifiedErrorId : ParameterArgumentValidationError,New-RsWebServiceProxy

@EitanBlumin
Copy link
Author

Hi @kadiyala82 .

Based on your error, it looks like you specified an empty string for the ApiVersion parameter.
It should be $null or unspecified instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment