Pergunta

Eu preciso criar um processo repetível para implantar relatórios SQL Server Reporting Services. Eu não sou a favor do uso de Negócios Development Studio Visual Studio e ou para fazer isso. O método RS.exe das implantações de script também parece um pouco desajeitado. Alguém tem uma maneira muito elegante que eles têm sido capazes de implantar relatórios. A chave aqui é que eu quero que o processo seja totalmente automatizado.

Foi útil?

Solução

Nós usamos RS.exe, uma vez que desenvolveu o roteiro que não precisava tocá-lo mais, ele simplesmente funciona.

Aqui está a fonte (I ligeiramente modificado-lo à mão para remover os dados sensíveis, sem a chance de testá-lo, espero que eu não fiz nada de freio), que implanta relatórios e imagens associadas de subdiretórios para várias línguas. Também é criado fonte de dados.

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

Aqui está o lote para chamar 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

Outras dicas

Eu usei o script @ David fornecido, mas eu tive que adicionar algum código ( Eu estou escrevendo isso como uma resposta, pois isso seria muito tempo para um comentário.

O problema é: se já existe uma "fonte de dados compartilhada" anexado a um relatório na definição do relatório, este nunca é a mesma fonte de dados como o que é criado no script.

Isso também torna-se evidente a partir do aviso emitido pelo método "CreateReport":

O conjunto de dados '' refere-se à fonte de dados compartilhada '', que não é publicado no servidor de relatório.

Assim, a fonte de dados tem de ser definido de forma explícita depois. Eu fiz as mudanças o seguinte código:

Eu adicionei uma variável global:

Dim dataSourceRefs(0) As DataSource

No final do método CreateDataSource, essa variável é preenchido:

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 no método PublishReport, essa fonte de dados fica explicitamente definido (após CreateReport foi chamado):

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

Note que esta última chamada é de apenas RS 2005 ou superior. Se você deseja carregar seus relatórios em um RS Server 2000, você tem que usar Set Relatório DataSources em lugar;

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

Bem, não realmente elegante. Nós criamos nossa própria ferramenta que utiliza o serviço reportingservices2005 web. Descobrimos que isso seja a forma mais confiável de conseguir o que queremos.

Não é realmente tão difícil e permite que você expandi-lo para fazer outras coisas como a criação de fontes e pastas de dados, conforme necessário.

Eu recomendo fortemente RSScripter . Como observado na visão geral:

Reporting Services Scripter é um .NET aplicativo que permite que o Windows Forms scripting e transferência da totalidade Relatórios Microsoft SQL Server Catálogo dos serviços itens para ajudar na transferi-los de um servidor para outro. Ele também pode ser usado para facilmente mover itens em massa de um Relatório Serviços de pasta para outra na mesma servidor. Dependendo do scripting opções escolhidas, o Reporting Services Scripter também pode transferir todo o catálogo propriedades de itens, tais como, Descrições opções de história, opções de Execução (Incluindo específica relatório e compartilhados horários), as assinaturas (normais e relatório de dados driven) e do lado do servidor parâmetros.

Eu sei que você diz que você não é a favor do Estúdio de Desenvolvimento de Negócios para fazer isso, mas eu encontrei o built-in ferramentas para ser muito confiável e fácil de usar.

Você já olhou para todas as soluções de integração contínua como CruiseControl.NET? Se você é capaz de implantar relatórios usando RS.exe então você pode configurar um processo automatizado em CruiseControl para construir e implantar seus relatórios sobre um temporizador ou sempre que um relatório é modificado.

Em nosso ambiente, desenvolvemos em VS com controle de versão, em seguida, implantar a DEV SSRS. Uma vez que o relatório é validado, usamos programa ReportSync para implantar relatórios de ReportServer DEV para ReportServer PROD. Os scripts RS.exe ainda têm o seu lugar, mas eu descobri ReportSync ser uma maneira muito mais simples e ágil para promover um relatório.

ReportSync:

ReportSync é um programa de fonte aberta livre para download e uso. Funciona muito bem para fazer o download de relatórios em massa, e pode até mesmo empurrar um relatório de um servidor para outro servidor.


Como chegar baixar o programa?

Como implantar um relatório?

  1. Execute o executável ea interface será iniciado.
  2. Use as SOURCE e DESTINATION diálogos escolher um single report, multiple reports, ou um entire folder of reports. Você pode qualquer destino de pasta que você gostaria. (DICA:. Você pode até mesmo atingir o mesmo servidor se você está querendo duplicar um relatório sobre o mesmo servidor)
  3. Após fazer suas seleções, pressione o Sync button
  4. Vá para o servidor de destino, e validar a alteração entrou em vigor, revendo a Alteração por Data.

Esta ferramenta tem sido muito conveniente, mas tenho notado algumas peculiaridades. Por exemplo when I want to update just one report that already exists in the destination, aqui é o que tenho a selecione-- [Source:Report> Target:Folder> Sync]. AVISO: Você pode pensar que você selecione o relatório servidor de destino para atualizá-lo, mas eu tentei isso e o relatório não é atualizado.


O que mais pode ReportSync fazer?

  • Há também um recurso Export, que funciona maravilhosamente para simplesmente despejar todos os arquivos RDL para uma pasta para mim acesso. Isso é útil no caso de você precisar migrar o servidor, adicionar os arquivos para um projeto da solução VS, ou fazer qualquer outra coisa Será que todos os arquivos.

  • Em meus testes este programa não Migrar outras assinaturas content--, fontes de dados compartilhadas, conjuntos de dados compartilhados. É apenas aplicável aos arquivos de relatório.

Eu sei que este post é antigo, mas me deparei com ele quando pesquisando roteiros RS.exe, então eu pensei que eu iria dar uma resposta a esta pergunta.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top