Distribuzione di Reporting Services
-
01-07-2019 - |
Domanda
È necessario creare un processo ripetibile per la distribuzione dei report di SQL Server Reporting Services.Non sono favorevole all'utilizzo di Visual Studio e/o Business Development Studio per eseguire questa operazione.Anche il metodo rs.exe per eseguire lo scripting delle distribuzioni sembra piuttosto goffo.Qualcuno ha un modo molto elegante per distribuire i report.La chiave qui è che voglio che il processo sia completamente automatizzato.
Soluzione
Usiamo rs.exe, una volta sviluppato lo script non abbiamo più avuto bisogno di toccarlo, funziona e basta.
Ecco il sorgente (l'ho leggermente modificato a mano per rimuovere i dati sensibili senza possibilità di testarlo, spero di non aver interrotto nulla), distribuisce report e immagini associate da sottodirectory per varie lingue.Viene creata anche l'origine dati.
'=====================================================================
' 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
Ecco il batch per chiamare 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
Altri suggerimenti
Ho usato la sceneggiatura @Davide fornito ma ho dovuto aggiungere del codice (lo scrivo come risposta, poiché sarebbe troppo lungo per un commento.
Il problema è:se è già presente un'"origine dati condivisa" allegata a un report nella definizione del report, questa non sarà mai la stessa origine dati creata nello script.
Ciò risulta evidente anche dall'avviso emesso dal metodo "CreateReport":
Il set di dati '' fa riferimento all'origine dati condivisa '', che non è pubblicata nel server di report.
Quindi l'origine dati deve essere impostata esplicitamente in seguito.Ho apportato le seguenti modifiche al codice:
Ho aggiunto una variabile globale:
Dim dataSourceRefs(0) As DataSource
Alla fine del metodo CreateDataSource, quella variabile viene riempita:
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
E nel metodo PublishReport, l'origine dati viene impostata esplicitamente (dopo che è stato chiamato CreateReport):
rs.SetItemDataSources(targetFolder + "/" + reportName.Substring(0, reportName.Length - 4), dataSourceRefs)
Tieni presente che quest'ultima chiamata è solo RS 2005 o successiva.Se vuoi caricare i tuoi report su un server RS 2000, devi utilizzare SetRapportoDataSource invece:
rs.SetReportDataSources(targetFolder + "/" + reportName.Substring(0, reportName.Length - 4), dataSourceRefs)
Beh, non proprio elegante.Abbiamo creato il nostro strumento che utilizza il servizio web reportingservices2005.Abbiamo scoperto che questo è il modo più affidabile per ottenere ciò che vogliamo.
Non è poi così difficile e ti consente di espanderlo per fare altre cose come creare origini dati e cartelle secondo necessità.
raccomando fortemente RSScripter.Come notato nella panoramica:
Scripter Servizi di reporting è un'applicazione .NET Windows Forms che consente lo scripting e il trasferimento di tutti gli elementi del catalogo dei servizi di reporting SQL di Microsoft SQL per aiutare a trasferrli da un server a un altro.Può anche essere utilizzato per spostare facilmente gli articoli su massa da una cartella dei servizi di reporting all'altra sullo stesso server.A seconda delle opzioni di script scelte, lo scripter dei servizi di reporting può anche trasferire tutte le proprietà degli elementi del catalogo come descrizioni, opzioni di cronologia, opzioni di esecuzione (inclusi i programmi specifici del report e condiviso), abbonamenti (normali e guidati dai dati) e parametri di report lato server.
So che dici di non essere favorevole all'utilizzo di Business Development Studio, ma ho trovato gli strumenti integrati molto affidabili e facili da usare.
Hai esaminato eventuali soluzioni di integrazione continua come CruiseControl.NET?Se sei in grado di distribuire report utilizzando rs.exe, puoi impostare un processo automatizzato in CruiseControl per creare e distribuire i tuoi report in base a un timer o ogni volta che un report viene modificato.
Nel nostro ambiente, sviluppiamo in VS con controllo della versione, quindi distribuiamo in DEV SSRS.Una volta convalidato il report, utilizziamo il programma ReportSync da cui distribuire i report ReportServer DEV
A ReportServer PROD
.Gli script RS.EXE hanno ancora il loro posto, ma ho trovato ReportSync un modo molto più semplice e agile per promuovere un report.
ReportSync:
ReportSync
è un programma open source da scaricare e utilizzare gratuitamente.Funziona benissimo per scaricare report in blocco e può persino inviare un report da un server a un altro server.
Come scaricare il programma?
Scarica i file del codice sorgente da Github:Phires/ReportSynch, Eseguire VS, aprire il file della soluzione (.SLN), compilare il programma, trovare il file eseguibile (.EXE) dal C: emp eportsync-master\bin elease cartella.Infine, salva il file .EXE da qualche parte per poterlo utilizzare regolarmente
Come posso copiare i report SSRS su un nuovo server se non sono il proprietario dei report --> Risposta ReportSync di nunespascal
Come distribuire un rapporto?
- Esegui l'eseguibile e l'interfaccia verrà avviata.
- Usa il
SOURCE
EDESTINATION
dialoghi per scegliere asingle report
,multiple reports
, o unentire folder of reports
.Puoi scegliere qualsiasi cartella di destinazione che desideri.(SUGGERIMENTO:Puoi anche scegliere come target lo stesso server se desideri duplicare un report sullo stesso server.) - Dopo aver effettuato le selezioni, premere il pulsante
Sync button
- Vai al server di destinazione e verifica che la modifica abbia avuto effetto esaminando la data di modifica.
Questo strumento è stato molto conveniente, ma ho notato alcune stranezze.Per esempio when I want to update just one report that already exists in the destination
, ecco cosa devo selezionare-- [Source:Report> Target:Folder> Sync
].AVVERTIMENTO:Potresti pensare di selezionare il report del server di destinazione per aggiornarlo, ma ho provato questo e il report non viene aggiornato.
Cos'altro può fare ReportSync?
C'è anche un
Export
funzionalità, che funziona meravigliosamente semplicemente per scaricare tutti i file RDL in una cartella a cui posso accedere.Ciò è utile nel caso in cui sia necessario migrare il server, aggiungere i file a un progetto di soluzione VS o fare qualsiasi altra cosa con tutti i file.Durante il mio test di questo programma non migrare altri contenuti: abbonamenti, origini dati condivise, set di dati condivisi.È applicabile solo ai file di report.
So che questo post è vecchio, ma l'ho trovato durante la ricerca degli script RS.EXE, quindi ho pensato di fornire una risposta a questa domanda.