In many projects, an installation script or package is required, which performs the upgrade of the server part of the application. The need, first of all, is due to the lack of direct access to the production server by the developers.
The installer in the form of a script is best suited for installation without explicitly logging into the server (RDP). The script can also be executed as a single loader, which will do the rest. In current projects, we implemented something like PsGet
[1] , only for the internal build server.
The application is large and consists of a number of components, one of which is the reporting module, built on the basis of
SSRS .
To manage the reporting server, Microsoft provided the ReportingService2005.asmx web service to developers
[2] .
Presets
Initial installation and configuration of the reporting server is not the responsibility of the developers and is performed by teams with a certain responsibility. Also, we do not create Data Sources, because they may contain sensitive information (such as passwords to connect).
As a result, the above settings, as well as the distribution of access, are not necessary for the script. It remains only to add and update the reports themselves.
Connect to the service
PowerShell 2.0 provides the ability to create a proxy for working with a web service via the New-WebServiceProxy command
[3] .
It is enough to specify the path to the description of the service on
WSDL [4] . We use Windows Authentication, so in the connection we specify the key UseDefaultCredential. In the proxy service itself, you must also specify the authentication method.
function Connect-ReportingService([string]$ssrsHost) { $reportingServiceUrl = $ssrsHost + "ReportService2005.asmx?wsdl" $reportingService= New-WebServiceProxy $reportingServiceUrl -UseDefaultCredential -namespace ReportingWebService $reportingService.UseDefaultCredentials = $true $reportingService }
The $ ssrsHost parameter contains the full path to which our service is configured (usually,
servername / ReportServer ).
')
Add report
In order to create or update a report, there is a method CreateReport
[5] .
As parameters, it takes the report name, the parent folder name (folders allow you to group reports and set various security policies to them), the need to overwrite flag, the binary content of the report file and additional properties (usually not used, you can pass $ null).
The method returns a collection of error and warning messages.
Of these, we will ignore messages about Data Sources.
The call will look like:
(Connect-ReportingService $ssrsHost).CreateReport($report, $ssrsFolder, $true, $reportBits, $null)
Thus, adding a report can be wrapped in a function:
function Deploy-Report([string]$ssrsHost, [string]$reportDir, [string]$report, [string]$ssrsFolder) { <# , ( ) #> $relativeReportLocation = "..\RS\$($report).rdl" # if (-not (Test-Path $reportFile)) { $message = "Report file '{0}' was not found!" -f $reportFile Write-Warning $message return } # [byte[]]$reportBits = [System.IO.File]::ReadAllBytes($reportFile) # , $warnings = (Connect-ReportingService $ssrsHost).CreateReport($report, $ssrsFolder, $true, $reportBits, $null) # "" $cleanedWarnings = $warnings | ? { -not $_.Message.Contains("data source") } # ( ) if(!$cleanedWarnings) { $result = "Report '{0}' published successfully with no warnings" -f $report Write-Host $result Write-Host "" } else { $warningHeader = "Report '{0}' published with warnings: " -f $report Write-Host $warningHeader $cleanedWarnings | % { Write-Warning $_.Message } Write-Host "" } }
findings
The presented implementation solves the problem of adding and updating a single report and can be used in such code:
ls "..\RS\*.rdl") | % { $_.Name.Replace(".rdl", "") } | % { Deploy-Report $ssrsHost $reportDir $report $ssrsFolder }
Calling web services through PowerShell is a trivial task.
The web service itself for SSRS provides much more possibilities, for example, adding / changing Data Source by means of the CreateDataSource method
[6] .
Extensions that can be made
In the current project we have implemented a bulk extension module.
So, reports can also be updated by condition, for example, based on the time of the last modification of files
[7] :
# () $deployedReports = (Connect-ReportingService $config).ListChildren($ssrsFolder, 1) [hashtable]$deployedReportsMap = @{} $deployedReports | % { $deployedReportsMap[$_.Name + '.rdl'] = $_ } ls ) ` | ? { ( -not $deployedReportsMap.ContainsKey($_.Name)) -or $deployedReportsMap[$_.Name].ModifiedDate -lt $_.LastWriteTime } ` | % { $_.Name.Replace(, ) } ` | % { Deploy-Report $ssrsHost $reportDir $report $ssrsFolder }
Sometimes it is necessary to update the Data Source of the report, for which the SetItemDataSources method is used.
Often it is required to flush the cache of the report (FlushCache method).
In general, everything is simple and expandable.
- psget.net
- msdn.microsoft.com/en-us/library/reportservice2005.reportingservice2005.aspx
- technet.microsoft.com/en-us/library/dd315258.aspx
- www.w3.org/TR/wsdl
- msdn.microsoft.com/en-us/library/reportservice2005.reportingservice2005.createreport.aspx
- msdn.microsoft.com/en-us/library/reportservice2005.reportingservice2005.createdatasource.aspx
- ListChildren method: msdn.microsoft.com/en-us/library/reportservice2005.reportingservice2005.listchildren.aspx