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.

È stato utile?

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?

Come distribuire un rapporto?

  1. Esegui l'eseguibile e l'interfaccia verrà avviata.
  2. Usa il SOURCE E DESTINATION dialoghi per scegliere a single report, multiple reports, o un entire 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.)
  3. Dopo aver effettuato le selezioni, premere il pulsante Sync button
  4. 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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top