Skip to content

Instantly share code, notes, and snippets.

@Jonesie
Forked from ChrisMissal/Deploy-SSRSProject.ps1
Last active February 25, 2019 18:34
Show Gist options
  • Save Jonesie/9005796 to your computer and use it in GitHub Desktop.
Save Jonesie/9005796 to your computer and use it in GitHub Desktop.
#requires -version 2.0
[CmdletBinding()]
param (
[parameter(Mandatory=$true)]
[ValidatePattern('\.rptproj$')]
[ValidateScript({ Test-Path -PathType Leaf -Path $_ })]
[string]
$Path,
[parameter(
ParameterSetName='Configuration',
Mandatory=$true)]
[string]
$Configuration,
[parameter(
ParameterSetName='Target',
Mandatory=$true)]
[ValidatePattern('^https?://')]
[string]
$ServerUrl,
[parameter(
ParameterSetName='Target',
Mandatory=$true)]
[string]
$Folder,
[parameter(
ParameterSetName='Target',
Mandatory=$true)]
[string]
$DataSourceFolder,
[parameter(
ParameterSetName='Target',
Mandatory=$true)]
[string]
$DataSetFolder,
[parameter(ParameterSetName='Target')]
[switch]
$OverwriteDataSources,
[System.Management.Automation.PSCredential]
$Credential
)
function New-XmlNamespaceManager ($XmlDocument, $DefaultNamespacePrefix) {
$NsMgr = New-Object -TypeName System.Xml.XmlNamespaceManager -ArgumentList $XmlDocument.NameTable
$DefaultNamespace = $XmlDocument.DocumentElement.GetAttribute('xmlns')
if ($DefaultNamespace -and $DefaultNamespacePrefix) {
$NsMgr.AddNamespace($DefaultNamespacePrefix, $DefaultNamespace)
}
return ,$NsMgr # unary comma wraps $NsMgr so it isn't unrolled
}
function Normalize-SSRSFolder (
[string]$Folder
) {
if (-not $Folder.StartsWith('/')) {
$Folder = '/' + $Folder
}
return $Folder
}
function New-SSRSFolder (
$Proxy,
[string]
$Name
) {
Write-Verbose "New-SSRSFolder -Name $Name"
$Name = Normalize-SSRSFolder -Folder $Name
if ($Proxy.GetItemType($Name) -ne 'Folder') {
$Parts = $Name -split '/'
$Leaf = $Parts[-1]
$Parent = $Parts[0..($Parts.Length-2)] -join '/'
if ($Parent) {
New-SSRSFolder -Proxy $Proxy -Name $Parent
} else {
$Parent = '/'
}
$Proxy.CreateFolder($Leaf, $Parent, $null)
}
}
function New-SSRSDataSource (
$Proxy,
[string]$RdsPath,
[string]$Folder,
[switch]$Overwrite
) {
Write-Verbose "New-SSRSDataSource -RdsPath $RdsPath -Folder $Folder"
$Folder = Normalize-SSRSFolder -Folder $Folder
[xml]$Rds = Get-Content -Path $RdsPath
$ConnProps = $Rds.RptDataSource.ConnectionProperties
$Definition = New-Object -TypeName SSRS.ReportingService2010.DataSourceDefinition
$Definition.ConnectString = $ConnProps.ConnectString
$Definition.Extension = $ConnProps.Extension
if ([Convert]::ToBoolean($ConnProps.IntegratedSecurity)) {
$Definition.CredentialRetrieval = 'Integrated'
}
$DataSource = New-Object -TypeName PSObject -Property @{
Name = $Rds.RptDataSource.Name
Path = $Folder + '/' + $Rds.RptDataSource.Name
}
if ($Overwrite -or $Proxy.GetItemType($DataSource.Path) -eq 'Unknown') {
$Proxy.CreateDataSource($DataSource.Name, $Folder, $Overwrite, $Definition, $null)
}
return $DataSource
}
function New-SSRSDataSet (
$Proxy,
[string]$RsdPath,
[string]$Folder,
[switch]$Overwrite,
$DataSourcePaths
) {
Write-Verbose "New-SSRSDataSet -RsdPath $RsdPath -Folder $Folder"
$Folder = Normalize-SSRSFolder -Folder $Folder
$Name = [System.IO.Path]::GetFileNameWithoutExtension($RsdPath)
$RawDefinition = Get-Content -Encoding Byte -Path $RsdPath
$warnings = $null
$Results = $Proxy.CreateCatalogItem("DataSet", $Name, $Folder, $true, $RawDefinition, $null, [ref]$warnings)
[xml]$Rsd = Get-Content -Path $RsdPath
$DataSourcePath = $DataSourcePaths[$Rsd.SharedDataSet.DataSet.Query.DataSourceReference]
if ($DataSourcePath) {
$Reference = New-Object -TypeName SSRS.ReportingService2010.ItemReference
$Reference.Reference = $DataSourcePath
$Reference.Name = 'DataSetDataSource' #$Rsd.SharedDataSet.DataSet.Name
$Proxy.SetItemReferences($Folder + '/' + $Name, @($Reference))
}
return $Results
}
$script:ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
$PSScriptRoot = $MyInvocation.MyCommand.Path | Split-Path
$Path = $Path | Convert-Path
$ProjectRoot = $Path | Split-Path
[xml]$Project = Get-Content -Path $Path
if ($PSCmdlet.ParameterSetName -eq 'Configuration') {
$Config = & $PSScriptRoot\Get-SSRSProjectConfiguration.ps1 -Path $Path -Configuration $Configuration
$ServerUrl = $Config.ServerUrl
$Folder = $Config.Folder
$DataSourceFolder = $Config.DataSourceFolder
$DataSetFolder = $Config.DataSetFolder
$OverwriteDataSources = $Config.OverwriteDataSources
}
$Folder = Normalize-SSRSFolder -Folder $Folder
$DataSourceFolder = Normalize-SSRSFolder -Folder $DataSourceFolder
$Proxy = & $PSScriptRoot\New-SSRSWebServiceProxy.ps1 -Uri $ServerUrl -Credential $Credential
New-SSRSFolder -Proxy $Proxy -Name $Folder
New-SSRSFolder -Proxy $Proxy -Name $DataSourceFolder
New-SSRSFolder -Proxy $Proxy -Name $DataSetFolder
$DataSourcePaths = @{}
$Project.SelectNodes('Project/DataSources/ProjectItem') |
ForEach-Object {
$RdsPath = $ProjectRoot | Join-Path -ChildPath $_.FullPath
$DataSource = New-SSRSDataSource -Proxy $Proxy -RdsPath $RdsPath -Folder $DataSourceFolder
$DataSourcePaths.Add($DataSource.Name, $DataSource.Path)
}
$DataSetPaths = @{}
$Project.SelectNodes('Project/DataSets/ProjectItem') |
ForEach-Object {
$RsdPath = $ProjectRoot | Join-Path -ChildPath $_.FullPath
$DataSet = New-SSRSDataSet -Proxy $Proxy -RsdPath $RsdPath -Folder $DataSetFolder -DataSourcePaths $DataSourcePaths
if(-not $DataSetPaths.Contains($DataSet.Name))
{
$DataSetPaths.Add($DataSet.Name, $DataSet.Path)
}
}
$Project.SelectNodes('Project/Reports/ResourceProjectItem') |
ForEach-Object {
if($_.MimeType.StartsWith('image/'))
{
$Path = $ProjectRoot | Join-Path -ChildPath $_.FullPath
$RawDefinition = Get-Content -Encoding Byte -Path $Path
$DescProp = New-Object -TypeName SSRS.ReportingService2010.Property
$DescProp.Name = 'Description'
$DescProp.Value = ''
$HiddenProp = New-Object -TypeName SSRS.ReportingService2010.Property
$HiddenProp.Name = 'Hidden'
$HiddenProp.Value = 'false'
$MimeProp = New-Object -TypeName SSRS.ReportingService2010.Property
$MimeProp.Name = 'MimeType'
$MimeProp.Value = $_.MimeType
$Properties = @($DescProp, $HiddenProp, $MimeProp)
if($_.FullPath.StartsWith('_'))
{
$HiddenProp.Value = 'true'
}
$Name = $_.FullPath
Write-Verbose "Creating resource $Name"
$warnings = $null
$Results = $Proxy.CreateCatalogItem("Resource", $_.FullPath, $Folder, $true, $RawDefinition, $Properties, [ref]$warnings)
}
}
$Project.SelectNodes('Project/Reports/ProjectItem') |
ForEach-Object {
$RdlPath = $ProjectRoot | Join-Path -ChildPath $_.FullPath
[xml]$Definition = Get-Content -Path $RdlPath
$NsMgr = New-XmlNamespaceManager $Definition d
$RawDefinition = Get-Content -Encoding Byte -Path $RdlPath
$Name = $_.Name -replace '\.rdl$',''
$DescProp = New-Object -TypeName SSRS.ReportingService2010.Property
$DescProp.Name = 'Description'
$DescProp.Value = ''
$HiddenProp = New-Object -TypeName SSRS.ReportingService2010.Property
$HiddenProp.Name = 'Hidden'
$HiddenProp.Value = 'false'
$Properties = @($DescProp, $HiddenProp)
$Xpath = 'd:Report/d:Description'
$DescriptionNode = $Definition.SelectSingleNode($Xpath, $NsMgr)
if($DescriptionNode)
{
$DescProp.Value = $DescriptionNode.Value
}
if($Name.StartsWith('_'))
{
$HiddenProp.Value = 'true'
}
Write-Verbose "Creating report $Name"
$warnings = $null
$Results = $Proxy.CreateCatalogItem("Report", $Name, $Folder, $true, $RawDefinition, $Properties, [ref]$warnings)
$Xpath = 'd:Report/d:DataSources/d:DataSource/d:DataSourceReference/..'
$DataSources = $Definition.SelectNodes($Xpath, $NsMgr) |
ForEach-Object {
$DataSourcePath = $DataSourcePaths[$_.DataSourceReference]
if (-not $DataSourcePath) {
throw "Invalid data source reference '$($_.DataSourceReference)' in $RdlPath"
}
$Reference = New-Object -TypeName SSRS.ReportingService2010.DataSourceReference
$Reference.Reference = $DataSourcePath
$DataSource = New-Object -TypeName SSRS.ReportingService2010.DataSource
$DataSource.Item = $Reference
$DataSource.Name = $_.Name
$DataSource
}
if ($DataSources) {
$Proxy.SetItemDataSources($Folder + '/' + $Name, $DataSources)
}
$Xpath = 'd:Report/d:DataSets/d:DataSet/d:SharedDataSet/d:SharedDataSetReference/../..'
$References = $Definition.SelectNodes($Xpath, $NsMgr) |
ForEach-Object {
$DataSetPath = $DataSetPaths[$_.SharedDataSet.SharedDataSetReference]
if ($DataSetPath) {
$Reference = New-Object -TypeName SSRS.ReportingService2010.ItemReference
$Reference.Reference = $DataSetPath
$Reference.Name = $_.Name
$Reference
}
}
if ($References) {
$Proxy.SetItemReferences($Folder + '/' + $Name, $References)
}
}
#requires -version 2.0
[CmdletBinding()]
param (
[parameter(Mandatory=$true)]
[ValidatePattern('\.rptproj$')]
[ValidateScript({ Test-Path -PathType Leaf -Path $_ })]
[string]
$Path,
[parameter(Mandatory=$true)]
[string]
$Configuration
)
function Normalize-SSRSFolder (
[string]$Folder
) {
if (-not $Folder.StartsWith('/')) {
$Folder = '/' + $Folder
}
return $Folder
}
$script:ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
Write-Verbose "$($MyInvocation.MyCommand.Name) -Path $Path -Configuration $Configuration"
[xml]$Project = Get-Content -Path $Path
$Config = $Project.SelectNodes('Project/Configurations/Configuration') |
Where-Object { $_.Name -eq $Configuration } |
Select-Object -First 1
if (-not $Config) {
throw "Could not find configuration $Configuration."
}
$OverwriteDataSources = $false
if ($Config.Options.SelectSingleNode('OverwriteDataSources')) {
$OverwriteDataSources = [Convert]::ToBoolean($Config.Options.OverwriteDataSources)
}
return New-Object -TypeName PSObject -Property @{
ServerUrl = $Config.Options.TargetServerUrl
Folder = Normalize-SSRSFolder -Folder $Config.Options.TargetFolder
DataSourceFolder = Normalize-SSRSFolder -Folder $Config.Options.TargetDataSourceFolder
DataSetFolder = Normalize-SSRSFolder -Folder $Config.Options.TargetDataSetFolder
OverwriteDataSources = $OverwriteDataSources
}
#requires -version 2.0
[CmdletBinding()]
param (
[parameter(Mandatory=$true)]
[ValidatePattern('^https?://')]
[string]
$Uri,
[System.Management.Automation.PSCredential]
$Credential
)
$script:ErrorActionPreference = 'Stop'
Set-StrictMode -Version Latest
if (-not $Uri.EndsWith('.asmx')) {
if (-not $Uri.EndsWith('/')) {
$Uri += '/'
}
$Uri += 'ReportService2010.asmx'
}
$Assembly = [AppDomain]::CurrentDomain.GetAssemblies() |
Where-Object {
$_.GetType('SSRS.ReportingService2010.ReportingService2010')
}
if (($Assembly | Measure-Object).Count -gt 1) {
throw 'AppDomain contains multiple definitions of the same type. Restart PowerShell host.'
}
if (-not $Assembly) {
if ($Credential) {
$CredParams = @{ Credential = $Credential }
} else {
$CredParams = @{ UseDefaultCredential = $true }
}
$Proxy = New-WebServiceProxy -Uri $Uri -Namespace SSRS.ReportingService2010 @CredParams
} else {
$Proxy = New-Object -TypeName SSRS.ReportingService2010.ReportingService2010
if ($Credential) {
$Proxy.Credentials = $Credential.GetNetworkCredential()
} else {
$Proxy.UseDefaultCredentials = $true
}
}
$Proxy.Url = $Uri
return $Proxy
if (-not (Test-Path("cred2.txt"))) {
Write-Host "=========================================================" -foregroundcolor cyan
Write-Host "» To deploy the Debug configuration to localhost, type"
Write-Host "» your credentials. It will be stored as a SecureString"
Write-Host "» on disk, but not checked into source control."
Write-Host "» Username: " -foregroundcolor cyan; Read-Host | Out-File cred1.txt
Write-Host "» Password: " -foregroundcolor cyan; Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File cred2.txt
}
$pass = cat cred2.txt | ConvertTo-SecureString
$user = cat cred1.txt
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $user,$pass
Write-Host "Deployment started..." -foregroundcolor yellow
.\Deploy-SSRSProject.ps1 -Path 'pathtoproject\ProjectFile.rptproj' -Configuration 'Debug' -Credential $cred
Write-Host "Deployment finished!" -foregroundcolor green
$pass = ConvertTo-SecureString -AsPlainText -Force -String "password"
$user = "username"
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist $user,$pass
Write-Host "Deployment started..." -foregroundcolor yellow
.\Deploy-SSRSProject.ps1 -Verbose -Path 'pathtoproject\ProjectFile.rptproj' -Configuration 'Release' -Credential $cred
Write-Host "Deployment finished!" -foregroundcolor green
@atchutmca
Copy link

Hi,

Could you please give me an example of the command to deploy? I have tried following but not successful.

$pass = ConvertTo-SecureString -AsPlainText -Force -String "password-of-the-user"
$user = "windows-user-of-the-windows-computer-on-which-the-ssrs-report-created"

.\Deploy-SSRSProject.ps1 -Verbose -Path 'C:\Users\username\Documents\Visual Studio 2008\Projects\Report Project2\Report Project2\Report Project2.rptproj' -Configuration 'windows-computer-name-on-which-the-report-project-is-created' -Credential $cred

Thanks & Regards,
Atchut.

@gep13
Copy link

gep13 commented Jan 6, 2015

@Jonesie thank you very much for this script, very useful!

@timabell
Copy link

@edudutra
Copy link

Great job. Saved me tons of work. Thanks

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