Implementación de servicios de informes
-
01-07-2019 - |
Pregunta
Necesito crear un proceso repetible para implementar informes de SQL Server Reporting Services.No estoy a favor de utilizar Visual Studio o Business Development Studio para hacer esto.El método rs.exe para implementar secuencias de comandos también parece bastante complicado.¿Alguien tiene una forma muy elegante de implementar informes?La clave aquí es que quiero que el proceso esté completamente automatizado.
Solución
Usamos rs.exe, una vez que desarrollamos el script ya no necesitamos tocarlo, simplemente funciona.
Aquí está la fuente (la modifiqué ligeramente a mano para eliminar datos confidenciales sin tener la oportunidad de probarlos, espero no haber alterado nada), implementa informes e imágenes asociadas de subdirectorios para varios idiomas.También se crea la fuente 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í está el lote para llamar a 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
Otros consejos
utilicé el guión @David suministrado, pero tuve que agregar algo de código (estoy escribiendo esto como respuesta, ya que sería demasiado largo para un comentario).
El problema es:Si ya existe una "fuente de datos compartida" adjunta a un informe en la definición del informe, esta nunca será la misma fuente de datos que la que se crea en el script.
Esto también se desprende de la advertencia emitida por el método "CreateReport":
El conjunto de datos '' se refiere a la fuente de datos compartida '', que no se publica en el servidor de informes.
Por lo tanto, la fuente de datos debe establecerse explícitamente después.He realizado los siguientes cambios de código:
Agregué una variable global:
Dim dataSourceRefs(0) As DataSource
Al final del método CreateDataSource, esa variable se completa:
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 método PublishReport, esa fuente de datos se establece explícitamente (después de llamar a CreateReport):
rs.SetItemDataSources(targetFolder + "/" + reportName.Substring(0, reportName.Length - 4), dataSourceRefs)
Tenga en cuenta que esta última convocatoria es sólo RS 2005 o superior.Si desea cargar sus informes en un servidor RS 2000, debe utilizar SetInformeFuentes de datos en su lugar:
rs.SetReportDataSources(targetFolder + "/" + reportName.Substring(0, reportName.Length - 4), dataSourceRefs)
Bueno, no muy 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.
En realidad no es tan difícil y le permite expandirlo para hacer otras cosas como crear fuentes de datos y carpetas según sea necesario.
Lo recomiendo RSScripter.Como se indica en la descripción general:
Scripter de servicios de informes es una aplicación de formularios .NET Windows que permite que los scripts y la transferencia de todos los elementos de catálogo de servicios de informes de informes de Microsoft SQL Server lo ayuden a transferirlos de un servidor a otro.También se puede usar para mover fácilmente los elementos en masa de una carpeta de servicios de informes a otra en el mismo servidor.Dependiendo de las opciones de secuencias de comandos elegidas, los servicios de informes de informes también pueden transferir todas las propiedades del elemento del catálogo, como descripciones, opciones de historial, opciones de ejecución (incluidos los programas específicos y compartidos del informe), suscripciones (normales y de datos) y parámetros del informe del lado del servidor.
Sé que dices que no estás a favor de que Business Development Studio haga esto, pero he descubierto que las herramientas integradas son muy confiables y fáciles de usar.
¿Ha investigado alguna solución de integración continua como CruiseControl.NET?Si puede implementar informes usando rs.exe, puede configurar un proceso automatizado en CruiseControl para crear e implementar sus informes en un temporizador o cada vez que se modifica un informe.
En nuestro entorno, desarrollamos en VS con control de versiones y luego implementamos en DEV SSRS.Una vez validado el informe, utilizamos el programa ReportSync para implementar informes desde ReportServer DEV
a ReportServer PROD
.Los scripts RS.EXE todavía tienen su lugar, pero he descubierto que ReportSync es una forma mucho más sencilla y ágil de promocionar un informe.
Sincronización de informes:
ReportSync
es un programa de código abierto que se puede descargar y utilizar de forma gratuita.Funciona muy bien para descargar informes de forma masiva e incluso puede enviar un informe de un servidor a otro.
¿Cómo conseguir descargar el programa?
Descargue los archivos del código fuente desde Github:Phires/ReportSynch, Ejecute VS, abra el archivo de solución (.SLN), compile el programa, busque el archivo ejecutable (.EXE) en C: emp eportsync-master\bin elease carpeta.Finalmente, guardé el .EXE en algún lugar para que puedas usarlo regularmente.
¿Cómo copio informes SSRS a un nuevo servidor si no soy el propietario de los informes? --> Respuesta de ReportSync por nunespascal
¿Cómo implementar un informe?
- Ejecute el ejecutable y se iniciará la interfaz.
- Utilizar el
SOURCE
yDESTINATION
Diálogos para elegir unsingle report
,multiple reports
, o unentire folder of reports
.Puede seleccionar cualquier carpeta de destino que desee.(PISTA:Incluso puede apuntar al mismo servidor si desea duplicar un informe en el mismo servidor). - Después de hacer sus selecciones presione el
Sync button
- Vaya al servidor de destino y valide que el cambio haya entrado en vigor revisando la fecha de cambio.
Esta herramienta ha sido muy útil, pero he notado algunas peculiaridades.Por ejemplo when I want to update just one report that already exists in the destination
, esto es lo que tengo que seleccionar-- [Source:Report> Target:Folder> Sync
].ADVERTENCIA:Podría pensar que seleccionaría el informe del servidor de destino para actualizarlo, pero lo intenté y el informe no se actualiza.
¿Qué más puede hacer ReportSync?
También hay un
Export
característica, que funciona de maravilla simplemente volcando todos los archivos RDL en una carpeta para que yo pueda acceder.Esto es útil en caso de que necesite migrar el servidor, agregar los archivos a un proyecto de solución VS o hacer cualquier otra cosa con todos los archivos.En mis pruebas de este programa no es migre otro contenido: suscripciones, fuentes de datos compartidas, conjuntos de datos compartidos.Solo es aplicable a los archivos de informes.
Sé que esta publicación es antigua, pero la encontré mientras investigaba scripts RS.EXE, así que pensé en responder esta pregunta.