function Set-ReportDataSource { <# .SYNOPSIS Set the DataSource for a SSRS report .PARAMETER Proxy SSRS Proxy .PARAMETER ReportPath Path to report on SSRS server .PARAMETER RdlPath Local filepath to RDL report file .PARAMETER AvoidDoubleHop Whether to use special measures to avoid the DoubleHop issue .PARAMETER ReportServerUserName Username for SSRS server .PARAMETER ReportServerPassword Password for SSRS server #> [CmdletBinding()] Param( [Parameter(Position=0,Mandatory=$true)] [System.Web.Services.Protocols.SoapHttpClientProtocol]$Proxy, [Parameter(Position=1, Mandatory=$true)] [string]$ReportPath, [Parameter(Position=2, Mandatory=$true)] [string]$RdlPath, [Parameter(Position=3, Mandatory=$true)] [Alias("ApplyDoubleHopFix")] [bool]$AvoidDoubleHop, [Parameter(Position=4, Mandatory=$false)] [Alias("Username")] [string]$ReportServerUserName, [Parameter(Position=5, Mandatory=$false)] [Alias("Password")] [string]$ReportServerPassword ) $logLead = Get-LogLeadName Write-Verbose ("$logLead : Getting XML Datasources of {0}" -f $RdlPath) [xml]$reportContent = Get-Content $RdlPath $rdlDataSources = $reportContent.Report.DataSources Write-Verbose ("$logLead : Getting Datasource References of published report {0} " -f $ReportPath) $reportDataSources = $Proxy.GetItemDataSources($ReportPath) Write-Verbose "$logLead : Calling Get-PublishedDataSources" $publishedDataSources = Get-PublishedDataSources $Proxy ($ReportPath.Split("/") | Where-Object {$_ -ne [String]::Empty} | Select-Object -First 1) $dirty = $false foreach ($rdlDataSource in $rdlDataSources.DataSource) { Write-Verbose ("$logLead : Checking Datasource {0}" -f $rdlDataSource.Name) $targetDataSource = $reportDataSources | Where-Object {$_.Name -eq $rdlDataSource.Name} if ($null -eq $targetDataSource) { Write-Verbose ("$logLead : Unable to find data source in published report with name {0}" -f $rdlDataSource.Name) continue } $ProxyNamespace = $targetDataSource.GetType().Namespace if ($null -eq $rdlDataSource.DataSourceReference) { Write-Verbose "$logLead : Setting DataProvider Reference" $ref = New-Object $targetDataSource.GetType().Assembly.GetType("$Proxynamespace.DataSourceDefinition") $ref.ConnectString = $rdlDataSource.ConnectionProperties.ConnectString $ref.Extension = $rdlDataSource.ConnectionProperties.DataProvider $ref.OriginalConnectStringExpressionBased = ($rdlDataSource.ConnectionProperties.ConnectString -match "^=").ToString() $ref.Enabled = $true $ref.EnabledSpecified = $true $ref.UseOriginalConnectString = $true $ref.ImpersonateUserSpecified = $true if ($rdlDataSource.ConnectionProperties.IntegratedSecurity -match "true") { if ($AvoidDoubleHop) { # Set the credentials on this data source if ((Test-IsWebServer) -and ([String]::IsNullOrEmpty($ReportServerUserName) -or [String]::IsNullOrEmpty($ReportServerPassword))) { # Read the User Credentials from the machine.config Write-Verbose ("$logLead : Reading Credential Information from the machine.config") [xml]$config = Get-ReportServerConfiguration $reportServerUserNode = $config.appSettings.SelectSingleNode("//add[@key=""ReportServerUserName""]/@value") $ReportServerPasswordNode = $config.appSettings.SelectSingleNode("//add[@key=""ReportServerPassword""]/@value") if (($null -eq $reportServerUserNode) -or ([String]::IsNullOrEmpty($reportServerUserNode.Value))) { Write-Warning "$logLead : Could not read the value for the ""ReportServerUserName"" appSetting from the machine.config. Correct this report manually" return; } if (($null -eq $ReportServerPasswordNode) -or ([String]::IsNullOrEmpty($ReportServerPasswordNode.Value))) { Write-Warning "$logLead : Could not read the value for the ""ReportServerPassword"" appSetting from the machine.config. Correct this report manually" return; } else { Write-Verbose ("$logLead : Using Credentials for $ReportServerUserName Passed via Parameter") } $ReportServerUserName = $reportServerUserNode.Value $ReportServerPassword = $ReportServerPasswordNode.Value } Write-Verbose "$logLead : Setting DataSource to Use Username $ReportServerUserName" $ref.UserName = $ReportServerUserName $ref.Password = $ReportServerPassword $ref.WindowsCredentials = $true } $ref.CredentialRetrieval = [SSRS.CredentialRetrievalEnum]::Store } Write-Host ("$logLead : Setting datasource {0} for report {1} " -f $targetDataSource.Name, $RdlPath) $targetDataSource.Item = $ref $dirty = $true } else { Write-Verbose "$logLead : Setting DataSource Reference" $ref = New-Object $targetDataSource.GetType().Assembly.GetType("$Proxynamespace.DataSourceReference") $ref.Reference = $publishedDataSources | Where-Object {$_.Name -eq $rdlDataSource.Name} | Select-Object -First 1 -ExpandProperty "Path" if ($ref.Reference.Length -gt 0) { Write-Verbose ("Setting datasource {0} for report {1} " -f $targetDataSource.Name, $RdlPath) $targetDataSource.Item = $ref $dirty = $true } } } if ($dirty) { Write-Verbose "$logLead : Saving updated datasources" try { $Proxy.SetItemDataSources($ReportPath, $reportDataSources) } catch [Exception] { Write-Warning ("$logLead : An invalid parameter was specified for one or more datasources. Correct this report manually. Exception: {0}" -f $_.Exception.Message) } } }