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)
}