2008-09-17 31 views
32

Necesito crear un proceso repetible para implementar informes de SQL Server Reporting Services. No estoy a favor de usar Visual Studio o Business Development Studio para hacer esto. El método rs.exe de implementaciones de scripting también parece bastante torpe. ¿Alguien tiene una manera muy elegante que han podido implementar informes? La clave aquí es que quiero que el proceso esté completamente automatizado.Despliegue de Reporting Services

Respuesta

32

Utilizamos rs.exe, una vez que desarrollamos el script no hemos necesitado tocarlo más, simplemente funciona.

Aquí está la fuente (la modifiqué ligeramente a mano para eliminar datos confidenciales sin posibilidad de probarla, espero que no haya roto nada), despliega informes e imágenes asociadas desde subdirectorios para varios idiomas. También se crea el origen de datos.

'===================================================================== 
' 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 

Aquí es el proceso por lotes para llamar a la 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

Hola. Estaba intentando usar este script para mis propias implementaciones de servicios de informes. Pregunta .. ¿Cómo organizo la estructura del directorio en mi computadora? ¿Tengo un proyecto vs para cada subdirectorio de informes que quiero? – BigJoe714

+0

Esto no tiene nada que ver con los proyectos de VS. La secuencia de comandos espera una subcarpeta para cada mutación de idioma (por ejemplo, en, de, ver inicio de secuencia de comandos). Cada carpeta de idioma contiene archivos rdl y recursos utilizados (normalmente imágenes utilizadas por los informes). –

+0

Entiendo que este script no tiene nada que ver con los proyectos de VS, pero estoy desarrollando mis informes en Visual Studio, así que me preguntaba cómo organizar la estructura de directorios del proyecto para poder usar este script para implementar los informes en lugar de el método VS – BigJoe714

0

Sé que usted dice que no está a favor del Business Development Studio para hacer esto, pero he encontrado que las herramientas integradas son muy confiables y fáciles de usar.

+2

Oh, yo estoy de acuerdo. El problema es que realmente quiero que la implementación esté completamente automatizada. – Bart

+0

ah. solo lo implementamos en un servidor de prueba y producción, y solo después de que se hayan realizado cambios, entonces el uso de las herramientas incorporadas funciona muy bien para nosotros (afortunados, supongo) – cori

1

Bueno, no es realmente elegante. Creamos nuestra propia herramienta que utiliza el servicio web reportingservices2005. Descubrimos que esta es la forma más confiable de obtener lo que queremos.

No es realmente tan difícil y le permite expandirlo para hacer otras cosas como crear fuentes de datos y carpetas según sea necesario.

0

¿Ha analizado alguna solución de integración continua como CruiseControl.NET? Si puede implementar Informes utilizando rs.exe, puede configurar un proceso automatizado en CruiseControl para compilar e implementar sus Informes en un temporizador o cada vez que se modifique un informe.

1

Recomiendo RSScripter. Como se señaló en el resumen:

Reporting Services Scripter es un .NET Windows Forms aplicación que permite secuencias de comandos y traslado de la totalidad Microsoft SQL Server Reporting Servicios Catálogo de artículos para ayudar en transferirlos de un servidor a otro. También se puede usar fácilmente para mover elementos en masa desde una carpeta de Servicios de Informes a otra en el mismo servidor . En función de las secuencias de comandos opciones elegidas, Reporting Services Scripter también puede transferir todas catálogo propiedades de elementos tales como descripciones, opciones de Historial, opciones de ejecución (incluyendo informe específico y compartido horarios), suscripciones (normales y basada en los datos) y informe del lado del servidor parámetros.

+3

desafortunadamente RSSScript ya no se está actualizando, lo que significa que no admite los objetos más nuevos como conjuntos de datos compartidos ... –

8

que utiliza el guión @David suministran pero tenía que añadir algo de código (estoy escribiendo esto como una respuesta, ya que esto sería demasiado largo para un comentario

El problema es:. Si hay ya es un "origen de datos compartido" adjunto a un informe en la definición del informe, este nunca es el mismo origen de datos que el creado en el script.

Esto también se hace evidente a partir de la advertencia emitida por el método de "CreateReport":

El conjunto de datos '' se refiere al origen de datos compartido '', que no se publicó en el servidor de informes.

Por lo tanto, la fuente de datos debe establecerse explícitamente a continuación. He hecho los siguientes cambios en el código:

he añadido una variable global:

Dim dataSourceRefs(0) As DataSource 

Al final del método CreateDataSource, esa variable se llena:

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 

Y en el PublishReport método, ese origen de datos se establece explícitamente (después de haber llamado a CreateReport):

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

Tenga en cuenta que esta última llamada es solo RS 2005 o superior. Si desea cargar sus informes en un servidor RS 2000, usted tiene que utilizar Conjunto de informe DataSources en lugar:

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

Esperaba que hubiera una forma de arreglar esta referencia antes de llamar a CreateReport, porque quiero que mi script se envíe a estar sin advertencias, pero al menos funciona ahora. –

Cuestiones relacionadas