SSRS/Power BI 报表服务器 - 通过 Powershell 更新 RDP 中的超链接
SSRS / PowerBI Report Server - Update Hyperlinks in RDL via Powershell
我的 PowerBI 报表服务器上有许多报表,其中包含指向其他报表的超链接。 URLS 包含本地的主机名,我想更新它们(更新为新服务器的名称或本地主机)
我已经设法将以下循环遍历所有报告的 Powershell 代码整合在一起(出于测试目的,我已将其缩小到一个文件夹)、获取它们的定义、找到所有超链接并更新它们的值。我唯一没有解决的是如何“保存”我所做的更新:
Clear-Host
$DestinationReportServerURI = "http://NewServer/reports";
$reportServerUri = "http://NewServer/reportserver/ReportService2010.asmx?wsdl";
$rs = New-WebServiceProxy -Uri $reportServerUri -UseDefaultCredential -Namespace "SSRS";
$SourceServer = "OldServer"
$DestServer = "NewServer"
$reports = Get-RsFolderContent -RsFolder '/Path/To/Reports' -ReportServerUri $DestinationReportServerURI -Recurse | Where-Object TypeName -EQ "Report";
# loop through all reports
foreach ($r in $reports)
{
#Get the item definition (returns a byte array)
$def = $rs.GetItemDefinition($r.Path)
$a = [System.Text.Encoding]::ASCII.GetString($def)
$idx = $a.IndexOf('<')
[xml]$rdl = $a.Substring($idx,($a.length - $idx))
$rdl.save("C:\Test$($r.Name)_old.rdl") #verify what the RDL was like before update
$namespace = @{
rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner"
df="http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition"
}
# get all the Hyperlink nodes for this report
$hyperlinks = $rdl | Select-Xml '//df:Hyperlink' -Namespace $namespace | select -Expand Node
foreach ($h in $hyperlinks)
{
if ($h.'#text' -like "*$SourceServer*")
{
$hypUdated = $true
$h.'#text' = $($h.'#text').ToLower().Replace($SourceServer.ToLower(),$DestServer.ToLower())
}
}
if ($hypUdated -eq $true)
{
$rdl.save("C:\Test$($r.Name).rdl")
echo "$($r.Path) hyperlink updated"
$b = [System.Text.Encoding]::ASCII.GetBytes($rdl)
$rs.SetItemDefinition($r.Path,$b,$null)
}
};
我明白了
Exception calling "SetItemDefinition" with "3" argument(s): "The
definition of this report is not valid or supported by this version
of Reporting Services. The report definition may have been created
with a later version of Reporting Services, or contain content that
is not well-formed or not valid based on Reporting Services schemas.
Details: Data at the root level is invalid. Line 1, position 1."
来自上面的代码,但是我保存了更新前后的 rdl,因此我可以比较它们以进行故障排除,而 Notepad++ 比较插件仅报告超链接已更新的行的差异。此外,我可以使用 GUI 手动将更新的 RDL 上传到服务器并且它可以工作(并且当我打开它时超链接会更新)
有变化我注意到了
$rs.SetItemDefinition($r.Path,$b,$null)
到
$rs.SetItemDefinition($r.Path,$def,$null)
(运行 SetItemDefinition
with the original byte array) 我没有收到任何错误,所以这一定与我改变它的方式有关
我做错了什么?
我已经修好了。问题是我将 XML 类型转换为字节数组而不是字符串表示形式。解决方案是
foreach ($h in $hyperlinks)
{
if ($h.'#text' -like "*$SourceServer*")
{
$hypUdated = $true
$h.'#text' = $($h.'#text').ToLower().Replace($SourceServer.ToLower(),$DestServer.ToLower())
}
}
if ($hypUdated -eq $true)
{
$rdl.save("C:\Test$($r.Name).rdl")
Write-Host "$($r.Path) hyperlink updated"
$b = [System.Text.Encoding]::ASCII.GetBytes($rdl.OuterXml)
$rs.SetItemDefinition($r.Path,$b,$null)
}
我的 PowerBI 报表服务器上有许多报表,其中包含指向其他报表的超链接。 URLS 包含本地的主机名,我想更新它们(更新为新服务器的名称或本地主机)
我已经设法将以下循环遍历所有报告的 Powershell 代码整合在一起(出于测试目的,我已将其缩小到一个文件夹)、获取它们的定义、找到所有超链接并更新它们的值。我唯一没有解决的是如何“保存”我所做的更新:
Clear-Host
$DestinationReportServerURI = "http://NewServer/reports";
$reportServerUri = "http://NewServer/reportserver/ReportService2010.asmx?wsdl";
$rs = New-WebServiceProxy -Uri $reportServerUri -UseDefaultCredential -Namespace "SSRS";
$SourceServer = "OldServer"
$DestServer = "NewServer"
$reports = Get-RsFolderContent -RsFolder '/Path/To/Reports' -ReportServerUri $DestinationReportServerURI -Recurse | Where-Object TypeName -EQ "Report";
# loop through all reports
foreach ($r in $reports)
{
#Get the item definition (returns a byte array)
$def = $rs.GetItemDefinition($r.Path)
$a = [System.Text.Encoding]::ASCII.GetString($def)
$idx = $a.IndexOf('<')
[xml]$rdl = $a.Substring($idx,($a.length - $idx))
$rdl.save("C:\Test$($r.Name)_old.rdl") #verify what the RDL was like before update
$namespace = @{
rd="http://schemas.microsoft.com/SQLServer/reporting/reportdesigner"
df="http://schemas.microsoft.com/sqlserver/reporting/2016/01/reportdefinition"
}
# get all the Hyperlink nodes for this report
$hyperlinks = $rdl | Select-Xml '//df:Hyperlink' -Namespace $namespace | select -Expand Node
foreach ($h in $hyperlinks)
{
if ($h.'#text' -like "*$SourceServer*")
{
$hypUdated = $true
$h.'#text' = $($h.'#text').ToLower().Replace($SourceServer.ToLower(),$DestServer.ToLower())
}
}
if ($hypUdated -eq $true)
{
$rdl.save("C:\Test$($r.Name).rdl")
echo "$($r.Path) hyperlink updated"
$b = [System.Text.Encoding]::ASCII.GetBytes($rdl)
$rs.SetItemDefinition($r.Path,$b,$null)
}
};
我明白了
Exception calling "SetItemDefinition" with "3" argument(s): "The definition of this report is not valid or supported by this version of Reporting Services. The report definition may have been created with a later version of Reporting Services, or contain content that is not well-formed or not valid based on Reporting Services schemas. Details: Data at the root level is invalid. Line 1, position 1."
来自上面的代码,但是我保存了更新前后的 rdl,因此我可以比较它们以进行故障排除,而 Notepad++ 比较插件仅报告超链接已更新的行的差异。此外,我可以使用 GUI 手动将更新的 RDL 上传到服务器并且它可以工作(并且当我打开它时超链接会更新)
有变化我注意到了
$rs.SetItemDefinition($r.Path,$b,$null)
到
$rs.SetItemDefinition($r.Path,$def,$null)
(运行 SetItemDefinition
with the original byte array) 我没有收到任何错误,所以这一定与我改变它的方式有关
我做错了什么?
我已经修好了。问题是我将 XML 类型转换为字节数组而不是字符串表示形式。解决方案是
foreach ($h in $hyperlinks)
{
if ($h.'#text' -like "*$SourceServer*")
{
$hypUdated = $true
$h.'#text' = $($h.'#text').ToLower().Replace($SourceServer.ToLower(),$DestServer.ToLower())
}
}
if ($hypUdated -eq $true)
{
$rdl.save("C:\Test$($r.Name).rdl")
Write-Host "$($r.Path) hyperlink updated"
$b = [System.Text.Encoding]::ASCII.GetBytes($rdl.OuterXml)
$rs.SetItemDefinition($r.Path,$b,$null)
}