-
-
Save EitanBlumin/e3b34d4c2de793054854e0e3d43f4349 to your computer and use it in GitHub Desktop.
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 | |
} |
Thank you for the note, @kadiyala82 .
I updated the script to its latest version, and also added the Recursive
parameter.
Can you check if it works for you?
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
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.
Hello Eithan,
looks like your script only used for single folder content to upload SSRS URL. But I am looking for recursive folders and those folder having reports and that needs to create recursive folder hirarchy and upload their hirarchy folder content into the SSRS URL.
I am using below Powershell script but I am getting errors. Can you please correct me or please edit the below script to upload all the recursive hirarchy folder content.
Import-Module ReportingServicesTools
$SubFolderParentPath = '/' + ((Split-Path -Parent $ ) -replace '\', '/')
$ReportPath = 'X:\SSRS_Reports_staging'
$Folders = Get-ChildItem $ReportPath -Recurse -Directory
$ReportServerURI = 'http://myreportserver/Reportserver/ReportService2010.asmx?wsdl'
Get-ChildItem $ReportPath -Recurse -Directory -Name | ForEach-Object {
# Split the relative input path into leaf (directory name)
# and parent path, and convert the parent path to the target parent path
# by prepending "/" and converting path-internal "" instances to "/".
$SubFolderName = Split-Path -Leaf $
try{
New-RsFolder -ReportServerUri $ReportServerURI -Path $SubFolderParentPath -FolderName $SubFolderName
Write-Host "Created folder ${SubFolderParentPath}/${SubFoldeNamer}"
Write-RsFolderContent -ReportServerUri $ReportServerURI -Path $SubFolderParentPath -RsFolder $SubFolderName -Verbose
}
catch {
# Report the specific error that occurred, accessible via $_
Write-Host "An error occurred for ${SubFolderParentPath}/${SubFolderName}: $_"
}
}
Errors:
VERBOSE: Establishing proxy connection to http://myreportserver/Reportserver/ReportServ
ice2010.asmx...
An error occurred for /DATAMGMT_STAGING/WIZMO: /DATAMGMT_STAGING is not a folder
Created folder /DATAMGMT_STAGING/APC/CORPHOME
VERBOSE: Performing the operation "Upload all contents in folder to CORPHOME" on t
arget "/DATAMGMT_STAGING/APC".
VERBOSE: Establishing proxy connection to http://myreportserver/Reportserver/ReportServ
ice2010.asmx...
An error occurred for /DATAMGMT_STAGING/APC/CORPHOME: /DATAMGMT_STAGING/APC is not
a folder