【问题标题】:SSRS and PowerShell: Get report as ExcelSSRS 和 PowerShell:以 Excel 格式获取报告
【发布时间】:2015-02-26 11:14:02
【问题描述】:

我正在尝试让 PowerShell 向我们的 SSRS 服务器发送 Web 请求并捕获结果。我在 SSRS url 字符串中使用 rs:FORMAT=EXCEL 参数碰壁了。我有以下内容:

首先,初始化凭据:

$User = "MYDOMAIN\MyUser"
$PWord = ConvertTo-SecureString -String "WooHooStringP$W0rd" -AsPlainText -Force
$c = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $User, $PWord

现在,请求报告:

Invoke-WebRequest `
-UserAgent ([Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer) `
-Credential $c `
-Uri "http://myserver/ReportServer_DEV/Pages/ReportViewer.aspx?/folder+path/report+name"

这很好用。我什至可以获取结果(包含此请求并使用 ().Content)。 然后,指定格式而不是普通渲染:

Invoke-WebRequest `
-UserAgent ([Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer) `
-Credential $c `
-Uri "http://myserver/ReportServer_DEV/Pages/ReportViewer.aspx?/folder+path/report+name&rs:format=HTML4.0"

注意rs:Format 规范?像魅力一样工作。

然后,为大结局,给我一个 Excel 文件:

Invoke-WebRequest `
-UserAgent ([Microsoft.PowerShell.Commands.PSUserAgent]::InternetExplorer) `
-Credential $c `
-Uri "http://myserver/ReportServer_DEV/Pages/ReportViewer.aspx?/folder+path/report+name&rs:format=EXCEL"

没办法,老兄:

Invoke-WebRequest : The remote server returned an error: (401) Unauthorized.
At line:1 char:11
+ $bytez = (Invoke-WebRequest `
+           ~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

为什么rs:format=EXCEL 选项会在所有其他 URL 都由 SSRS 提供服务的情况下引发未经授权的异常?

【问题讨论】:

    标签: powershell reporting-services ssrs-2008-r2


    【解决方案1】:

    我想通了!我以错误的方式解决了这个问题:SSRS 通过 PowerShell 可以使用的 Web 服务提供访问,而无需破解 URL 并捕获响应。我找到了一个执行此操作的脚本并对其进行了修改以适合我的目的:

    function GetRSConnection($server, $instance)
    {
        #   Create a proxy to the SSRS server and give it the namespace of 'RS' to use for
        #   instantiating objects later.  This class will also be used to create a report
        #   object.
    
        $User = "DOMAIN\Username"
        $PWord = ConvertTo-SecureString -String "Pa$$w0rd" -AsPlainText -Force
        $c = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $User, $PWord
    
        $reportServerURI = "http://" + $server + "/" + $instance + "/ReportExecution2005.asmx?WSDL"
    
        $RS = New-WebServiceProxy -Class 'RS' -NameSpace 'RS' -Uri $reportServerURI -Credential $c
        $RS.Url = $reportServerURI
        return $RS
    }
    
    function GetReport($RS, $reportPath)
    {
        #   Next we need to load the report. Since Powershell cannot pass a null string
        #   (it instead just passses ""), we have to use GetMethod / Invoke to call the
        #   function that returns the report object.  This will load the report in the
        #   report server object, as well as create a report object that can be used to
        #   discover information about the report.  It's not used in this code, but it can
        #   be used to discover information about what parameters are needed to execute
        #   the report.
        $reportPath = "/" + $reportPath
        $Report = $RS.GetType().GetMethod("LoadReport").Invoke($RS, @($reportPath, $null))
    
        # initialise empty parameter holder
        $parameters = @()
        $RS.SetExecutionParameters($parameters, "nl-nl") > $null
        return $report
    }
    
    function AddParameter($params, $name, $val)
    {
        $par = New-Object RS.ParameterValue
        $par.Name = $name
        $par.Value = $val
        $params += $par
        return ,$params
    }
    
    function GetReportInFormat($RS, $report, $params, $outputpath, $format)
    {
        #   Set up some variables to hold referenced results from Render
        $deviceInfo = "<DeviceInfo><NoHeader>True</NoHeader></DeviceInfo>"
        $extension = ""
        $mimeType = ""
        $encoding = ""
        $warnings = $null
        $streamIDs = $null
    
        #   Report parameters are handled by creating an array of ParameterValue objects.
        #   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
        $RS.SetExecutionParameters($params, "nl-nl") > $null
    
        #    Render the report to a byte array.  The first argument is the report format.
        #    The formats I've tested are: PDF, XML, CSV, WORD (.doc), EXCEL (.xls),
        #    IMAGE (.tif), MHTML (.mhtml).
        $RenderOutput = $RS.Render($format,
            $deviceInfo,
            [ref] $extension,
            [ref] $mimeType,
            [ref] $encoding,
            [ref] $warnings,
            [ref] $streamIDs
        )
    
        #   Determine file name
        $parts = $report.ReportPath.Split("/")
        $filename = $parts[-1] + "."
        switch($format)
        {
            "EXCEL" { $filename = $filename + "xls" } 
            "WORD" { $filename = $filename + "doc" }
            "IMAGE" { $filename = $filename + "tif" }
            default { $filename = $filename + $format }
        }
    
        if($outputpath.EndsWith("\\"))
        {
            $filename = $outputpath + $filename
        } else
        {
            $filename = $outputpath + "\" + $filename
        }
    
        $filename
    
        # Convert array bytes to file and write
        $Stream = New-Object System.IO.FileStream($filename), Create, Write
        $Stream.Write($RenderOutput, 0, $RenderOutput.Length)
        $Stream.Close()
    }
    
    $RS = GetRSConnection -server "DEVBOX" -instance "ReportServer_DEV"
    $report = GetReport -RS $RS -reportPath "folder name/report name"
    
    $params = @()
    $params = AddParameter -params $params -name "Month" -val "201311"
    
    GetReportInformat -RS $RS -report $report -params $params -outputpath "i:\test" -format "EXCEL"
    

    【讨论】:

    • 感谢您分享此内容。今天对我有用!效果很好。
    【解决方案2】:

    使用网络请求:

    [string]$Domain = "DomainUsername"
    [string]$Username = "Username"
    [string]$Password = "Password"
    [string]$ReportServer = "http://ssrsreportserver/ReportServer/ReportExecution2005.asmx" #Report Server
    [string]$ReportLocation = "/Report Location/Report Name" #Report Location ON SSRS
    $ReportLocation = $ReportLocation.Replace("/", "%2f")
    $ReportLocation = $ReportLocation.Replace(" ", "+")
    [string]$outputFile = $PSScriptRoot + '\Report.xlsx' #Save location for the file
    
    #If the report has any parameters
    [string]$ParamString = "";
    $ParamString += "&param1=paramvalue"
    $ParamString += "&param2=paramvalue"
    
    [string]$URL = $ReportServer + "?" + $ReportLocation + "&rs:Command=Render&rs:Format=" + "EXCELOPENXML" + "&rs:ParameterLanguage=en-GB" + $ParamString
    Write-Host $URL
    $Req = [System.Net.WebRequest]::Create($URL);
    $Req.Credentials = new-object System.Net.NetworkCredential($Username, $Password, $Domain)
    $Req.Timeout = 30000;
    
    $WebStream = $Req.GetResponse().GetResponseStream();
    
    $MemStream = New-Object System.IO.MemoryStream
    $WebStream.CopyTo($MemStream);
    [long]$Len = $MemStream.Length;
    
    [byte[]]$outBytes = [System.Byte[]]::CreateInstance([System.Byte], $Len)
    $MemStream.Seek(0, [System.IO.SeekOrigin]::Begin);
    $MemStream.Read($outBytes, 0, [int]$Len);
    $WebStream.Close();
    $MemStream.Close();
    $MemStream.Dispose();
    
    $Stream = New-Object System.IO.FileStream($outputFile), Create, Write
    $Stream.Write($outBytes, 0, $outBytes.Length)
    $Stream.Close()
    Invoke-Item $outputFile
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多