Posts belonging to Category SSRS



Displaying Microsoft Project Task’s Notes in SSRS 2008

Lego Deadlock

I was asked to take a look at an issue the other day regarding displaying Microsoft Project Task’s Notes in SSRS 2008.  If you’ve worked with building reports for Microsoft Project Server, you have no doubt dealt with the RTF data that is stored in the Task’s Notes fields.

With SQL Server 2005 Reporting Services (SSRS) it was easy to display this information by following the steps outlined in Christophe Fiessinger post “How to display Microsoft Project Task’s Notes field in a report”.

But What About SSRS 2008

With SSRS 2008, the Reporting Services engine was re-architected.  Some of this new architecture included an improvement in the underlying security.  The question is did these changes have an effect the method available in the blog previously linked.

Unfortunately, it does.  Instead of displaying notes from Project Server as desired, you end up with row after row of N/A – as seen below.

image As a result, the code used for SSRS 2005 to display the RTF will not work with SSRS 2008.  Digging into the error message reveals that the reason that all of the tasks display as N/A is the following error message:

System.Security.SecurityException: Request for the permission of type ‘System.Security.Permissions.UIPermission, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089′ failed.
at System.Security.CodeAccessSecurityEngine.Check(Object demand, StackCrawlMark& stackMark, Boolean isPermSet)
at System.Security.CodeAccessPermission.Demand()
at System.Windows.Forms.NativeWindow.CreateHandle(CreateParams cp)
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.Application.ParkHandle(CreateParams cp)
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.TextBoxBase.CreateHandle()
at System.Windows.Forms.RichTextBox.set_Rtf(String value)
at ReportExprHostImpl.CustomCodeProxy.byteArrayToString(Byte[] b)
The action that failed was:
Demand
The type of the first permission that failed was:
System.Security.Permissions.UIPermission
The Zone of the assembly that failed was:
MyComputer

No good.  The solution fails to function anymore because of the attempt to implement System.Windows.Forms.RichTextBox from within SSRS.  The new security restriction prevent this.

Can It Be Implemented Differently?

Investigating this more, I found an post on the Microsoft forums that dealt with issue.  In that post, there was a reference to a StackOverflow question that also was looking for a solution to this issue.

Both posts point towards adding the following function to the report:

Public Function ConvertRtfToTextRegex(ByVal input As String) As String
        Dim returnValue As String = String.Empty
        returnValue = System.Text.RegularExpressions.Regex.Replace(input, "\{\*?\\[^{}]+}|[{}]|\\\n?[A-Za-z]+\n?(?:-?\d+)?[ ]?", "")
        Return returnValue
End Function

Instead of the code from the original Project Server post the code for the SSRS report should look like this:


'Instantiate a stringbuilder object
Public s As New System.Text.StringBuilder() 

Public Function byteArrayToString(ByVal b() As Byte) As String
    Dim i As Integer
    dim mystr as string 

Try
    s.length = 0 

    For i = 0 To b.Length - 1
        If i <> b.Length - 1 Then
            s.Append(chr(b(i)))
        End If
    Next 

    mystr = left(s.ToString, len(s.ToString)-1) 

    return ConvertRtfToTextRegex(mystr)
Catch ex as exception
    return ex.tostring()
    s.length = 0 

End Try
End Function 

Public Function ConvertRtfToTextRegex(ByVal input As String) As String
        Dim returnValue As String = String.Empty
        returnValue = System.Text.RegularExpressions.Regex.Replace(input, "\{\*?\\[^{}]+}|[{}]|\\\n?[A-Za-z]+\n?(?:-?\d+)?[ ]?", "")
        Return returnValue
End Function

After adding the new code, the values that come back start looking as they would have with SSRS 2005.  Problem solved!

image

Follow-Up

While I’ve provided a solution to this issue, there is a little more to be garnered from this solution.  That is the power of the SQL Server community.  In solving this I didn’t have to have any inherent knowledge of UIPermissions and how they got hosed up because SSRS 2008 is more secure.  This is a good thing by the way. I also didn’t have to know how to write a goofy regular expression.  Thank God!

All I had to do was to take what I knew and start to search for items that were similar and follow where the trail led me.  In this way the common knowledge of the community was shared previously and I am sharing it again myself.

It’s a good thing to share what you know.  Whether through answering questions on forums, writing blog posts, or participating in your local SQL Server user groups.  This helps raise the bar for everyone else and expands the knowledge of our community.

PASSMN June Meeting Today

Minnesota SQL Server Users Group

Don’t forget, PASSMN June Meeting is today.  We have Lara Rubbelke (twitter | blog) coming in to talk about some of the new SSRS features in SQL Server 2008 R2.

More details can be found here.

PASSMN June Meeting This Week

Minnesota SQL Server Users Group

The month has been flying along and I thought I’d remind people that the PASSMN meeting is this week.  If you’ve not registered now’s a great time to get your RSVP in.  We have Lara Rubbelke (twitter | blog) coming in to talk about some of the new SSRS features in SQL Server 2008 R2.

Here are the meeting details…

Date and  Time:

June 15, 2010
3:00 PM CST

Location:

8300 Norman Center Drive, 9th Floor, Bloomington, MN  55437 (map)

Please RSVP here if you will be attending in person, this helps us understand how many people to tell the sponsor to get food for.

Live Meeting

URL: https://www.livemeeting.com/cc/usergroups/join?id=TGJT8N&role=attend&pw=H%3A%7C%3Ds%5C77f

Meeting ID: TGJT8N

Entry Code: H:|=s\77f

Agenda:

3:00 –3:15 : Announcements
3:15 –3:25 : Sponsor
3:25 –4:45 : SSRS 2008 R2 (Lara)
4:45 –5:00 : Survey Collection and Giveaways
5:00 –5:30 : Networking

Presentation:

What’s New in SQL Server 2008 R2 Reporting Services
Lara Rubbelke
Microsoft, Inc.

Amp up your Reporting Services with the many great enhancements in SQL Server 2008 R2. Lara will take you on a tour of all that is new in R2 including collaboration features, new visualizations, rendering enhancements, and new data sources. After this session you will wonder why they call R2 an "interim" release!

PASSMN June Meeting Announced

Minnesota SQL Server Users Group

It’s time to look at the June meeting for the Minnesota SQL Server User Group.  This month we have Lara Rubbelke (twitter | blog) coming in to talk about some of the new SSRS features in SQL Server 2008 R2.

Here are the meeting details…

Date and  Time:

June 15, 2010
3:00 PM CST

Location:

8300 Norman Center Drive, 9th Floor, Bloomington, MN  55437 (map)

Please RSVP here if you will be attending in person, this helps us understand how many people to tell the sponsor to get food for.

Live Meeting

URL: https://www.livemeeting.com/cc/usergroups/join?id=TGJT8N&role=attend&pw=H%3A%7C%3Ds%5C77f

Meeting ID: TGJT8N

Entry Code: H:|=s\77f

Agenda:

3:00 –3:15 : Announcements
3:15 –3:25 : Sponsor
3:25 –4:45 : SSRS 2008 R2 (Lara)
4:45 –5:00 : Survey Collection and Giveaways
5:00 –5:30 : Networking

Presentation:

What’s New in SQL Server 2008 R2 Reporting Services
Lara Rubbelke
Microsoft, Inc.

Amp up your Reporting Services with the many great enhancements in SQL Server 2008 R2. Lara will take you on a tour of all that is new in R2 including collaboration features, new visualizations, rendering enhancements, and new data sources. After this session you will wonder why they call R2 an "interim" release!

Tap, Tap, Tap – SSWUG Conference Starts Today


ssccdl_couch-laptop1_250x20
The SSWUG Ultimate Virtual Conference starts this morning.  Are you planning to take advantage of this opportunity?  The Rock Starspeakers are waiting in the channels, anticipating you every move.  But, have you registered?

It’s not too late.  If you can’t get to the sessions today, there is always tonight to go through and view them.  Just check out what the conference includes.

  • More than 75 technical sessions
  • New! Live sessions track – all live sessions, with speaker Q&A/interviews at the end of the day
  • On-Demand access to sessions for 45 days – miss a session? No problem.
  • Chat, Twitter Integration, SKYPE integration for Q&A
  • Experience-based learning – find out what you need to know from people that are using the technology every day
  • These are NOT sales presentations.
  • 6-Month SSWUG.ORG Membership (or membership extension), included!
  • ALL-ACCESS Pass: SQL Server and Business Intelligence with related SharePoint and .NET technologies – all included, one low price
  • Great vendor hall – learn about the best tools, technologies, publications and partners out there for your shop

Hope in and join the conference!  I’ll be there after my morning meeting.

Are You Registered?


ssccdl_couch-laptop1_250x20
It starts next week,the SSWUG Ultimate Virtual Conference on October 21-24.  This is an excellent opportunity to get the benefits of heading to a conference full of Rock Star speakers while being able to view the content from the comforts of home or your desk.

Have you registered?

If you haven’t registered yet, I really recommend that you do.  Heck, you can even use this discount (SPJSUVC09) to save a little on the registration.  But I’ve told you what to do, have I told you why.  Well, let’s take a look at some bullet points that describe the conference: ‘Cuz we all like bullet points.

  • More than 75 technical sessions
  • New! Live sessions track – all live sessions, with speaker Q&A/interviews at the end of the day
  • On-Demand access to sessions for 45 days – miss a session? No problem.
  • Chat, Twitter Integration, SKYPE integration for Q&A
  • Experience-based learning – find out what you need to know from people that are using the technology every day
  • These are NOT sales presentations.
  • 6-Month SSWUG.ORG Membership (or membership extension), included!
  • ALL-ACCESS Pass: SQL Server and Business Intelligence with related SharePoint and .NET technologies – all included, one low price
  • Great vendor hall – learn about the best tools, technologies, publications and partners out there for your shop

Are you jazzed?  Wait, I didn’t make you laugh.  Good sales pitches always include some laughter.  One more bullet point:

Yeah, that’s right.  And there just might be more humor at the one coming up.  So let’s get signed up.

Report Manager in Windows 7


failed-security-check-clowns-security-fail_big
While working on some questions for a project I am working on, I ran into an issue with Report Manager today.  I haven’t had the pleasure of running into this issue in a while and thought I would share the issue and the resolution because it affects both Windows 7 and Vista.

Between this time and the previous few times I’ve dealt with this, I’ve spent more than time that I should on it and it does telegraph well into a second issue that I’ll talk about at the end.  And the easiest way for me to remember things is to write them down.

Your First Time

When going into Report Manager for the first time after installing it on my laptop I got the following screen:

RM_Win7_1

Not a very exciting screen.  Reporting Services is nice and secure because, as a user, I couldn’t do anything.  But since doing something was what was needed, figuring this out was required.

I started by going out and checking the Reporting Services configuration.  When the configuration tool is opened in Windows 7 and Vista it asks the user if they want to allow the program to make changes to the computer.

Ah-ha! Security?!

I never setup any security for Reporting Services after the installation.  By default, Reporting Services makes the BUILTIN\Administrators account an administrator to Reporting Services.  I was running Internet Explorer but I wasn’t running it as a user, not as an administrator.  So while I was using

Setting Up The First User

To get started, start up Internet Explorer as an administrator.  To do this right-click on Internet Explorer in the menu and select “Run as administrator”.  BTW, you should check out Live Mesh if you haven’t it’s great for synchronizing folders.

RM_Win7_3

Next go to Site Settings and select the Security tab.  You’ll notice that only the BUILTIN\Administrators have access after the installation.  This was the problem initially because Internet Explorer from regular launch didn’t acknowledge these permissions.

RM_Win7_4

Select New Role Assignment and add yourself in as a  System Administrator.

RM_Win7_5

Next go to Home and select Properties and go to the Security tab.

RM_Win7_6

  Select New Role Assignment and add yourself in as a  Content Manager.

RM_Win7_7

Now close Internet Explorer and open it back up.  Browse to the Reporting Services site and you should be able to do everything you expected to be able to do before.

RM_Win7_8

Bad Default Behavior?

Now, you might be thinking this is all pointless and definitely a bug.  Truthfully it’s not, Internet Explorer is running under minimum permissions which you really want it to do.  The lower the permissions that you are cruising the internet with, the better.  Unless you like viruses then the worse.

Also, the BUILTIN\Administrators account should be removed as a user and administrator from Reporting Services as soon as the “real” administrators have been added.  No sense leaving a whole in your Reporting Services site for administrators from other systems to get access to reports that they shouldn’t have access to.

Analyzing Report Execution Time


fob_watch2
One of the reasons I was digging around to find out how many reports were being executed for each folder the other day was that there were some subscription issues at the client.  The goal was to get a break down of when reports were being executed and generally who’s reports they were.

With that information in hand the topic quickly shifted to which reports were taking the most resources on the Reporting Services instance.  There are a number of ways to go about this but for this case I wanted to know how long it took from the when the report was requested until it was delivered to the user.

Like in the last post, this information can be gleamed from the ExecutionLog table in the Report Server database.  There are five columns that I use to get execution time information:

  • TimeStart – Time that the report execution begins
  • TimeEnd – Time that the report execution completes
  • TimeDataRetrieval- Time spent running retrieving data from data sources
  • TimeProcessing – Time spent processing the report
  • TimeRendering – Time spent rendering the report in the requested format

Note: that the execution time for the report for TimeDataRetrieval, TimeProcessing, and TimeRendering does not equal the difference between TimeStart and TimeEnd.  This is because there are other operations performed while executing and returning reports that are not tracked.

As with the other script, this query also includes start and end dates.  Here is the script:

DECLARE @StartDate datetime

    ,@EndDate datetime

 

SELECT @StartDate = '1/1/2009'

    ,@EndDate = '12/31/2009'

 

SELECT c.name

    ,c.Path

    ,COUNT(*) as Executions

    ,CAST(AVG(DATEDIFF(ms, TimeStart, TimeEnd)*1.)AS decimal(12,2)) AS AverageExecutionTime

    ,CAST(SUM(el.TimeDataRetrieval)/(COUNT(*)*1.) AS decimal(12,2)) AS AverageTimeDataRetrieval

    ,CAST(SUM(el.TimeProcessing)/(COUNT(*)*1.) AS decimal(12,2)) AS AverageTimeProcessing

    ,CAST(SUM(el.TimeRendering)/(COUNT(*)*1.) AS decimal(12,2)) AS AverageTimeRendering

    ,CAST((SELECT ' Count = "' + CAST(COUNT(*) as varchar) + '"'

            + ' Value = "' + COALESCE(CAST(iel.Parameters as varchar(max)), '-NONE-') + '"'   as Parameters

        FROM dbo.ExecutionLog iel

        WHERE iel.TimeStart BETWEEN MIN(el.TimeStart) AND MAX(el.TimeStart)

        AND iel.ReportID = el.ReportID

        GROUP BY COALESCE(CAST(iel.Parameters as varchar(max)), '-NONE-')

        ORDER BY COUNT(*) DESC

        FOR XML PATH('')) as xml) as Parameters

FROM dbo.ExecutionLog el

    INNER JOIN dbo.Catalog c ON el.ReportID = c.ItemID

WHERE el.TimeStart BETWEEN @StartDate AND @EndDate

GROUP BY c.name, c.Path, el.ReportID

ORDER BY SUM(el.TimeDataRetrieval) DESC

Running the script on my laptop shows the reports that have been executed.  As you can tell, I am a reporting fiend.  Take a look at the output below":

ssrs2

Do note the last column.  This column has an XML document that summarizes all of the parameter variations that were used to with the report in the given timeframe with a count of the number of executions.  For my purposes, I looked at the reports that were executed most frequently.

When I clicked on the XML link in the first row, it opened the following document:

<Parameters> Count = "1" Value = "ShowDescription=False&amp;StartDate=01/01/2002 00:00:00&amp;EndDate=12/31/2003 00:00:00"</Parameters><Parameters> Count = "1" Value = "ShowDescription=False&amp;StartDate=1/1/2002 12:00:00 AM&amp;EndDate=12/31/2003 12:00:00 AM"</Parameters><Parameters> Count = "1" Value = "ShowDescription=False&amp;StartDate=1/15/2002 12:00:00 AM&amp;EndDate=12/31/2003 12:00:00 AM"</Parameters><Parameters> Count = "1" Value = "ShowDescription=False&amp;StartDate=6/15/2002 12:00:00 AM&amp;EndDate=12/31/2003 12:00:00 AM"</Parameters>

I’ve found that this query to be quite helpful in finding both the high execution time reports along with sample parameter strings that can be used to performance test the reports.

Finding Number of Reports Executed By Folder


Pile-771824m

While working with a client a couple weeks back, I was asked to determine the count of reports that were being executed under each folder off the root directory on the Reporting Services instance.  Each of the folders off the root directory represented a department at the client.

For the output, I decided that I wanted to break out the reports executed by each hour of the day to see where the traffic was occurring.  Then the columns would be named after the first level folders off the root directory with counts of the number of reports executed under each folder.

The script is setup to take any date range you’d like.  In the case with the client, I was looking at that data for the first of the month.  In the script below, I expanded it to execute for the entire year.

DECLARE @ColumnList table (FirstLevelFolder nvarchar(128))

 

INSERT INTO @ColumnList

SELECT DISTINCT REPLACE(LEFT(Path, CHARINDEX('/',Path + '/',2)),'/','')

FROM dbo.ExecutionLog el

      INNER JOIN dbo.Catalog c ON el.ReportID = c.ItemID

WHERE el.TimeStart BETWEEN @StartDate AND @EndDate

AND Path <> ''

 

DECLARE @Columns nvarchar(max)

      ,@SQL nvarchar(max)

      

SELECT @Columns = STUFF((

      SELECT ',' + QUOTENAME(FirstLevelFolder)

      FROM @ColumnList

      ORDER BY FirstLevelFolder

      FOR XML PATH('')      

      ), 1, 1, '') 

 

SET @SQL = 'SELECT StartHour, ' 

      + @Columns 

      + 'FROM (

            SELECT DATEPART(hh, TimeStart) as StartHour, REPLACE(LEFT(Path, CHARINDEX(''/'',Path,2)),''/'','''') as Path, COUNT(*) as Executions

            FROM dbo.ExecutionLog el

                  INNER JOIN dbo.Catalog c ON el.ReportID = c.ItemID

            WHERE el.TimeStart BETWEEN @StartDate AND @EndDate

            GROUP BY DATEPART(hh, el.TimeStart), REPLACE(LEFT(Path, CHARINDEX(''/'',Path,2)),''/'','''')) x ' 

      + 'PIVOT ' + 

      + '(SUM(Executions) FOR Path IN (' + @Columns + ')) AS pt;'; 

 

EXEC sp_executesql @SQL, N'@StartDate datetime, @EndDate datetime', @StartDate = @StartDate, @EndDate = @EndDate

There are two things to take away from this script.  The first is that logging in the reporting services provides a lot of information that can be used to see what the users are doing.  And second, with a little dynamic SQL data can be pivoted without knowing what the end columns will be.

I Didn’t Receive My Subscription


magnifyGuy

Ever have a Reporting Services (SSRS) subscription that didn’t fire off as you thought it should?  Or was SQL Agent offline when subscriptions should have been fired?  Or did you just create a subscription and want to find out if it’s been configured properly?

Fortunately all of the information is sitting neatly and plainly in your SQL Server database.  Unfortunately it the plainly part isn’t quite the truth.  If you’ve looked before, subscriptions are named with uniqueidentifiers.  These values don’t exactly read in a manner that help identify which subscription they correspond to.

The query below provides a list of all current subscriptions in SSRS and also the last execution date.  The final column has the SQL syntax that would be needed to start the job to execute the subscription.  A little modification and the query can also be used to find execution history on the subscription.

;WITH cte (job_id, job_name, execution_time, execution_order) 

AS 

( 

SELECT DISTINCT j.job_id 

    ,j.name 

    ,CONVERT(datetime, STUFF(STUFF(run_date,7,0,'/'),5,0,'/') 

        + SPACE(1) 

        + STUFF(STUFF(RIGHT('000000' + CONVERT(varchar(20), run_time), 6),5,0,':'),3,0,':'))

    ,ROW_NUMBER() OVER (PARTITION BY j.job_id ORDER BY CONVERT(datetime, STUFF(STUFF(run_date,7,0,'/'),5,0,'/') 

        + SPACE(1) 

        + STUFF(STUFF(RIGHT('000000' + CONVERT(varchar(20), run_time), 6),5,0,':'),3,0,':')) DESC)

FROM msdb.dbo.sysjobs j (nolock) 

    INNER JOIN msdb.dbo.syscategories c ON j.category_id = c.category_id

    LEFT OUTER JOIN msdb.dbo.sysjobhistory jh (nolock) ON j.job_id = jh.job_id 

WHERE c.name ='Report Server'

) 

SELECT 

    x.job_name 

    ,c.name 

    ,x.execution_time

    ,c.path 

    ,su.description 

    ,CONVERT(varchar(max), su.ExtensionSettings) as ExtensionSettings 

    ,'EXEC msdb..sp_start_job ''' + x.job_name + '''' as SQLStatement

FROM cte x 

    INNER JOIN dbo.Schedule sc ON x.job_name = CONVERT(varchar(100), sc.ScheduleID) 

    INNER JOIN dbo.ReportSchedule rs ON sc.ScheduleID = rs.ScheduleID 

    INNER JOIN dbo.Subscriptions su ON rs.SubscriptionID = su.SubscriptionID 

    INNER JOIN dbo.Catalog c ON su.Report_OID = c.ItemID 

WHERE execution_order = 1

ORDER BY 3, 2