Skip to content

Category: SQL Server

The Health Analyzer and PowerPivot for SharePoint

*Note – Updated 2012-09-07

The Health Analyzer that first appeared in SharePoint 2010 is a fantastic idea. Periodically, (you say when) timer jobs run to check predefined health rules, and when those fail, you are alerted in Central Administration with a yellow or red error bar depending on the severity. This can potentially bring problems to an administrator’s attention before their effects are felt. Unfortunately, some of the default rules, through a combination of being useless, or buggy, result in almost any farm being constantly alerted. This has the negative effect of reducing confidence in it, and causing administrators to ignore these alerts, which is a pity, because when properly configured, they can be quite useful.

The trick is to spend a few minutes to deactivate the ones that don’t work properly, or are unnecessary. My personal favourite is the alert “Database has large amounts of unused space” – which is actually a very good condition.

All that you really need to do for these buggy rules is to open them up, and disable them. It’s relatively straightforward to do so. While in Central Administration, just open up any of the alerts, and select the “View” link in the Rule Settings section.

image

From the resulting screen, just click Edit in the ribbon, and deselect the “Enabled” option.

image

Taking the time to do either do this, or to remedy the situation for all of the alerts that you’re receiving on your farm will turn your Health Analyzer from a nuisance to a valuable monitoring tool.

In order to test whether or not your changes have worked, you need to run all of the Health Analyzer jobs. You can do this manually, through Central Administration, or you can run the following PowerShell (by Gary Lapointe, lifted shamelessly from Matthew McDermott’s blog):

Get-SPTimerJob | where {$_.Title -like “Health Analysis Job*”} | Start-SPTimerJob

Installing PowerPivot for SharePoint introduces a group of new rules to the mix, and like their out of the box cousins, they are a mixed blessing. Some are important, and some are downright wrong. I had occasion recently to do a clean install of PowerPivot for SharePoint 2012, and decided to document the Health Analyzer results, and their required actions here.

Upon completion of the PowerPivot for SharePoint install, I was initially taken aback to find so many errors:

image

OK, one of these has nothing to do with PowerPivot, but we’ll tackle the rest. In reality, they’re not so bad taken one at a time. We’ll start with one that’s potentially very important:

1. Built-in accounts are used as application pool or service identities.

It’s good practice to always use domain accounts for any service in SharePoint, which is why this alert exists. Opening it up points to the offending culprit, the Claims to Windows token service (C2WTS). By default, it is typically set up to run with the local system account, and there’s a good reason for that.

image

The C2WTS service is used by PowerPivot (OK… Excel Services) to convert from claims based identities to Windows identities. Non claims based services (like Excel Services) need it to work, and it is required for PowerPivot to work properly.

It’s relatively straightforward to change the identity for this service, but whatever you do, change it using Central Administration, not through Windows Services. SharePoint “knows” about the identity and will eventually reset it if you use the Windows interface. To change the identity, simply navigate to Security-Configure Service Accounts and select the appropriate managed account – but be warned, if you do, you have more work to do – in my opinion, it’s best to leave it as Local System.

The problem is, the C2WTS must run with the identity of an account that is part of the Local Administrators group on the server, or as Local System. If you do decide to use a domain account, you will need to add it that group (see this discussion for more detail). However, if you do, you’ll simply trigger another rule warning you about process identities being in the local administrators group. You just can’t win.

By the way, if you do decide to switch the identity to a domain user, and you decide to switch it back, it’s not so simple. The service account UI only allows the selection of managed accounts, and Local System isn’t one of them. If you do need to switch back, just run the PowerShell scripts listed in this Technet article.

Either way you go, you’ll simply want to deactivate the offending rule.

2. PowerPivot: The Analysis Services instance runs in tabular mode, but the configuration setting that specifies this mode is turned off.

Sounds frightening. However, opening up the alert reveals the true problem.

image

The issue is actually that the rules analyzer can’t see that the tabular mode setting is set properly, so it assumes the worst, and alerts you. The reason that it can’t see it, is that the account used by health analyzer doesn’t have access to the file on the file system. That account is typically the farm account, and granting that account access to the file will prevent the alert from reappearing.

Or you can turn it off –  your choice. Given that there’s little chance of something sneaking into the PowerPivot instance and switching the configuration away from tabular, you’re probably pretty safe.

3. PowerPivot: MidTier process account should have ‘Full Read’ permission on all associated SPWebApplications

This one matters, especially if you need to do data refresh. Don’t turn it off. The detail on this alert doesn’t really add anything, so I’m not showing it here.

By “MidTier” it means the process account running PowerPivot. If you used the (very good) PowerPivot Configuration Tool that ships with SQL Server 2012, and selected the defaults, the chances are that the account is your farm account. If that works for you, and your farm account has access to all of your content, well you likely aren’t getting this alert, but in my case, I don’t typically give the farm account access to the site collections.

In my recent case, I needed to do two things – change the account used by PowerPivot to a different account, and then grant that account access to the farm content.

Firstly, if you’re unsure of what account PowerPivot is using, navigate to Security-Configure Service Accounts. Your list of pools/services will vary, but once you select the one used by your service application, you’ll see it in the list

image

Changing the Application Poll for PowerPivot

If you need to change the account, you’ll need to navigate to your PowerPivot Service Application. From Central Administration, select Application Management-Manage Service Applications, and then select (but don’t click through!) your PPSA.

image

With the PPSA selected, click on the Properties button. Then, in the resultant dialog, select, or create the application pool that you wish to use for PowerPivot.

image

Take note of the managed account that you will be using for the application pool, as that is the account that will need full read access in the next step.

Setting Permissions for the PowerPivot Application Pool

You could go through your site collection and add the service account to any relevant groups, etc, but the easiest way to accomplish what is necessary is to treat it the same way that Search does the default content access account, and add it to the User Policy for the relevant SharePoint web applications. To do this, from Central Admin, navigate to Application Management-Manage Web Applications. Next, select the web application in question (again, don’t click through), and click the “User Policy” button in the ribbon.

image

If your account is not already listed, click add users and follow the prompt. When presented with the option, select “Full Read” for the permission level.When complete, you should see an entry similar to the following

image

Repeat this process for all applications in the farm. Once this is complete, PowerPivot should have the permissions that it needs, and you should receive no further alerts of this type.

4. PowerPivot: Usage data is not getting updated at the expected frequency.

image

This alert may or may not be important to you, but I do recommend getting it fixed. PowerPivot maintains usage data in its service application database, and the service application can surface that data to administrators in Central Administration. To see this, simply navigate to the PowerPivot service application in Central Administration, and click through it to manage.

It actually uses PowerPivot workbooks to surface the information, so if PowerPivot isn’t set up correctly, you will see errors. In addition, these workbooks need to be refreshed from the original data source. This refresh is performed by a timer job, which updates the underlying workbook. This Health Analyzer job looks at the most recently updated date of the workbook, and fires the alert if it hasn’t been updated recently. This is good, because in a default installation, it won’t be.

There is a bug in the setup procedure that prevents the correct permissions from being applied to the service application database (see this discussion for more detail – the bug is still there in SQL 2012 RTM). Fortunately, the fix is relatively straightforward.

You’ll need to run SQL Server Management Studio and connect to the SQL server hosting your PowerPivot Service Application database. Open the database, and navigate to Security-Users. You should see your service account already there (if not – add it…), then right click on it and select properties. In the resulting dialog box, select Membership. If not already selected, you’ll need to check both the db_datareader and db_datawriter roles.

Once that’s done, the service application will be able to use the usage data for PowerPivot.

However, this will not update the relevant worksheet immediately. If you want to do this, you need to navigate to the “PowerPivot Management Dashboard Processing Timer Job” (available in Central Administration via Monitoring-Review job definitions), open it up and click the “Run Now” button. This should refresh the worksheet. The dashboard will then work properly, and the alert should stop firing (at least for now..).

5. PowerPivot: ADOMD.NET is not installed on a standalone WFE that is configured for central admin

You will see this alert if you’re using PowerPivot for SharePoint from SQL Server 2012. ADOMD.NET is a dependency for PowerPivot and the Health Analyzer is alerting you to the fact that it is not installed. The problem is that it IS installed. What’s happening? The Health Analyzer is looking for ADOMD.NET 11.0.0.0 (the one that ships with SQL Server 2008 R2). The ADOMD.NET that ships with SQL Server 2012 is 11.0.2100.60. This of course fails the check, and fires the alert. (For more info check out Trevor Seward’s article)

What’s the solution? Disable the rule. You run the risk of not noticing if the file gets removed, but I bet you’ll notice that when PowerPivot stops working.

Below points added 2012-09-07

6.  PowerPivot: Registry settings for Microsoft.AnalysisServices.ChannelTransport.dll are not valid after you install the SQL Server 2008 R2 version of the MSOLAP provider on this computer

This alert will show up most commonly in larger farms – farms that have separated the shared services roles from the front end server roles, and it will show up on the front end servers. The problem  occurs because although the PowerPivot features get deployed to all servers, the deployed assemblies do not get registered properly in the Global Assembly cache. The PowerPivot install registers them so this shouldn’t appear on the application server(s).

The solution is to register them manually on all of the affected front end servers.

To do so, open a command prompt in administration mode. Once open, navigate to:

C:WindowsassemblyGAC_MSILMicrosoft.AnalysisServices.ChannelTransport

Once here, there will be another subdirectory that will depend on the version of PowerPivot for SharePoint installed. The SQL 2012 version will start with 11, the 2008 version with 10, etc. Navigate into that folder. Once in that folder, run the following command:

C:WindowsMicrosoft.NETFramework64v2.0.50727regasm.exe Microsoft.AnalysisServices.ChannelTransport.dll

That should be all that you need to do to fix this one. It will also let PowerPivot work correctly, which is of course a good thing.

7. PowerPivot: Secondary Logon service (seclogon) is disabled

The secondary login service is a built in Windows service, and it is used by PowerPivot to generate the thumbnails that appear in the PowerPivot gallery. It is set to start up manually in Windows by default. According to the PowerPivot Health Rules reference, this should be sufficient for correct operation. Unfortunately, in some cases it isn’t, the service never starts, the Health Analyzer thinks that the service is disabled, and the thumbnails don’t get built.

Fortunately, the fix for this is simple. Login to each of the servers in the farm, start the service, and set its start up options to automatic. That’s it.

 

This represents the bulk of the Health Analyzer issues with PowerPivot that I’ve come across. If you have others, or I’m out to lunch on any of my analysis, please drop me a comment – I’m keen to hear.

12 Comments

Migrate Reporting Services from Native Mode To SharePoint Integrated Mode

I have previously written about upgrading and moving Reporting Services to SSRS/2008 R2/SP2010, and also on upgrading to the new Service application in 2012. Both of these deal with moving prior versions of Reporting Services running in SharePoint mode to more recent versions, also running in integrated mode. What has been lacking from Microsoft until now was a mechanism to help move an organization from Reporting Services in Native mode to Reporting Services in integrated mode.

The solution to date has been to go back to the source projects in BIDS and redeploy them to the Integrated Mode server. This of course assumes that BIDS was used for report design (not Report Builder), and that the projects are available. You also lose all server side configurations (like subscriptions) with this approach.

On Friday, April 20 2012 Microsoft released Version 1.0 of  the Reporting Services Migration Tool, which allows you to do just that. It’s a high level tool that brings all of the artifacts out of the Native mode instance, and at a later point in time, import them into the Integrated Mode instance. Ultimately, the stated aim of the tool is to allow a file system level backup of your Reporting Services Instances, be they Native or Integrated mode.

It can be run either by command line, or through a GUI. A snapshot of the GUI screen can be seen below.

image

The tool is definitely version 1, and has several limitations which I’ll outline below, but it does work. It does so by connecting to either the WMI provider, or the Reporting Services web services, then extracting all of the available content, and then building a PowerShell script which can be run to place the backed up content in a SharePoint document library that has been properly configured to support the Reporting Services content types.

Operation of the tool is relatively straightforward, and is adequately documented on the download page, so I won’t go through a step by step, but I do want to share a few observations.

Firstly, migration is from Native Mode to Integrated Mode only. The stated objective of this tool is to support both modes on either end of the migration path, but for now it’s a one way trip. For the moment, it does limit its ability to perform as a backup tool. However, if you examine your output folder, you’ll find all of your report files, connection files (etc), so if you’ve built your reports with BIDS, and lost the original source project, it’s a great way to get them out of the Reporting Services database.

I have also been unable to get the WMI provider to work at all. I’ve tested with both SSRS 2008R2 and SSRS 2012 Native mode sources, but the tool can’t seem to find the WMI instance. The tool still works in this configuration, but it will not back up passwords or history snapshots. I’ll update this post if/when a solution to this can be found.

UPDATE – Thanks to Tristan in this MSDN forum thread – The WMI provider is working. I have added the paragraph and image below.

The Instance Name field is mislabelled. It should be SERVERInstance for non default instances, or just SERVER for default instances. Unfortunately the nowhere in the help is the requirement for SERVERNAME mentioned. Essentially, you should treat this field the same as you would the Server field when connecting via Management Studio. The image above has been updated to show the correct value for Instance Name (In this case, although not necessary, I have included the name of the default instance).

As outlined on the download page, the tool does not back up Reporting Services security information, or role information – which makes sense when moving to a new security model. Also, linked reports aren’t supported in Integrated mode, so they’re not backed up at all.

For a complete list of constraints and instructions, visit the download page.

For it’s limitations, this tool is a very welcome addition to the toolkit. Migrating from Native Mode to SharePoint Integrated mode Reporting Services no longer  needs to be painful.

2 Comments

Fixing Access Errors When Creating a BISM Connection for PowerView

PowerView is one of the shiny new features that are available to SharePoint users with the implementation od SQL Server 2012. To be sure, you don’t need to convert your database engine over to SQL Server 2012, but you do need to install PowerPivot for SharePoint, and/or the new Reporting Services service application for SharePoint, both only available in SQL Server 2012.

PowerView requires a connection to an xVelocity Analysis Services engine (formerly known as tabular mode or VertiPaq), or to an Excel spreadsheet with an embedded PowerPivot model in order to function. When connecting to the Analysis Services engine, there are a couple of permissions that need to be set on that engine that you should be aware of.

If you wish to connect to the Analysis Services engine, you have two choices. Firstly, you can use a Reporting Services connection (.rds) and select “Microsoft BI Semantic Model for PowerView” as the Data Source type.

image

Once this is done, it can be used to create PowerView reports. This approach works without any additional configuration. The reason that this is so is that Reporting Services takes advantage of the EFFECTIVEUSERNAME connection property for user impersonation. This is something that BISM does as well. When using an RS connection, the stored credential (in this case) is used to establish a connection with the data source, and then all queries are executed with the identity of the requesting end user (provided that the “Set execution context…” option is not selected.

For further reading on how Reporting Services uses the EFFECTIVEUSERNAME property, check this article. Since BISM uses the same property, it’s highly relevant to PowerView.

However, the problem arises if we choose the second option, and want to work with a BISM file directly. If we want to use a basic BISM file, we first add it by creating a document with the the BI Semantic Model content type.

image

However, the connection form is far simpler than the one used to configure the Reporting Services connection. You’ll notice immediately that there is no option for storing credentials. For a server connection, all that is necessary is a name for the connection, the name of the server, and the name of the database.

Unfortunately, if you haven’t gotten everything configured just so and you click ok, you’ll receive the error “Cannot connect to the server or database”.

image

This is due to the fact that when the server performs the validation check against the Analysis Services server, it uses a system account to first connect to the AS server. This is documented in this Connect forum entry. The corrective action is to add the account to the Analysis Services Server Administrator role:

 image

What account needs to be added? The forum article I referenced above indicates the PowerPivot service account, which is now listed in SharePoint as the “SQL Server Analysis Services” account. However, my testing has indicated that the farm account is the one that is used to verify connections with Analysis Services, so that’s what I’m recommending here. This is only used for validation purposes, and to get around this problem without adding the account to the administrators role, you can simply select the “Save the link file without connection validation” option. This may however be unsettling to users.

Once you’ve created your BISM connection, you should then be able to use it to launch Excel, or create a PowerView report. When you launch Excel, the BISM is referenced by an Excel connection, which then connects directly to the data source with the credentials of the end user. No problem. However, if you attempt to create a PowerView  report, you may find yourself faced with “An error occurred while loading the model for the item or data source”.

image

In the body, it misleadingly leads you to believe that it’s the end user (btidwell in this case) that doesn’t have access. What should happen is that, as explained above, the Reporting Services service makes a connection with the AS server, and then uses the EffectiveUserName property to impersonate the user. For more detail on how BISM authenticates to back end data sources, see this MSDN article.

If you’re seeing this error, the chances are that the service account that is being used for Reporting Services doesn’t have access to the Analysis Services database.

As in the verification step above – granting the account access to the specific database doesn’t do it, you need to add the service account that is used by Reporting services to the Server Administrators role. Once you’ve done that, PowerView should behave smoothly.

4 Comments

How To Automate SharePoint Report Creation With SSIS and SSRS

If you’ve used SQL Server Reporting Services to any great extent, you’ve likely encountered the need to generate reports automatically. This requirement may be for for delivery purposes, archival purposes, or simply to reduce report rendering wait times for the end users. SSRS supports this requirement out of the box – a report administrator can set up a subscription, enter the required parameters, and the report will be generated and delivered on that schedule.

This approach is highly declarative, and puts the onus of subscription creation on the report administrator. To this end SSRS also supports data driven subscriptions, which allow the subscriptions to be looked up from a SQL table. How that table is maintained is up to the individual organization, but it does allow a measure of dynamism. With SQL Server Reporting Services 2012, this feature is made much more user friendly through the use of User Driven Subscriptions.

The down side to any of this dynamic behaviour is that in every case, it requires the Enterprise version of SQL Server (with SQL Server 2012, the BI SKU also has this capability). In addition, with SQL Server versions prior to 2012, the capability is somewhat less than user friendly.

In this post, I will outline a methodology that will allow you to provide SharePoint list based report subscriptions that will allow users to subscribe to published reports, and have them published to a SharePoint document library. The approach is not restricted to SharePoint – indeed it could be used with native mode to read through a list of possible parameter values, and email the resulting reports, or store them in a file system, but the SharePoint example is the one that I will be using below.

I should also point out that although the examples below use SQL Server 2012, the approach should work with versions back to SQL Server 2005.

The primary components of this solution are a SharePoint list that will be read to determine what reports to render (the subscription list), a SQL Server Integration Services (SSIS) package that will read through the subscription list and use the values therein to render the report, and finally, a SharePoint document library that will house the reports. Of course, we also need a report to be rendered, and in our case, this report is also stored in a SharePoint document library, as Reporting Services is running in SharePoint Integrated mode.

The good news, is that all of the constituent portions of this solution are either downloadable for free, or come with SQL server in any other edition besides Express. Therefore, the chances are that if you have SharePoint, then you already have all of the tools that you need.

Step 1 – Obtain the SharePoint List Source and Destination Project

Out of the box, SSIS doesn’t know how to talk to SharePoint data. Fortunately, there’s an excellent Codeplex project that adds the required capability. If you haven’t already done so, download the SharePoint List Source and Destination project from Codeplex. You will find a good blog post on working with this tool here. Once installed, you will be ready to build the solution. Of course, this step is only necessary if you want to use a SharePoint list as a subscription source.

Step 2 – Create your subscription and report library

In this solution, we will allow a user to enter a subscription request in our subscription list. The user can specify the URL of the report to be run, the parameters for the report, the file type that is to be produced, and the library where the report is to be stored. In order to support this, we’ll need at least one document library where the produced reports will be stored, and one custom list.

Create your document library, and note its URL. In our case below, our report library will be at http://home.nautilusinc.local/sites/nmarine/IT/Sandbox/ExpenseReportOutput. This URL will be used below. In this library, we don’t need to add any custom metadata properties, but you certainly may, should you wish to do so.

Next, create a custom list. In our case, the list will be named “Subscriptions” and will be created in the  “http://home.nautilusinc.local/sites/nmarine/IT/Sandbox” site. Where you create this list is not important, but what is important is the display name of the list, and the URL of its parent site.

For our use case, we want the user to be able to specify the Report to be rendered, the destination to place the rendered reports, the parameters to use for the rendered report, and the file type of the rendered report. To that end, we will add 4 additional columns to the list, as shown below.

image

You will also note that the “Title:” field has been renamed to “Subscription” on this list. This is purely for cosmetic purposes. Three of the new fields are simply single line text fields, while the Format field is choice. In our example, the options available for the choice field are WORDOPENXML, PDF, EXCELOPENXML, IMAGE, and NULL. You can allow any of the possible output types that Reporting services supports. I have outlined these types previously in another post here.

While it is outside the scope of this article, you will likely want to modify the form to display more user friendly names for the options than “WORDOPENXML”, etc, and automatically calculate the value for the subscription field. InfoPath would be an excellent tool to do this with, and there are other alternatives as well. For our purposes, we will work with the form as is.

Once done, you will want to add a couple of subscriptions. In our case, we’re working on a very simple report as shown below:
image

The report takes a single parameter, employee name, and renders the report filtered by that parameter. The subscription list item that we’ll create will look something like below:

image

The value for ReportURL is the full URL path to the report definition, in our case it is http://home.nautilusinc.local/sites/nmarine/finance/ReportsMarch22/ExpenseReports.rdl (you should be able to enter the URL into a browser and see the report), and the destination library is the full URL path to the destination library, in our case http://home.nautilusinc.local/sites/nmarine/IT/Sandbox/ExpenseReportOutput.

After adding two subscriptions, our subscription list appears as follows:

image

When our job runs (defined below) it will iterate through this list and create a corresponding PDF file and Word file in the destination library. Next, we create the SSIS package that will actually do the work.

Step 3 – Create a Reporting Services Web Service Proxy Class

In order to render the Reporting Services reports, we will need to call the Reporting Services web service from a SSIS Script task. In order to do that, we’ll need to use a proxy class. Luckily, we can just generate one using the WSDL.EXE generation tool available from the .Net 3.5 SDK. You run the tool with the following options:

wsdl.exe /language:[language choice] /out:ReportService.[language choice] http://[SPSiteURL]/_vti_bin/ReportServer/ReportService.asmx?WSDL

where:

  • [language choice] = VB or CS
  • [SPSiteURL] = URL of the SharePoint Site Collection

In our case, the precise command is:

wsdl.exe /language:VB /out:ReportService.vb http://home.nautilusinc.local/sites/nmarine/_vti_bin/ReportServer/ReportExecution2005.asmx?WSDL

If you don’t want to build your own, you can download the one that I created for this project (it’s Visual Basic). It was built using SSRS 2012, but should be backward compatible. Also, don’t forget to change the embedded server URLs.

Once you have the output file, make note of its location – we’ll use it below when creating the script task in SSIS.

Step 4 – Build the SSIS Package

I’m going to assume that most people reading this have little or no exposure to SSIS, so I’ll try to be as detailed as possible. You’ll need to start SQL Server Data Tools (if you’re using SQL Server 2012) or Business Intelligence Development Studio (for SQL versions prior to 2012).

image

You may notice that is has a striking resemblance to Visual Studio 2010. That’s because it is VS2010.  Select “New Project” then in the “Business Intelligence” section, select “integration Services Project”. Give the new project a name and location and click OK.

image

Once created, we’ll need to create a SharePoint List connection manager. From the Solution explorer, right click on “Connection Managers” and select “New Connection Manager”. Scroll down on the window, select “SPCRED” and click Add.

image

You will only see SPCRED if you completed Step 1 above. The Connection Manager will then prompt for a name and a set of credentials. Provide the name, and also provide it with an account that has access to the subscription list. If the SSIS service account has access, you can select “Use Credentials of Executing Process”, otherwise provide a service account with access.

image

We’ll be working within a Data flow task, so drag a Data Flow Task onto the design canvas.

image

Next, double click on the data flow task, or click on the Data Flow tab to bring up the Data Flow Task Editor. From there, drag a “SharePoint List Source” action onto the canvas. (Note: if the SharePoint List Source does not appear, there may have been a problem installing it. Consult the documentation for the SharePoint List Source and Destination project for troubleshooting steps.) Double Click on the List Source action to configure it. The first item to configure is the Connection Manager. Simply select it from the (hidden!!! ) drop down list. Click on the area beside “SharePoint Credential Conn…” to reveal the dropdown.

image

Next, click on the “ Component Properties” tab. Here, you perform the bulk of the action configuration. There are many options to choose from, but the ones that we’re concerned with here are SiteUrl and SiteListName. SiteURL is the absolute URL of the site that will contain our list, and SiteListName is the display name of the list. I stress display name as this is different than working with most other APIs for SharePoint, which tend to use the internal name. Also – it’s relatively easy for users to change the display name of the list. Doing so will break the package until it is reconfigured.

image

Next, drag a Script Component onto the canvas, below the data source. If prompted, choose “Transformation” for the script type. Next, connect the two actions by dragging the arrow from the  SharePoint List Source to the Script Component.

image

Next, double click on the script component to bring up the script component editor. From the left, select Input Columns and select all of the columns to use in this script. In our case, we’ll be working with the columns shown below:

image

Next, click on the Script section, choose the language that you want to work with, then click the “Edit Script” button.

image

Without getting into too much detail of how the script action works, what we are going to do is to add code that will run for each row of data that flows through the transformation. In our case, that will be for each configuration item. We’re going to use the values of the columns of each configuration item to render the reports. Therefore, the code that we will write will go into the “Input0_ProcessInputRow” sub.

Before we can do that however, we need to add some supporting items. Firstly, since we’ll be working with web services, we’ll need to reference the .Net System.Web.Services library. Right click on the project name in solution explorer, and select Add Reference. From the .Net tab, select System.Web.Services, and click OK.

image

Next, expand the “Imports” section and import the System.IO and the System.Net  namespace.

image

We now need to add our Reporting Services proxy class. The best way to do this is to first create a new class. Right click on the project in solution explorer, and select Add – Class.

image

Next, give the class a name. I like to match the name to the main class embedded, so the new name is ReportExecutionService.vb. Next, using Notepad, open the file that you created or downloaded in Step 3 above. Select all text, copy it into the clipboard, and then paste it into the newly created class, overwriting anything already there. Once done, save and close the class.

Next, I add a helper function to the script that helps to deal with URLs missing an ending slash. You can add it immediately above the “Input0_ProcessInputRow” sub. The code is below:

 Private Function CheckSlash(ByVal input As String) As String
        If input.EndsWith(Path.DirectorySeparatorChar) Then
            Return input
        Else
            Return input & Path.DirectorySeparatorChar
        End If
    End Function

As we saw below, the output format parameters aren’t the friendliest, and we will need to specify the extension for the output file. To allow this, I also wrote a small helper function to turn output format values into file extensions, and include it below. This also needs to be added to the script.

Private Function GetExt(format As String) As String
        Select Case format
            Case Is = "XML"
                Return "xml"
            Case Is = "Null"
                Return Nothing
            Case Is = "CSV"
                Return "csv"
            Case Is = "ATOM"
                Return "atom"
            Case Is = "PDF"
                Return "pdf"
            Case Is = "HTML4.0"
                Return "htm"
            Case Is = "RGDI"
                Return "gdi"
            Case Is = "MHTML"
                Return "mhtml"
            Case Is = "EXCEL"
                Return "xls"
            Case Is = "EXCELOPENXML"
                Return "xlsx"
            Case Is = "RPL"
                Return "rpl"
            Case Is = "IMAGE"
                Return "tiff"
            Case Is = "WORD"
                Return "doc"
            Case Is = "WORDOPENXML"
                Return "docx"
            Case Else
                Return Nothing
        End Select
    End Function

 

Finally, we’re ready to add code to the “Input0_ProcessInputRow” sub. The complete code listing is below:

  1. Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)
  2.       '
  3.       Dim rs As New ReportExecutionService
  4.       rs.Url = "http://home.nautilusinc.local/sites/nmarine/_vti_bin/ReportServer/ReportExecution2005.asmx"
  5.       rs.Credentials = System.Net.CredentialCache.DefaultCredentials
  6.       Dim report As Byte() = Nothing
  7.       Dim deviceinfo As String = Nothing
  8.  
  9.       Dim ParameterPairs As String() = Row.Parameters.Split(";")
  10.       Dim parameters As ParameterValue() = New ParameterValue(ParameterPairs.Length – 1) {}
  11.       Dim CurrentPair As String()
  12.       For i As Integer = 0 To ParameterPairs.Length – 1
  13.           CurrentPair = ParameterPairs(i).Split("=")
  14.           parameters(i) = New ParameterValue
  15.           parameters(i).Name = CurrentPair(0)
  16.           parameters(i).Value = CurrentPair(1)
  17.       Next
  18.  
  19.       Dim historyID As String = Nothing
  20.       Dim credentials As DataSourceCredentials() = Nothing
  21.       Dim showHideToggle As String = Nothing
  22.       Dim extension As [String] = String.Empty
  23.       Dim encoding As [String] = String.Empty
  24.       Dim mimeType As [String] = String.Empty
  25.       Dim warnings As Warning() = Nothing
  26.       Dim reportHistoryParameters As ParameterValue() = Nothing
  27.  
  28.       Dim streamIDs As String() = Nothing
  29.       Dim execInfo As New ExecutionInfo()
  30.       Dim execHeader As New ExecutionHeader()
  31.  
  32.       rs.ExecutionHeaderValue = execHeader
  33.       execInfo = rs.LoadReport(Row.ReportURL, historyID)
  34.       rs.SetExecutionParameters(parameters, "en-us")
  35.       Dim destUrl As String = Row.DestinationLibrary
  36.       Dim destinationUrl As String = CheckSlash(destUrl) + Row.SubscriptionTitle + "." + GetExt(Row.Format)
  37.       Dim r As Byte()
  38.  
  39.       Try
  40.           report = rs.Render(Row.Format, deviceinfo, extension, mimeType, encoding, warnings, streamIDs)
  41.           Dim m_WC As WebClient = New WebClient
  42.           m_WC.Credentials = System.Net.CredentialCache.DefaultCredentials
  43.           r = m_WC.UploadData(destinationUrl, "PUT", report)
  44.       Catch ex As Exception
  45.  
  46.       End Try
  47.   End Sub

 

Again, without getting into too much detail, some explanation of the above code is in order.

Lines 3-5 initialize the web service, assign it a URL (Don’t forget to change this for your environment!!) and assign it the credentials to use when calling the web service.

When this  sub is called by SSIS, it is passed a row object. The row object contains column objects for each column that is used by the script (this was configured above). Therefore, to get the value for any given column, you simply need to refer to it as row.ColumnName. In our case, to get the value of the Parameters column, you use row.Parameters. Lines 9 through 17 get the value of the parameters column, split the value into an array of string objects using a semicolon as a value delimiter, then for each of these objects, separates them into name/value pairs using the equals sign as a delimiter, and them finally assigns them to a Reporting Services parameter collection.

Using this approach, we can use a single field to store all of the parameters for a report, and any report can have any number of parameters.

Lines 19-32 are  primarily used for initialization. Line 33 loads the report specified in the subscription (by calling row.ReportURL). Line 34, sets the parameters, and lines 35-36 set the destination variables.

Finally, Line 40 calls the web service to actually render the report into a byte stream, and line 43 uses the .Net WebClient object to upload the file directly into SharePoint. In this example, we don’t actually add any metadata to the SharePoint library, but if this was required, you could use the techniques outlined in this post. We are now ready to test the process.

Step 5 – Run the Package

Close the Script editor window and click the OK button. If all is well, your Script Component action should show no errors. When ready, click the run button to test your package. If all is well, after a short compilation period, you should see that 2 records were successfully read from the subscription list, an both steps should show green. If things don’t go well, the error messages are pretty good….

image

Navigating to the destination library, we see the two requested reports.

image

Next Steps

Obviously, every time that this package runs, the reports will be overwritten with the new report. This may be desired behaviour, but if not, you may want to turn on version control (each version will be stored as a version) or modify the script to change the file name on each run (date stamping is a common technique).

In addition, you will want the package to be run automatically without human intervention. To do this, you’ll want to deploy it to a SQL Server running SSIS , and to schedule it to run as an agent job. There is a wealth of information online for how to do that.

Conclusion

The example provided above covers a single use case, but with minor adjustment could be used to automate all sorts of reporting tasks. A common one would be to use the NULL renderer to refresh report caches on a server. If you find any unique uses of this approach, I would love to hear about it. Please post a comment!

Credits

In preparing this post, I found the following articles to be useful:

SSIS and Reporting Services Web Services

Uploading documents to WSS (Windows Sharepoint Services) using SSIS

SharePoint reporting services SOAP endpoint in CTP3

Upload document from Local Machine to SharePoint Library using WebService

Uploading files to the SharePoint Document Library and updating any metadata columns

8 Comments

How To Get A Comprehensive List of all E-Mail Enabled Libraries in SharePoint

I recently completed a multi-farm consolidation and upgrade from SharePoint 2007 to 2010 for a customer, collapsing three farms into one. The approach was to create a new farm, and to individually do dbattach upgrades of each of the 2007 databases into separate SharePoint applications. Everything went well, including Reporting Services subscriptions, but we ran into a problem with incoming email.

The problem is that while all of the incoming email settings for a library are properly migrated when doing a dbattach upgrade, all of the aliases are stored in the Farm Database (in the EmailEnabledLists table, if you’re interested in looking), and it remains empty. The resultant effect is that you inspect the library properties, and all looks good, and email is properly being delivered to the drop folder. Unfortunately, the incoming email service timer job is looking for emails that correspond to the entries in the EMailEnabledLists table, and there are none.

The solution is to simply turn off incoming email for the affected lists, and then turn it back on. A bit cumbersome maybe, but it does work. However, in our case, our customer had over 100 libraries and wasn’t sure where they all were. A bit of hunting around found a couple of ways to get a list of email enabled libraries through code (here and here).

However, I don’t like writing code if I don’t have to, and decided to have a look in the content databases. Don’t forget the first rule of playing around in the SharePoint content databases, which is don’t. However, reading from them isn’t so bad, and ultimately solves our problem. Enough information is in fact in there to construct a simple query:

SELECT
     Webs.FullUrl As LibraryURL,
     AllLists.tp_Title As LibraryTitle,
     AllLists.tp_EmailAlias As emailAlias
FROM
     AllLists
INNER JOIN
     webs on AllLists.tp_WebID = Webs.Id
WHERE
    AllLists.tp_EmailAlias IS NOT NULL
Opening up SQL Server Management Studio, and running this query on each content database will give you a comprehensive list of all e-mail enabled document libraries.
7 Comments