我已经玩弄了好几天没有运气。基本上我正在尝试使用Powershell构建一个简单的库来呈现SSRS报告。我正在使用Powershell试图在以后简化开发(而不是为每个项目编写C#应用程序)。大多数情况下,这将用于通过报告安排各种事情。
我的报告呈现主要是在Powershell中工作。我无法弄清楚的一件事是如何在调用render方法之前为报表提供参数。我发现了大量与C#和VB相关的代码(我在其他SSRS项目中使用过),但是我无法将其转换为Powershell。
由于我对Powershell很新,我不熟悉正确的方法。这是我一直在使用的代码:
$ReportExecutionURI = "http://glitas10//ReportServer//ReportExecution2005.asmx?wsdl"
$ReportPath = "/Financial/ExpenseReportStub"
$format = "PDF"
$deviceInfo = "<DeviceInfo><NoHeader>True</NoHeader></DeviceInfo>"
$extension = ""
$mimeType = ""
$encoding = ""
$warnings = $null
$streamIDs = $null
$Reports = New-WebServiceProxy -Uri $ReportExecutionURI -UseDefaultCredential
# Load the report
$Report = $Reports.GetType().GetMethod("LoadReport").Invoke($Reports, @($ReportPath, $null))
# Render the report
$RenderOutput = $Reports.Render($format, $deviceInfo, [ref] $extension, [ref] $mimeType, [ref] $encoding, [ref] $warnings, [ref] $streamIDs)
显然,对于不需要参数的报表,它可以正常工作。
关于我需要做什么来实例化正确的对象并传递参数的任何想法?
答案 0 :(得分:9)
以下是我最终使用的解决方案的一些信息,以防其他人需要做同样的事情。它的效果非常好。
第一种方法是构建一个由Powershell脚本使用的DLL。这很好,但它会导致两个问题。首先,您的脚本已来围绕DLL。其次,此DLL绑定到特定的SSRS服务器。为了访问另一台服务器,您必须使用多个DLL。
最终,我又回到了使用网络代理。这里的关键是使用名称空间,以便您可以实例化ParameterValue对象。这是代码:
# 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.
$reportServerURI = "http://<SERVER>/ReportServer/ReportExecution2005.asmx?WSDL"
$RS = New-WebServiceProxy -Class 'RS' -NameSpace 'RS' -Uri $reportServerURI -UseDefaultCredential
$RS.Url = $reportServerURI
# Set up some variables to hold referenced results from Render
$deviceInfo = "<DeviceInfo><NoHeader>True</NoHeader></DeviceInfo>"
$extension = ""
$mimeType = ""
$encoding = ""
$warnings = $null
$streamIDs = $null
# 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 = "/PathTo/Report"
$Report = $RS.GetType().GetMethod("LoadReport").Invoke($RS, @($reportPath, $null))
# Report parameters are handled by creating an array of ParameterValue objects.
$parameters = @()
$parameters += New-Object RS.ParameterValue
$parameters[0].Name = "Parameter 1"
$parameters[0].Value = "Value"
$parameters += New-Object RS.ParameterValue
$parameters[1].Name = "Parameter 2"
$parameters[1].Value = "Value"
# 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.
# The formats I've tested are: PDF, XML, CSV, WORD (.doc), EXCEL (.xls),
# IMAGE (.tif), MHTML (.mhtml).
$RenderOutput = $RS.Render('PDF',
$deviceInfo,
[ref] $extension,
[ref] $mimeType,
[ref] $encoding,
[ref] $warnings,
[ref] $streamIDs
)
# Convert array bytes to file and write
$Stream = New-Object System.IO.FileStream("output.pdf"), Create, Write
$Stream.Write($RenderOutput, 0, $RenderOutput.Length)
$Stream.Close()
看起来相当容易,而且确实如此。这种方法效果非常好,是我现在用来呈现和通过电子邮件发送预定报告的方法,因为它提供了比内置SSRS调度更多的灵活性。另外,它相对较快。我用来邮寄报告的其中一个脚本每分钟可以渲染和发送大约20-30个报告。
答案 1 :(得分:0)
有同样的问题,还希望将生成的MHT文件作为电子邮件正文发送: 发现以下情况有效 旧的CDO.Message是我发现的唯一允许将MHTML文件作为电子邮件正文发送的东西。 下面是VB程序的(工作)翻译 旧但很简单; - )!
################## Send MHTML email ##############################
# use antiquated CDO to send mhtml as email body
$smtpServer = "my-mail-server"
$smtpSubject = "MHT file sent as body of email"
$smtpTo = "you@work.com"
$smtpFrom = "me@home.org"
$MHTMLfile = "my-MHT-File.mht
# e.g. from an SSRS.Render
$AdoDbStream = New-Object -ComObject ADODB.Stream
$AdoDbStream.Charset = "ascii"
$AdoDbStream.Open()
$AdoDbStream.LoadFromFile($MHTMLfile)
$CdoMessage = New-Object -ComObject CDO.Message
$CdoMessage.DataSource.OpenObject($AdoDbStream,"_Stream")
$SendUsingPort = 2
$smtpPort = 25
$cfg = "http://schemas.microsoft.com/cdo/configuration/"
$CdoMessage.Configuration.Fields.Item($cfg + "sendusing") = $SendUsingPort
$CdoMessage.Configuration.Fields.Item($cfg + "smtpserver") = $SmtpServer
$CdoMessage.Configuration.Fields.Item($cfg + "smtpserverport") = $smtpPort
$CdoMessage.To = $smtpTo
$CdoMessage.From = $smtpFrom
$CdoMessage.Subject = $smtpSubject
$CdoMessage.MimeFormatted = $true
$CdoMessage.Configuration.Fields.Update()
WRITE-HOST "Sending email"
$CdoMessage.Send()
答案 2 :(得分:0)
我有一个类似的问题。 花了一些时间来找出问题所在。 如果需要,您不应“撤消”不带参数的报告 因此,代码应如下所示:
try {
<# Despose and clear resources if open #>
if ($RS) { $RS.Dispose() }
if ($Stream) { $Stream.Close() }
<# Create Report Service #>
[string]$reportServerURI = "<SSRS Service URL>"
$RS = New-WebServiceProxy -Class 'RS' -NameSpace 'RS' -Uri $reportServerURI -UseDefaultCredential
$RS.Url = $reportServerURI
<# Set up some variables to hold referenced results from Render #>
$deviceInfo = "<DeviceInfo><NoHeader>True</NoHeader></DeviceInfo>"
$extension = ""
$mimeType = ""
$encoding = ""
$warnings = $null
$streamIDs = $null
<# Initial Report #>
$reportPath = "<Full path/URL to rdl file>"
## Do not revoke the report ## $Report = $RS.GetType().GetMethod("LoadReport").Invoke($RS, @($reportPath, $null))
<# Initial Report Parameters Array #>
$Parameters = $RS.GetType().GetMethod("LoadReport").Invoke($RS, @($reportPath, $null)).Parameters
<# Populate Report Parameters values #>
$Params = @()
Foreach ($Parameter in $Parameters ) {
$par1 = New-Object RS.ParameterValue;
$Par1.Name = $Parameter.Name;
$Par1.Label = $Parameter.Name;
switch ($Par1.Name) {
"<1st Param Name>" { $par1.Value = <1st Param Value>; break }
"<2nd Param Name>" { $par1.Value = <2nd Param Value>; break }
...
"<#n Param Name>" { $par1.Value = <#n Param Value>; break }
}
$Params += $Par1;
}
<# Execute/invoke the report with the parameters #>
$RS.SetExecutionParameters($Params, "en-us") > $null
<# Set report render output format#>
[string]$format = <"PDF","Excel" etc.>
<# Eecute Report render #>
try { $RenderOutput = $RS.Render($format,
$deviceInfo,
[ref] $extension,
[ref] $mimeType,
[ref] $encoding,
[ref] $warnings,
[ref] $streamIDs)
} catch { Log-Message -message "Unable to render or save the report due to an error." -IsError $true; throw
}
<# Convert array bytes to file and write #>
$Stream = New-Object System.IO.FileStream(<Final Report Output File), Create, Write
$Stream.Write($RenderOutput, 0, $RenderOutput.Length)
$Stream.Close()
if ($RS) { $RS.Dispose() }
}catch{ Log-Message -message "Error in Execute-Report, could not stream or other error." -IsError $true; throw }
问题解决了。