2008-09-17 151 views
32

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

回答

32

我们使用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 
+0

嗨。我试图将这个脚本用于我自己的报告服务部署。问题..我如何在我的计算机上组织目录结构?我想为每个报告子目录都有一个vs项目吗? – BigJoe714 2009-02-16 14:09:42

+0

这与VS项目无关。该脚本预期每个语言突变的子文件夹(例如,en,de,参见脚本开始)。每个语言文件夹都包含使用的rdl文件和资源(通常是由报告使用的图像)。 – 2009-03-10 13:49:50

0

我知道你说你不赞成业务开发工作室来做这件事,但我发现内置工具非常可靠并且易于使用。

+2

哦,我同意。问题是我真的希望部署完全自动化。 – Bart 2008-09-17 23:40:50

+0

啊。我们只部署到测试和生产服务器,并且只有在更改完成后,才能使用内置工具对我们非常有效(我猜我们很幸运) – cori 2008-09-18 14:49:12

1

那么不是很优雅。我们创建了使用reportingservices2005 Web服务的自己的工具。我们发现这是获得我们想要的最可靠的方式。

这不是那么困难,并且可以让您扩展它来完成其他事情,如根据需要创建数据源和文件夹。

0

您是否研究过任何持续集成解决方案(例如CruiseControl.NET)?如果您能够使用rs.exe部署报告,那么您可以在CruiseControl中设置一个自动化流程,以在计时器上或每当报告被修改时构建和部署您的报告。

1

我强烈建议RSScripter。正如概览指出:

报告服务的编剧是一个.NET Windows窗体应用程序,使 脚本和所有 的Microsoft SQL Server的传递报告 服务目录项 以帮助从一台服务器转移到他们另一个是 。它也可以用于轻松地将 质量上的项目从一个报告 服务文件夹移动到同一台 服务器上的另一个文件夹。根据脚本选择 选项,报告服务 的编剧也可传送所有目录 项目性质,例如描述, 历史选项,执行选项 (包括特定的报告和共享 调度),订阅(正常和 数据驱动)和服务器端报告 参数。

8

我使用的脚本@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的服务器,你必须代替使用套装报告数据源:

rs.SetReportDataSources(targetFolder + "/" + reportName.Substring(0, reportName.Length - 4), dataSourceRefs)