2010-11-16 63 views
3

我一直在玩这个没有运气的日子。基本上我试图建立一个简单的库来使用Powershell来呈现SSRS报告。我正在使用Powershell试图稍后缓解开发(而不是为每个项目编写C#应用程序)。大多数情况下,这将用于安排报告的各种事情。使用Powershell中的SOAP使用参数呈现SSRS报告

我有报告渲染主要是在Powershell中工作。我无法弄清楚的一件事是如何在调用渲染方法之前向报告提供参数。我发现很多与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

为什么不能直接在$ Reports上调用LoadReport?当你执行这个'$ Reports |时,你会看到什么? GET-Member'? LoadReport不显示吗?如果是这样,它有什么签名?此外,看看这篇文章是否有所帮助 - http://social.msdn.microsoft.com/Forums/en-US/sqlreportingservices/thread/c14011bf-6d06-492e-befa-f82902a1d187/ – 2010-11-16 17:22:22

+0

我试过了,但似乎没有就像我提供的论据一样。出于某种原因使用调用工作。但是,该部分起作用,并且不应该干扰提供参数。 – Matthew 2010-11-16 17:30:26

+0

添加到我以前的评论,它出现使用$ Reports.LoadReport不会接受空的历史ID,这就是为什么我发现的代码是使用调用。 – Matthew 2010-11-16 17:50:14

回答

9

下面是我最终使用的解决方案的一些信息,以防其他人需要这样做。它工作得很好。

工作的第一种方法是构建一个由Powershell脚本使用的DLL。这工作得很好,但它会导致两个问题。首先,你的脚本来装载一个DLL。其次,这个DLL绑定到特定的SSRS服务器。为了访问另一台服务器,你必须使用多个DLL。

最后,我回到使用Web代理。这里的关键是使用名称空间,以便您可以实例化一个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个报告。

+0

任何解决方案与完整的源代码渲染,生成文件和邮件吗? – Kiquenet 2012-06-27 12:43:57

+0

不错,我试过的方式是$ webclient。下载文件($ url,$ file),然后通过电子邮件发送。 – Shawn 2013-01-22 00:14:59

+0

在更新版本的powershell中,常量'[NullString] :: Value'被添加来避免$''在作为字符串传递给方法时被强制为空字符串的问题。传递这个常量而不是'$ null',你可以避免使用反射。如果'[NullString]'不可用作加速器,'[System.Management.Automation.Internal.AutomationNull] :: Value'是等价的(但稍微不灵活)。 – x0n 2014-10-21 20:50:55

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 = "[email protected]" 
$smtpFrom = "[email protected]" 
$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()