Most of the time, it’s acceptable for customers to deploy a report manually via Visual Studio, Report Manager, or maybe by using an rss script.
Last month I bumped into an organization that had a hard and fast rule that “anything deployable” (Winform apps, Webform apps, SSRS reports, etc.) had to be deployed via an MSI.
So, I put together a little proof of concept showing them how. The sample basically displays some “setup ui” to collect information like where the data source for the report should be created and what it’s name should be, and the username and password that should be used in the data source. Making all this information “dynamic” was important because one often publishes a report and its data source to a different location on a production box than on the machine it was originally created on…your database server name (and even the name of the database) might be different, too
The setup UI runs in the context of a VS deployment package. Once the setup information has been collected, the deployment package launches a custom action. The custom action is nothing more than code which leverages the Reporting Services SOAP APIs to publish the report and data source.
After you have downloaded and unzipped the files, open the PublishReportMSI solution, and enjoy this little walkthrough:
1. Open the PublishReportProject project: this sucker is the Setup Project that we use to invoke a Custom Action that does all the real work of publishing a report and fixing up its data source.
2. Right-click PublishReportProject and choose View | File System. You’ll see a new folder in this list called “TempFolder”, and it contains SampleReport.rdl. SampleReport.Rdl is a report which uses a Data Source called “MyOlap”, and MyOlap hits a cube inside a database named MySSAS. Needless to say, even once you get this thing published on your server, the report itself won’t work since you don’t have my back-end stuff…Sorry!
3. Choose View | User Interface. Under Start, you’ll see where I added 2 Textbox forms to gather information from the user. If you look at the properties of each form, you’ll see that each Label (Like “Data Source Location”) has an associated Property name(“DSL”) and a Default Value (“/Data Sources”). We’ll use the Property values later on…Also notice how I didn’t hash out the username / password…a bad idea, but I’m in a hurry.
4. Choose View | Custom Actions, and you’ll see how we launch the Custom Action which does the real work. Note the Install folder and how it contains ClassLibrary1.dll. ClassLibrary1 contains all the SSRS web service API logic that publishes our report and data source. Right-click ClassLibrary1.dll and choose Properties.
5. Eyeball the CustomActionData property. This is how we “feed” all of the information that we collected in our user interface to the class library. You’ll see the same thing over and over again here: /PropertyName = [PropertyName] , Basically, /PropertyName represents a variable in the class library (which we haven’t looked at yet), and we set this value with = [PropertyName]. [PropertyName] is the value we specified in the Edit?Property property back in the User Interface area.
I found this part to be the trickiest thing I had to play around with…just be patient or search MSDN about how CustomActionData works.
OK…so you now should see how we:
· Copy a report (in this case SampleReport.rdl) to a temp folder on the machine that the MSI gets run on
· Collect information from the user about where to publish this report
· Push the user-provided info to a custom action which lives inside a Class Library
Next, let’s look at the Class Library itself. Open The ClassLibrary1 project, double-click Class1.cs and switch to code view.
1. First, check the web references for this project…note anything familiar? We’re just leveraging the 2005 SSRS Management endpoint…no big deal.
2. OK, check out the code next. I was lazy, so a lot of this stuff could be made more dynamic…I didn’t bother though. In the Install() method, we begin by assigning all those values we collected in the MSI UI to local variables.
3. Next, we authenticate against the web service and create a folder in SSRS called “MSI Report Demo”. We’ll be dropping our report here later on.
4. After that, it’s time to read the definition of SampleReport.rdl (which our MSI has already dumped in c:\temp). We plug the definition into an array of bytes called reportDefinition.
5. Then, we create the report with a call to CreateReport()…again, note the hardcoded values…yuk!
6. The next thing to do is re-create the data source that the report will depend on. We do so largely using the values we collected from the user earlier on. Calling CreateDataSource() pushes the data source out to the SSRS instance.
Warning: When you play with this, make sure you are regularly cleaning up (deleting) the /MSI Report Demo folder & report, AND the data source from your SSRS instance BEFORE you run the MSI..if you forget, we’ll throw an exception because I didn’t bother to handle scenarios where this stuff already exists on the server…that’s what you get for trying to use free code.
7. After the data source has been created, we have to circle back to our recently published report and “fix up” its data source reference so the report “knows” where its data source is…Note the hard coded values.
8. Finally, we make a feeble attempt to clean up by deleting the Sample Report from the file system.
I assume you will probably want to get “your” version of the publisher working as quickly as possible…Here’s what you need to do:
1. Replace the strings “SampleReport” or “SampleReport.RDL” with “YourReportName” and “YourReportName.RDL” on lines 44, 47, 88, 91, 97 of Class1.cs and anywhere else you happen to see them show up J
2. Back in the Deployment Project, delete my SampleReport.rdl as a resource.
3. Right-click the setup project and select View | System, then Add your RDL doc to the TempFolder (Right-click TempFolder, choose Add).
5. You should be ready to install now…This worked for me every time I tried it, but of course your mileage may vary depending on what you try to publish. I suggest you start simple, then get more daring J
Also remember that when you run the MSI, you are essentially installing an application. If setup completes with no errors, don’t forget to right-click the setup project in Solution Explorer and choose Uninstall before you try and run the MSI again…