Using Microsoft Report Viewer In PowerShell

In this post I’m going to give a quick example using Microsoft Report Viewer in PowerShell. PowerShell makes is easy enough to slap together a simple report by converting data to HTML and adding some CSS but every now and then you need something a bit more polished. For instance generating a chart and or report in Word format that is ready for distribution or printing, laid out according to page size and orientation with headers, footers, logos etc. HTML doesn’t work that great for this so I did a POC using Microsoft ReportViewer 2012, this should work with the 2015 version as well but I didn’t try it.

I’m not going to dig into creating reports with the report viewer in this post, I’ll be focusing on using it with PowerShell. If you are not familiar with the report viewer you can catchup over here and there are some very good resources and samples on the GotReportViewer website as well. Short version, you design reports using the report designer in Visual Studio, at run time you pass it data and render the report to a file or display it in the report viewer. If you don’t have the report viewer installed you can download it here. The whole solution is in my GitHub repo here but I will be highlighting/explaining some aspects of it as we go along.

Code Highlights
When you design the report you have to assign data sources to it that will provide the report with the fields it will use at design time to author the report and it will also expect the same objects at run time with the populated data. You’ll have to create these in a .NET project, compile it and load the assembly along with the ReportViewer assembly into PowerShell.

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.ReportViewer`.WinForms") 
[System.Reflection.Assembly]::LoadWithPartialName("ReportPOC")

In this solution the data source is the ReportData class in the ReportPOC assembly. When you create the data source collection you have to create a strongly typed collection, in this case a generic List of the data source type.

$data = New-Object "System.Collections.Generic.List[ReportPOC.ReportData]"

Creating the records and adding them to the data source is pretty straight forward.

$item1 = New-Object ReportPOC.ReportData
$item1.ServerName = "Server1"
$item1.CPUAvail = "128"
$item1.CPUUsed = "103"
$data.Add($item1)

Then you create the report viewer instance specify the path to your report file and add the data source.

$rep = New-Object Microsoft.Reporting.WinForms.ReportDataSource
$rep.Name = "ReportDS"
$rep.Value = $data
$rv.LocalReport.ReportPath = "C:\MySource\ReportPOC\POC.rdlc";
$rv.LocalReport.DataSources.Add($rep);

Next you render the report and write the output byte array to a file stream, remember to cast the render result to type [byte[]] or else it won’t work.

[byte[]]$bytes = $rv.LocalReport.Render("WORDOPENXML");
$fs = [System.IO.File]::Create("C:\MySource\ReportPOC\POC.docx")
$fs.Write( [byte[]]$bytes, 0, $bytes.Length);
$fs.Flush()
$fs.Close()

The result, a chart and report using the same data source with a page break between them as it displays in Word 2013:

Using Microsoft Report Viewer In PowerShell

Next Steps
If you want a re-usable solution I would create a more generic data source class to avoid coding a new data source class for different charts. Also add some parameters to the report/chart to control the headings, legend and labels, page headers/footers etc. You can also export to other formats by passing different parameters to the render method like “EXCEL”, “PDF”, “HTML” and “XML”. You can also create different series to group categories and apply logic to the report/chart to calculate values or control colors for example if CPU usage is > 90 % color the bar red, this is done in the report designer.

Francois Delport

Installing SQL Server Reporting Services On A Client Operating System

In this post I’m going to cover installing SQL Server Reporting Services on a client Operating System.

In my previous post I showed how to use a service principal to call the Azure Billing API without any user interaction. I used the results from that scheduled API call to populate a local database that I’ll be using for reporting. Technically you could call the API every time passing it the required date range and report on that but it is much quicker to do it locally. Secondly I wanted a way to schedule the delivery of the chart/report using SSRS instead of browsing to the report every day. The goal for all of this, is to catch any upwards trend in my Azure usage instead of waiting for my Azure spending limit to kick in.

Side Note: You could use Billing Alerts, it is currently in preview but it is a bit simplistic, you can only set alerts on a specific amount not an amount for a specific interval other than your billing period. For example, I create an alert for $1000 since my average monthly usage is $900 and one of my team members forget to shut down a few VMs while testing. If I used alerts a few days would pass before I pick it up and the $1000 limit is reached. It would be useful if I could set a daily limit which would be based on my average usage plus a bit, this way if it goes over for example $50 per day I will get an alert.

Anyway back to the actual topic of this post. It has been a while since I used SQL Server Reporting Services and it has been even longer since I installed it. I decided to install SSRS on my dev machine to test the scheduling of my Azure usage report. I ran into a few problems that I want to document for future use. Bear in mind this was a Windows 10 pc not a server, you won’t have most of these problems if you are using a server OS. Most of the solutions around permissions was covered already thanks to this post.

  • First problem occurred at the very end of the installation, I had an existing SQL instance and I added SSRS to it.
    Installing SQL Server Reporting Services On A Client Operating System

I was using the local administrator account to run the installation and the user had permissions to modify the Temp folder. Turns out you can’t do much about it at this point just continue with the installation and fix the other errors related to this later on.

  • Second problem was the SSRS service wouldn’t start, I got “Access Denied” error messages when I start the service. To fix this give the account running the SSRS service permissions to the:
      “C:\Program Files\Microsoft SQL Server\MSRS12.MSSQLSERVER\Reporting `    
       Services”
    folder.
  • Not really a problem but keep in mind when you configure SMTP settings SSRS needs an account name with access to your SMTP server, you can’t use Gmail, Hotmail etc, which makes sense, this will usually be used in an enterprise environment. If you want to test emailing on a schedule and you don’t have a valid account I recommend smtp4dev or setup your own SMTP server in IIS.
  • I also saw the following errors in the event log
    “Report Server (MSSQLSERVER) cannot load the TERADATA extension.”
    and
    “Report Server (MSSQLSERVER) cannot load the SQLPDW extension.”
    These won’t prevent you from working but it does spam the eventlog, making it difficult when you are trying to troubleshoot real problems. This link will explain how to disable the plugins if you don’t need them or how to install the software components if you need them.
  • You will also have trouble loading the SSRS website as administrator, this link explains how to fix that and also administrator access for SSMS.

Side Note: The SSRS version you get with SQL Express doesn’t support emailing and scheduling reports. I did a quick google and found some free solutions that email Crystal Reports on a schedule. I didn’t try it myself but it is something to keep in mind for home use. I also tried to use PowerBI but it doesn’t have the ability to schedule and email reports.

Francois Delport