【问题标题】:SSRS report using PowerShell Start-Job使用 PowerShell Start-Job 的 SSRS 报告
【发布时间】:2021-08-22 20:02:56
【问题描述】:

我有一个 PowerShell GUI,它使用字符串数组输入从 SSRS 报告中提取一些值。但是,由于这会冻结 GUI,我决定使用Start-Job 来启动一个工作,该工作会在 ProgressBar 继续在 GUI 中运行的同时提取 SSRS 报告。

SSRS 报告只有一个输入参数。当我使用Start-Job 使用多个值呈现报表时,我只得到第一条记录的结果,而与输入值的数量无关。

同样的函数在本地调用时运行顺畅,Start-Job 不返回所有输入值的记录。

这是代码:

$GetSSRSData = {
    param([string[]]$InputArray)

    $reportServerURI = "https://<SERVER>/ReportServer/ReportExecution2005.asmx?wsdl"
    $RS = New-WebServiceProxy -Class 'RS' -NameSpace 'RS' -Uri $reportServerURI -UseDefaultCredential
    $RS.Url = $reportServerURI

    $deviceInfo = "<DeviceInfo><NoHeader>True</NoHeader></DeviceInfo>"
    $extension = ""
    $mimeType = ""
    $encoding = ""
    $warnings = $null
    $streamIDs = $null

    $reportPath = "/Folder/Report"
    $Report = $RS.GetType().GetMethod("LoadReport").Invoke($RS, @($reportPath, $null))

    # Report parameters are handled by creating an array of ParameterValue objects.
    $parameters = @()

    for($i = 0; $i -lt $InputArray.Count; $i++){
        $parameters += New-Object RS.ParameterValue
        $parameters[$i].Name  = "ParameterName"
        $parameters[$i].Value = "$($InputArray[$i])"
    }

    # Add the parameter array to the service.  Note that this returns some
    # information about the report that is about to be executed.
    $RS.SetExecutionParameters($parameters, "en-us") > $null
    
    # Render the report to a byte array. The first argument is the report format.
    $RenderOutput = $RS.Render('CSV',
        $deviceInfo,
        [ref] $extension,
        [ref] $mimeType,
        [ref] $encoding,
        [ref] $warnings,
        [ref] $streamIDs
    )

    $output = [System.Text.Encoding]::ASCII.GetString($RenderOutput)
    return $output
}
$InputArray = @('XXXXXX', 'YYYYYY', 'ZZZZZZ', 'ABCDEF')

<#
# The below code works perfectly
$Data = GetSSRSData -InputArray $InputArray
ConvertFrom-Csv -InputObject $Data
#>

$job = Start-Job -ScriptBlock $GetSSRSData -ArgumentList $InputArray
do { [System.Windows.Forms.Application]::DoEvents() } until ($job.State -ne "Running")
$Data = Receive-Job -Job $job
Write-Host $Data # returns only the first record

当我如下所示更改底部时,我能够验证作业是否在输出第一条记录后结束。

        $RenderOutput = $RS.Render('CSV',
        $deviceInfo,
        [ref] $extension,
        [ref] $mimeType,
        [ref] $encoding,
        [ref] $warnings,
        [ref] $streamIDs
    )

    Write-Output $RenderOutput
}

$InputArray = @('XXXXXX', 'YYYYYY', 'ZZZZZZ', 'ABCDEF')
$job = Start-Job -ScriptBlock $GetSSRSData -ArgumentList $InputArray
do {[System.Text.Encoding]::ASCII.GetString($job.ChildJobs[0].Output)} until ($job.State -ne "Running")

我也试过在Render函数后加一个5秒的sleep函数,但没有任何区别。

请注意,不能为每个输入重复调用 Start-Job,因为每个函数调用都会花费大量时间,因此需要在一次调用中提取报告。

  • 为什么 Render 函数在作为作业启动时表现不同?函数是否在渲染其他记录之前提前结束?
  • 有没有其他方法可以解决这个问题,比如 Runspace 或者 Start-ThreadJob?

参考:https://stackoverflow.com/a/63253699/4137016

【问题讨论】:

    标签: powershell reporting-services ssrs-2008-r2 reportingservices-2005 start-job


    【解决方案1】:

    答案在这里:ArgumentList parameter in Invoke-Command don't send all array
    这里可能会有更好的答案:How do I pass an array as a parameter to another script?

    -ArgumentList $InputArray 更改为-ArgumentList (,$InputArray)

    $InputArray = @('XXXXXX', 'YYYYYY', 'ZZZZZZ', 'ABCDEF')
    $job = Start-Job -ScriptBlock $GetSSRSData -ArgumentList (,$InputArray)
    

    【讨论】:

    • 我从没想过!我本可以检查一下:Write-Output $InputArray.Count 而不是:Write-Output $RenderOutput 非常感谢您让它工作!
    • 要发送多个参数,包括一个数组,-ArgumentList $InputString, (,$InputArray)。对吗?
    • @Suraj,你应该使用正常的语法-ArgumentList $InputString, $InputArray。仅在提供单个数组时才需要 (, $array) 语法。这是 PowerShell 陷阱之一
    猜你喜欢
    • 2018-01-02
    • 1970-01-01
    • 2011-04-25
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多