I was looking for a way to deploy reports on the production server without going through the Report Manager and deploying one report at a time.  Then I stumbled upon RS.EXE, a scripting hosting utility that uses VB.NET script.  With VB.NET script you can deploy all your reports.

But how do you deploy SSRS reports in VB.NET?  Instead of creating one from scratch I searched the Internet and found one from John Desch’s blog Using the RS.EXE utility to deploy a Report Server Project and Shared Dataset.  It was said to be one of the best automated script available but one of the problems with the script is it does not support 2008SP1 which I need it to.

Good thing I found another script based on John Desch’s script but with enhancements including support for 2008SP1.  I found the script from Nishar’s blog SSRS Deployment–Complete Automation–2012 & 2008

I slightly modified the Commonscript.rss file for my own purposes.

‘Begin Script

Dim definition As [Byte]() = Nothing

Dim bytedefinition As [Byte]() = Nothing

Dim warnings As Warning() = Nothing

‘Main Entry point of utility

Public Sub Main()

Console.WriteLine()  
  
Console.WriteLine("Initiating Deployment")  
  
rs.Credentials = System.Net.CredentialCache.DefaultCredentials  
  
Try  
  
    'Create the shared data source  
  
    CreateFolders(DataSourceFolderName, "/", "", "Visible")  
  
    'Create the folder that will contain the shared data sets  
  
    'CreateFolders(DataSetFolderName, "/", "", "Visible")  
  
    'Create the folder that will contain the deployed reports  
  
    CreateFolders(ReportFolderName, "/", "", "Visible")  
  
Catch goof As Exception  
  
    Console.WriteLine(goof.Message)  
  
End Try  
  
ReadFiles(ReportSourcePath, "*.rds")  
  
'ReadFiles(ReportSourcePath, "*.rsd")  
  
ReadFiles(ReportSourcePath, "*.rdl")  
  
'Publish the report  
  
'PublishReport(ReportName)  
  
'UpdateDataSources(ReportFolderName, DataSourcePath)  

End Sub

‘Utility for creation of folders

Public Sub CreateFolders(ByVal folderName As String, ByVal parentPath As String, ByVal description As String, ByVal visible As String)

Console.WriteLine()  
  
Console.WriteLine("Checking for Target Folders")  
  
'CatalogItem properties  
  
Dim descriptionProp As New \[Property\]  
  
descriptionProp.Name = "Description"  
  
descriptionProp.Value = description  
  
Dim visibleProp As New \[Property\]  
  
visibleProp.Name = "Visible"  
  
visibleProp.value = visible  
  
Dim props(1) As \[Property\]  
  
props(0) = descriptionProp  
  
props(1) = visibleProp  
  
Try  
  
    rs.CreateFolder(folderName, parentPath, props)  
  
    Console.WriteLine("Folder {0} successfully created", foldername)  
  
Catch goof As SoapException  
  
    If goof.Message.Indexof("AlreadyExists") > 0 Then  
  
        Console.WriteLine("Folder {0} already exists", foldername)  
  
    End If  
  
End Try  

End Sub

‘Utility for reading files from the Report Sevices Project

Public Sub ReadFiles(filepath As String, fileextension As String)

Console.WriteLine()  
  
Console.WriteLine("Reading Files from Report Services Project")  
  
Dim rptdirinfo As System.IO.DirectoryInfo  
  
rptdirinfo = New System.IO.DirectoryInfo(filepath)  
  
Dim filedoc As FileInfo()  
  
filedoc = rptdirinfo.GetFiles(fileextension)  
  
Try  
  
    For rptcount As Integer = 0 To filedoc.Length - 1  
  
        If Not filedoc(rptcount).Name.ToString.Trim.ToUpper.Contains("BACKUP") Then  
  
            Select Case fileextension  
  
                Case "*.rds"  
  
                    CreateDataSource(filedoc(rptcount).tostring.trim)  
  
                Case "*.rsd"  
  
                    CreateDataSet(filedoc(rptcount).tostring.trim)  
  
                Case "*.rdl"  
  
                    PublishReport(filedoc(rptcount).tostring.trim)  
  
            End Select  
  
        End If  
  
    Next  
  
Catch goof As Exception  
  
    Console.WriteLine("In ReadFiles " + goof.message)  
  
End Try  

End Sub

‘Utility for Creating Shared Data Sets contained in the project

Public Sub CreateDataSet(ByVal filename As String)

Dim valstart As Integer  
  
Dim valend As Integer  
  
Dim DSDefinitionStr As String  
  
Dim DataSourceName As String  
  
Dim QueryString As String  
  
Try  
  
    Dim stream As FileStream = File.OpenRead(ReportSourcePath + "\\" + filename)  
  
    definition = New \[Byte\](stream.Length - 1) {}  
  
    stream.Read(definition, 0, CInt(stream.Length))  
  
    stream.Close()  
  
    For i As Integer = 0 To definition.Length - 1  
  
        DSDefinitionStr = DSDefinitionStr + Convert.ToString(Convert.ToChar(Convert.ToInt16(definition(i).ToString)))  
  
    Next  
  
    valstart = DSDefinitionStr.ToString.Indexof("<DataSourceReference>")  
  
    If valstart > 0 Then  
  
        valstart = DSDefinitionStr.ToString.IndexOf("<DataSourceReference>") + 21  
  
        valend = DSDefinitionStr.ToString.IndexOf("</DataSourceReference>")  
  
        DataSourceName = DSDefinitionStr.ToString.Substring(valstart, valend - valstart)  
  
        Console.WriteLine(DataSourceName)  
  
    End If  
  
Catch e As IOException  
  
    Console.WriteLine(e.Message)  
  
End Try  
  
filename = filename.tostring.replace(".rsd", "")  
  
Console.WriteLine("Attempting to Deploy DataSet {0}", filename)  
  
Try  
  
    Dim item As CatalogItem  
  
    item = rs.CreateCatalogItem("DataSet", filename, "/" + DataSetFolderName, True, definition, Nothing, warnings)  
  
    If Not (warnings Is Nothing) Then  
  
        Dim warning As Warning  
  
        For Each warning In warnings  
  
            If warning.message.tostring.tolower.contains("refers to the shared data source") Then  
  
                Console.WriteLine("Connecting DataSet {0} to Data Source {1}", filename, DataSourceName)  
  
                Dim referenceData() As ItemReferenceData = rs.GetItemReferences("/" + DataSetFolderName + "/" + filename, "DataSet")  
  
                Dim references(0) As ItemReference  
  
                Dim reference As New ItemReference()  
  
                Dim datasourceURL = "/" + DataSourcePath + "/" + DataSourceName  
  
                reference.name = referenceData(0).Name  
  
                Console.WriteLine("Reference name = " + reference.name)  
  
                reference.Reference = datasourceURL  
  
                references(0) = reference  
  
                rs.SetItemReferences("/" + DataSetFolderName + "/" + filename, references)  
  
            Else  
  
                Console.WriteLine(warning.Message)  
  
            End If  
  
        Next warning  
  
    Else  
  
        Console.WriteLine("DataSet: {0} published successfully with no warnings", filename)  
  
    End If  
  
Catch goof As SoapException  
  
    If goof.Message.Indexof("AlreadyExists") > 0 Then  
  
        Console.WriteLine("The DataSet {0} already exists", fileName.ToString)  
  
    Else  
  
        If goof.Message.IndexOf("published") = -1 Then  
  
            Console.Writeline(goof.Message)  
  
        End If  
  
    End If  
  
End Try  
  
'UpdateDataSetSources(filename,DataSetFolderName, DataSourceFolderName,DataSourceName)  

End Sub

‘Utility for creating Data Sources on the Server

Public Sub CreateDataSource(filename As String)

'Define the data source definition.  
  
Dim dsDefinition As New DataSourceDefinition()  
  
Dim DataSourceName As String  
  
Dim valstart As Integer  
  
Dim valend As Integer  
  
Dim ConnectionString As String  
  
Dim Extension As String  
  
Dim IntegratedSec As String  
  
Dim DataSourceID As String  
  
Dim PromptStr As String  
  
PromptStr = ""  
  
Dim DSDefinitionStr As String  
  
DSDefinitionStr = ""  
  
DataSourceName = filename.tostring.trim.substring(0, filename.tostring.trim.length - 4)  
  
Console.WriteLine("Attempting to Deploy Data Source {0}", DataSourceName)  
  
Try  
  
    Dim stream As FileStream = File.OpenRead(ReportSourcePath + "\\" + filename)  
  
    bytedefinition = New \[Byte\](stream.Length - 1) {}  
  
    stream.Read(bytedefinition, 0, CInt(stream.Length))  
  
    stream.Close()  
  
    For i As Integer = 0 To bytedefinition.Length - 1  
  
        DSDefinitionStr = DSDefinitionStr + Convert.ToString(Convert.ToChar(Convert.ToInt16(bytedefinition(i).ToString)))  
  
    Next  
  
Catch goof As IOException  
  
    Console.WriteLine(goof.Message)  
  
End Try  
  
If DSDefinitionStr.ToString.Contains("<ConnectString>") And DSDefinitionStr.ToString.Contains("</ConnectString>") Then  
  
    valstart = DSDefinitionStr.ToString.IndexOf("<ConnectString>") + 15  
  
    valend = DSDefinitionStr.ToString.IndexOf("</ConnectString>")  
  
    ConnectionString = DSDefinitionStr.ToString.Substring(valstart, valend - valstart)  
  
End If  
  
If DSDefinitionStr.ToString.Contains("<Extension>") And DSDefinitionStr.ToString.Contains("</Extension>") Then  
  
    valstart = DSDefinitionStr.ToString.IndexOf("<Extension>") + 11  
  
    valend = DSDefinitionStr.ToString.IndexOf("</Extension>")  
  
    Extension = DSDefinitionStr.ToString.Substring(valstart, valend - valstart)  
  
End If  
  
If DSDefinitionStr.ToString.Contains("<IntegratedSecurity>") And DSDefinitionStr.ToString.Contains("</IntegratedSecurity>") Then  
  
    valstart = DSDefinitionStr.ToString.IndexOf("<IntegratedSecurity>") + 20  
  
    valend = DSDefinitionStr.ToString.IndexOf("</IntegratedSecurity>")  
  
    IntegratedSec = DSDefinitionStr.ToString.Substring(valstart, valend - valstart)  
  
End If  
  
If DSDefinitionStr.ToString.Contains("<DataSourceID>") And DSDefinitionStr.ToString.Contains("</DataSourceID>") Then  
  
    valstart = DSDefinitionStr.ToString.IndexOf("<DataSourceID>") + 14  
  
    valend = DSDefinitionStr.ToString.IndexOf("</DataSourceID>")  
  
    DataSourceID = DSDefinitionStr.ToString.Substring(valstart, valend - valstart)  
  
End If  
  
If DSDefinitionStr.ToString.Contains("<Prompt>") And DSDefinitionStr.ToString.Contains("</Prompt>") Then  
  
    valstart = DSDefinitionStr.ToString.IndexOf("<Prompt>") + 8  
  
    valend = DSDefinitionStr.ToString.IndexOf("</Prompt>")  
  
    PromptStr = DSDefinitionStr.ToString.Substring(valstart, valend - valstart)  
  
End If  
  
dsdefinition.CredentialRetrieval = CredentialRetrievalEnum.Integrated  
  
dsdefinition.ConnectString = ConnectionString  
  
dsdefinition.Enabled = True  
  
dsdefinition.EnabledSpecified = True  
  
dsdefinition.Extension = extension  
  
dsdefinition.ImpersonateUser = False  
  
dsdefinition.ImpersonateUserSpecified = True  
  
'Use the default prompt string.  
  
If PromptStr.ToString.Length = 0 Then  
  
    dsdefinition.Prompt = Nothing  
  
Else  
  
    dsdefinition.Prompt = PromptStr  
  
End If  
  
dsdefinition.WindowsCredentials = False  
  
Try  
  
    rs.CreateDataSource(DataSourceName, "/" + DataSourceFolderName, False, dsdefinition, Nothing)  
  
    Console.WriteLine("Data source {0} created successfully", DataSourceName.ToString)  
  
Catch goof As SoapException  
  
    If goof.Message.Indexof("AlreadyExists") > 0 Then  
  
        Console.WriteLine("The Data Source name {0} already exists", DataSourceName.ToString)  
  
    End If  
  
End Try  

End Sub

‘Utility to Publish the Reports

Public Sub PublishReport(ByVal reportName As String)

Try  
  
    Dim stream As FileStream = File.OpenRead(ReportSourcePath + "\\" + reportName)  
  
    definition = New \[Byte\](stream.Length - 1) {}  
  
    stream.Read(definition, 0, CInt(stream.Length))  
  
    stream.Close()  
  
Catch e As IOException  
  
    Console.WriteLine(e.Message)  
  
End Try  
  
reportname = reportname.tostring.replace(".rdl", "")  
  
Console.WriteLine("Attempting to Deploy Report Name {0}", reportname.tostring)  
  
Dim item As CatalogItem  
  
  
Try  
  
    item = rs.CreateCatalogItem("Report", reportname, "/" + ReportFolderName, True, definition, Nothing, warnings)  
  
    'warnings = rs.CreateCatalogItem(reportName, "/" + ReportFolderName, False, definition, Nothing)  
  
    If Not (warnings Is Nothing) Then  
  
        If item.Name <> "" Then  
  
            Console.WriteLine("Report: {0} published successfully with warnings", reportName)  
            UpdateDataSources_report(reportName)  
            UpdateDataSet_report(reportName)  
        Else  
  
            Dim warning As Warning  
  
            For Each warning In warnings  
  
                Console.WriteLine(warning.Message)  
  
            Next warning  
  
        End If  
  
    Else  
  
        Console.WriteLine("Report: {0} published successfully with no warnings", reportName)  
        UpdateDataSources_report(reportName)  
        UpdateDataSet_report(reportName)  
    End If  
  
Catch goof As SoapException  
  
    If goof.Message.Indexof("AlreadyExists") > 0 Then  
  
        Console.WriteLine("The Report Name {0} already exists", reportName.ToString)  
  
    Else  
  
        If goof.Message.IndexOf("published") = -1 Then  
  
            Console.WriteLine(goof.Message)  
  
        End If  
  
    End If  
  
End Try  

End Sub

‘Utility to Update The Data Sources on the Server

Public Sub UpdateDataSources(ReportFolderName As String, DataSourcePath As String)

rs.Credentials = System.Net.CredentialCache.DefaultCredentials  
  
Dim item As CatalogItem  
  
Dim items As CatalogItem()  
  
Try  
  
  
  
    items = rs.ListChildren("/" + ReportFolderName, False)  
  
    For Each item In items  
  
        'Console.WriteLine("          update date source called     --------"+ item.Path + " -----------")  
  
        If item.path.Indexof("rdl") > 0 And ReportName = "" Then  
  
            'Console.WriteLine("          update date source called     --------"+ item.path.Indexof("rdl").tostring() + " -----------")  
  
            Dim dataSources() As DataSource = rs.GetItemDataSources(item.Path)  
  
            For Each ds As DataSource In dataSources  
  
                Dim sharedDs(0) As DataSource  
  
                sharedDs(0) = GetDataSource(DataSourcePath, ds.Name)  
  
                rs.SetItemDataSources(item.Path, sharedDs)  
  
                Console.WriteLine("Set " & ds.Name & " datasource for " & item.Path & " report")  
  
                'end if  
            Next  
  
        End If  
  
    Next  
  
    If ReportName = "" Then  
  
        Console.WriteLine("Shared data source reference set for reports in the {0} folder.", ReportFolderName)  
  
    End If  
  
  
    If ReportName <> "" Then  
  
        '    Console.WriteLine("               " + "/" + ReportFolderName + "/" + ReportName + "  ------------- second  update called        ---------------------- ")  
  
        Dim dataSources() As DataSource = rs.GetItemDataSources("/" + ReportFolderName + "/" + ReportName)  
  
        For Each ds As DataSource In dataSources  
  
            Dim sharedDs(0) As DataSource  
  
            sharedDs(0) = GetDataSource(DataSourcePath, ds.Name)  
  
            rs.SetItemDataSources("/" + ReportFolderName + "/" + ReportName, sharedDs)  
  
            Console.WriteLine("Set " & ds.Name & " datasource for " & "/" + ReportFolderName + "/" + ReportName & " report")  
  
            'end if  
        Next  
  
        Console.WriteLine("All the shared data source reference set for report {0} ", "/" + ReportFolderName + "/" + ReportName)  
  
    End If  
  
Catch goof As SoapException  
  
    Console.WriteLine(goof.Detail.InnerXml.ToString())  
  
End Try  

End Sub

‘Utility to Update The Data Sources on the Server

Public Sub UpdateDataSources_report(ReportName As String)

rs.Credentials = System.Net.CredentialCache.DefaultCredentials  
  
Dim item As CatalogItem  
  
Dim items As CatalogItem()  
  
Try  
  
    'If ReportName <> "" then  
  
    '    Console.WriteLine("               " + "/" + ReportFolderName + "/" + ReportName + "  ------------- second  update called        ---------------------- ")  
  
    Dim dataSources() As DataSource = rs.GetItemDataSources("/" + ReportFolderName + "/" + ReportName)  
  
    For Each ds As DataSource In dataSources  
  
        Dim sharedDs(0) As DataSource  
  
        sharedDs(0) = GetDataSource(DataSourcePath, ds.Name)  
  
        rs.SetItemDataSources("/" + ReportFolderName + "/" + ReportName, sharedDs)  
  
        Console.WriteLine("Set " & ds.Name & " datasource for " & "/" + ReportFolderName + "/" + ReportName & " report")  
  
        'end if  
    Next  
  
    Console.WriteLine("All the shared data source reference set for report {0} ", "/" + ReportFolderName + "/" + ReportName)  
  
    'end if      
  
  
Catch goof As SoapException  
  
    Console.WriteLine(goof.Detail.InnerXml.ToString())  
  
End Try  

End Sub

‘Utility to link The Dataset with the Report

Public Sub UpdateDataSet_report(ReportName As String)

rs.Credentials = System.Net.CredentialCache.DefaultCredentials  
  
  
Try  
  
    Dim dataSets As ItemReferenceData() = rs.GetItemReferences("/" + ReportFolderName + "/" + ReportName, "DataSet")  
  
    If dataSets IsNot Nothing AndAlso dataSets.Length > 0 AndAlso Not String.IsNullOrEmpty(dataSets(0).Name) Then  
  
        For i As Integer = 0 To dataSets.Length - 1  
  
            Dim references(0) As ItemReference  
            Dim sharedDataSet = New ItemReference()  
            sharedDataSet.Name = dataSets(i).Name  
            Console.WriteLine("Attempting to Link Dataset {0}", dataSets(i).Name)  
            sharedDataSet.Reference = "/" + DataSetFolderName + "/" + dataSets(i).Name  
            references(0) = sharedDataSet  
            rs.SetItemReferences("/" + ReportFolderName + "/" + ReportName, references)  
            Console.WriteLine("Report " + ReportName + " Linked to data set " + "/" + DataSetFolderName + "/" + Convert.ToString(sharedDataSet.Name))  
        Next  
  
    End If  
  
Catch goof As SoapException  
  
    Console.WriteLine(goof.Detail.InnerXml.ToString())  
  
End Try  

End Sub

‘Function to Reference Data Sources

Private Function GetDataSource(sharedDataSourcePath As String, dataSourceName As String) As DataSource

Dim reference As New DataSourceReference()  
  
Dim ds As New DataSource  
  
reference.Reference = "/" + sharedDataSourcePath & "/" & dataSourceName  
  
ds.Item = CType(reference, DataSourceDefinitionOrReference)  
  
ds.Name = dataSourceName  
  
Console.WriteLine("Attempting to Link Data Source {0}", ds.Name)  
  
GetDataSource = ds  

End Function

I also modified the deploy.bat file as well.

set ServerPath=http://localhost/ReportServer
set DataSourceFolderName=Data Sources
set DataSourcePath=Data Sources
set DataSetFolderName=Datasets
set ReportFolderName=My Reports
set ReportSourcePath=.\My Reports
set ReportName=

rs.exe
-i Commonscript.rss
-s %ServerPath%
-v DataSourceFolderName=”%DataSourceFolderName%”
-v DataSourcePath=”%DataSourcePath%”
-v DataSetFolderName=”%DataSetFolderName%”
-v ReportFolderName=”%ReportFolderName%”
-v ReportSourcePath=”%ReportSourcePath%”
-v ReportName=”%ReportName%”
-e Mgmt2010