我需要创建一个可重复的流程来部署 SQL Server Reporting Services 报表。我不赞成使用 Visual Studio 或 Business Development Studio 来做到这一点。脚本部署的 rs.exe 方法似乎也相当笨拙。有没有人有一种非常优雅的方式来部署报告。这里的关键是我希望这个过程完全自动化。
7 回答
我们使用 rs.exe,一旦我们开发了脚本,我们就不需要再碰它了,它就可以工作了。
这是源代码(我手动对其进行了轻微修改以删除敏感数据而没有机会对其进行测试,希望我没有破坏任何东西),它部署了各种语言的子目录中的报告和相关图像。还创建了数据源。
'=====================================================================
' File: PublishReports.rss
'
' Summary: Script that can be used with RS.exe to
' publish the reports.
'
' Rss file spans from beginnig of this comment to end of module
' (except of "End Module").
'=====================================================================
Dim langPaths As String() = {"en", "cs", "pl", "de"}
Dim filePath As String = Environment.CurrentDirectory
Public Sub Main()
rs.Credentials = System.Net.CredentialCache.DefaultCredentials
'Create parent folder
Try
rs.CreateFolder(parentFolder, "/", Nothing)
Console.WriteLine("Parent folder created: {0}", parentFolder)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
PublishLanguagesFromFolder(filePath)
End Sub
Public Sub PublishLanguagesFromFolder(ByVal folder As String)
Dim Lang As Integer
Dim langPath As String
For Lang = langPaths.GetLowerBound(0) To langPaths.GetUpperBound(0)
langPath = langPaths(Lang)
'Create the lang folder
Try
rs.CreateFolder(langPath, "/" + parentFolder, Nothing)
Console.WriteLine("Parent lang folder created: {0}", parentFolder + "/" + langPath)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
'Create the shared data source
CreateDataSource("/" + parentFolder + "/" + langPath)
'Publish reports and images
PublishFolderContents(folder + "\" + langPath, "/" + parentFolder + "/" + langPath)
Next 'Lang
End Sub
Public Sub CreateDataSource(ByVal targetFolder As String)
Dim name As String = "data source"
'Data source definition.
Dim definition As New DataSourceDefinition
definition.CredentialRetrieval = CredentialRetrievalEnum.Store
definition.ConnectString = "data source=" + dbServer + ";initial catalog=" + db
definition.Enabled = True
definition.EnabledSpecified = True
definition.Extension = "SQL"
definition.ImpersonateUser = False
definition.ImpersonateUserSpecified = True
'Use the default prompt string.
definition.Prompt = Nothing
definition.WindowsCredentials = False
'Login information
definition.UserName = "user"
definition.Password = "password"
Try
'name, folder, overwrite, definition, properties
rs.CreateDataSource(name, targetFolder, True, definition, Nothing)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
Public Sub PublishFolderContents(ByVal sourceFolder As String, ByVal targetFolder As String)
Dim di As New DirectoryInfo(sourceFolder)
Dim fis As FileInfo() = di.GetFiles()
Dim fi As FileInfo
Dim fileName As String
For Each fi In fis
fileName = fi.Name
Select Case fileName.Substring(fileName.Length - 4).ToUpper
Case ".RDL"
PublishReport(sourceFolder, fileName, targetFolder)
Case ".JPG", ".JPEG"
PublishResource(sourceFolder, fileName, "image/jpeg", targetFolder)
Case ".GIF", ".PNG", ".BMP"
PublishResource(sourceFolder, fileName, "image/" + fileName.Substring(fileName.Length - 3).ToLower, targetFolder)
End Select
Next fi
End Sub
Public Sub PublishReport(ByVal sourceFolder As String, ByVal reportName As String, ByVal targetFolder As String)
Dim definition As [Byte]() = Nothing
Dim warnings As Warning() = Nothing
Try
Dim stream As FileStream = File.OpenRead(sourceFolder + "\" + reportName)
definition = New [Byte](stream.Length) {}
stream.Read(definition, 0, CInt(stream.Length))
stream.Close()
Catch e As IOException
Console.WriteLine(e.Message)
End Try
Try
'name, folder, overwrite, definition, properties
warnings = rs.CreateReport(reportName.Substring(0, reportName.Length - 4), targetFolder, True, definition, Nothing)
If Not (warnings Is Nothing) Then
Dim warning As Warning
For Each warning In warnings
Console.WriteLine(warning.Message)
Next warning
Else
Console.WriteLine("Report: {0} published successfully with no warnings", targetFolder + "/" + reportName)
End If
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
Public Sub PublishResource(ByVal sourceFolder As String, ByVal resourceName As String, ByVal resourceMIME As String, ByVal targetFolder As String)
Dim definition As [Byte]() = Nothing
Dim warnings As Warning() = Nothing
Try
Dim stream As FileStream = File.OpenRead(sourceFolder + "\" + resourceName)
definition = New [Byte](stream.Length) {}
stream.Read(definition, 0, CInt(stream.Length))
stream.Close()
Catch e As IOException
Console.WriteLine(e.Message)
End Try
Try
'name, folder, overwrite, definition, MIME, properties
rs.CreateResource(resourceName, targetFolder, True, definition, resourceMIME, Nothing)
Console.WriteLine("Resource: {0} with MIME {1} created successfully", targetFolder + "/" + resourceName, resourceMIME)
Catch e As Exception
Console.WriteLine(e.Message)
End Try
End Sub
这是调用 rs.exe 的批处理:
SET ReportServer=%1
SET DBServer=%2
SET DBName=%3
SET ReportFolder=%4
rs -i PublishReports.rss -s %ReportServer% -v dbServer="%DBServer%" -v db="%DBName%" -v parentFolder="%ReportFolder%" >PublishReports.log 2>&1
pause
我使用了@David提供的脚本,但我必须添加一些代码(我将其作为答案输入,因为这对于评论来说太长了。
问题是:如果报表定义中的报表已经附加了一个“共享数据源”,那么这绝不会与脚本中创建的数据源相同。
从“CreateReport”方法发出的警告中也可以看出这一点:
数据集“”是指共享数据源“”,未在报表服务器上发布。
所以数据源必须在之后明确设置。我进行了以下代码更改:
我添加了一个全局变量:
Dim dataSourceRefs(0) As DataSource
在 CreateDataSource 方法结束时,该变量被填充:
Dim dsr As New DataSourceReference
dsr.Reference = "/" + parentFolder + "/" + db
Dim ds As New DataSource
ds.Item = CType(dsr, DataSourceDefinitionOrReference)
ds.Name = db
dataSourceRefs(0) = ds
在 PublishReport 方法中,该数据源被显式设置(在调用 CreateReport 之后):
rs.SetItemDataSources(targetFolder + "/" + reportName.Substring(0, reportName.Length - 4), dataSourceRefs)
请注意,最后一次调用仅为 RS 2005 或更高版本。如果要将报表加载到 RS 2000 服务器上,则必须使用 Set Report DataSources 代替:
rs.SetReportDataSources(targetFolder + "/" + reportName.Substring(0, reportName.Length - 4), dataSourceRefs)
嗯,不是很优雅。我们创建了自己的工具,该工具使用了reportingservices2005 Web 服务。我们发现这是获得我们想要的最可靠的方式。
它并没有那么难,并且可以让您扩展它以执行其他操作,例如根据需要创建数据源和文件夹。
我强烈推荐RSScripter。如概述中所述:
Reporting Services Scripter 是一个 .NET Windows 窗体应用程序,它支持对所有 Microsoft SQL Server Reporting Services 目录项进行脚本编写和传输,以帮助将它们从一台服务器传输到另一台服务器。它还可用于轻松地将大量项目从一个 Reporting Services 文件夹移动到同一服务器上的另一个文件夹。根据所选的脚本选项,Reporting Services Scripter 还可以传输所有目录项属性,例如描述、历史记录选项、执行选项(包括报告特定和共享计划)、订阅(正常和数据驱动)和服务器端报告参数。
我知道您说您不赞成 Business Development Studio 执行此操作,但我发现内置工具非常可靠且易于使用。
您是否研究过任何持续集成解决方案,例如 CruiseControl.NET?如果您能够使用 rs.exe 部署报告,那么您可以在 CruiseControl 中设置一个自动化流程,以便在计时器或修改报告时构建和部署您的报告。
在我们的环境中,我们在带有版本控制的 VS 中进行开发,然后部署到 DEV SSRS。验证报告后,我们使用 ReportSync 程序将报告从 部署ReportServer DEV
到ReportServer PROD
. RS.EXE 脚本仍然占有一席之地,但我发现 ReportSync 是一种更简单、更灵活的报告推广方式。
报告同步:
ReportSync
是一个免费下载和使用的开源程序。它非常适合批量下载报告,甚至可以将报告从一台服务器推送到另一台服务器。
如何获得下载程序?
从 Github 下载源代码文件:Phires/ReportSynch,运行 VS,打开解决方案文件(.SLN),编译程序,从C:\Temp\reportsync-master\bin\Release找到可执行文件(.EXE)文件夹。最后,将 .EXE 保存在某个地方供您定期使用
如果我不是报告的所有者,如何将 SSRS 报告复制到新服务器--> nunespascal 的 ReportSync 回答
如何部署报告?
- 运行可执行文件,界面将启动。
- 使用
SOURCE
和DESTINATION
对话选择single report
、multiple reports
或entire folder of reports
。您可以选择任何您想要的目标文件夹。(提示:如果您想在同一台服务器上复制报告,您甚至可以针对同一台服务器。) - 做出选择后,按
Sync button
- 转到目标服务器,并通过查看 Changed By Date 来验证更改是否生效。
这个工具非常方便,但我注意到了一些怪癖。例如when I want to update just one report that already exists in the destination
,这里是我必须选择的——[ Source:Report> Target:Folder> Sync
]。警告:您可能认为您会选择目标服务器报告来更新它,但我已经尝试过了,但报告没有得到更新。
ReportSync 还能做什么?
还有一个
Export
功能,它非常适合简单地将所有 RDL 文件转储到一个文件夹中供我访问。如果您需要迁移服务器、将文件添加到 VS 解决方案项目或对所有文件执行其他任何操作,这将很有帮助。在我的测试中,该程序不会迁移其他内容——订阅、共享数据源、共享数据集。它仅适用于报告文件。
我知道这篇文章很旧,但我在研究 RS.EXE 脚本时遇到了它,所以我想我会回答这个问题。