我需要创建一个可重复的过程来部署SQL Server Reporting Services报告.我不赞成使用Visual Studio和/或Business Development Studio来执行此操作.脚本部署的rs.exe方法似乎也相当笨重.有没有人能够以非常优雅的方式部署报告.这里的关键是我希望这个过程完全自动化.
我们使用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)