Custom Printer Delivery Extension rendering problem in 2008
We are moving our application from SSRS 2005 to SSRS 2008. In 2005 we have used custom printer delivery extension solution based on sample provided by Microsoft. It works fine.
In 2008, it print only first page. We investigate the problem and found that Image Render used to render report in EMF format does not return all pages. We search internet for solution and found that many people are facing same problem. At one place someone
suggested to iterate through all pages using <StartPage> in <DeviceInfo>. Below is the code snippet:
string deviceInfo = String.Format(
System.Globalization.CultureInfo.InvariantCulture,
@"<DeviceInfo><OutputFormat>emf</OutputFormat><PageHeight>{0}</PageHeight><PageWidth>{1}</PageWidth><PrintDpiX>{2}</PrintDpiX><PrintDpiY>{3}</PrintDpiY><StartPage>#PAGE_NO#</StartPage></DeviceInfo>",
pageHeight, pageWidth, printX, printY);
// Render report
RenderedOutputFile[] output = null;
List<RenderedOutputFile> m_files = new List<RenderedOutputFile>();
bool doRenderPage = true;
int page = 0;
while (doRenderPage)
{
doRenderPage = false;
try
{
// If we specify 0 (zero) for <StartPage> then 2005 return all pages while 2008 return first page only.
output = notification.Report.Render("IMAGE", deviceInfo.Replace("#PAGE_NO#", page.ToString()));
// This check whether page is available or not
if (output != null && output.Length > 0)
{
// This condition will be true for 2005 with multiple page reports
if (output.Length > 1)
{
m_files.AddRange(output);
}
// This means that report is render from 2008 or single page report from 2005
else if (output[0].Data != null && output[0].Data.Length > 0)
{
page = (page == 0) ? 2 : page + 1;
m_files.Add(output[0]);
doRenderPage = true; // We are not aware of total pages so let try to fetch next page..
}
}
}
catch
{
}
}
As there is no way to get total pages we have to iterate through each page as shown above.Knowing total pages will also not help us as even if I specify <StartPage> and <EndPage> it render single page.
This is creating bottleneck in performance for schedule report to print on specified printer as it fire SP to collect data for each page. So for example if report is of 30 pages then we are looping and calling Render method 30 times and this in turn call
our SP 30 times.
Is there any other way in which we can achieve this functionality?
Rakesh Patel
March 30th, 2011 5:43am
Hi Rakesh,
I am trying to involve someone familiar with this topic to a further look at this issue. There might be some time delay. Appreciate your patience.
Thank you for your understanding and support.
Thanks,
Jerry
Free Windows Admin Tool Kit Click here and download it now
March 31st, 2011 9:33pm
Thanks Jerry. I will be waiting for your reply.
April 4th, 2011 9:41am
Hi Jerry,
Any update on this issue?
Regards,
Rakesh Patel
Free Windows Admin Tool Kit Click here and download it now
April 12th, 2011 4:52am
Hello Rakesh,
Can you please confirm if the post,
http://social.msdn.microsoft.com/Forums/en/sqlreportingservices/thread/0d9d2b53-117c-4cec-9e51-3b678720a75e, helped?
To test if this is an Image Renderer issue, did you try exporting your report to PDF and then printing? I am just trying to understand the format of the report you used to print. PDF also uses the Image Renderer and may show the same symptom if this is an
image rendering issue.
From the rsreportserver.config:
<Extension Name="PDF" Type="Microsoft.ReportingServices.Rendering.ImageRenderer.PDFRenderer,Microsoft.ReportingServices.ImageRendering"/>
Since this is custom code and since the custom printer delivery extension sample should be used only as educational purpose (http://msdn.microsoft.com/en-us/library/ms160778.aspx),
we do not have technical support for the extension but we can research if there is any issue with the image renderer as you mentioned in the thread.
What is the build number of SSRS that you are using? Can you please share the whole SSRS log file during the time of the issue?
Thanks,
Cathy Miller
Microsoft Online Community Support
April 12th, 2011 9:47am
Hi Cathy,
Thanks for your response. We understand that printer extension is for education purpose. But we are actually facing problem with Image Renderer and not the extension.
I checked the link and its related to issue of scaling in 2008.
PDF Render is working fine. It give me all pages at a time.
Problem is with Image Renderer and that too when I specify for "EMF" format. If I specify "TIFF"
format all pages are returned. When I print TIFF format on printer report quality is not good.
EMF format does not repect <StartPage> and <EndPage> information provided in DeviceInfo parameter.
How can I get all pages of a report using EMF format in single call of Image Renderer?
How can I upload log file?
Regards,
Rakesh Patel
Free Windows Admin Tool Kit Click here and download it now
April 14th, 2011 10:03am
Hi Cathy,
Thanks for your response. We understand that printer extension is for education purpose. But we are actually facing problem with Image Renderer and not the extension.
I checked the link and its related to issue of scaling in 2008.
PDF Render is working fine. It give me all pages at a time.
Problem is with Image Renderer and that too when I specify for "EMF" format. If I specify "TIFF"
format all pages are returned. When I print TIFF format on printer report quality is not good.
EMF format does not repect <StartPage> and <EndPage> information provided in DeviceInfo parameter.
How can I get all pages of a report using EMF format in single call of Image Renderer?
How can I upload log file?
Regards,
Rakesh Patel
April 14th, 2011 5:00pm
Hi Cathy/Jerry,
Any updates on this? I am waiting for the solution.
Regards,
Rakesh Patel
Free Windows Admin Tool Kit Click here and download it now
April 19th, 2011 4:18am
Hi Cathy,
Can you please confirm that there is bug in Image Renderer of SSRS 2008?
Is there any work around for this bug?
Regards,
Rakesh Patel
April 27th, 2011 2:22am
Hi Rakesh,
We are still researching this issue. Can you please confirm the build number of the SSRS 2008 you are using?
Thanks,
Cathy Miller
Microsoft Online Community Support
Free Windows Admin Tool Kit Click here and download it now
April 28th, 2011 11:20am
Hi Cathy,
We have tested on both Developer and Enterprise edition of SSRS.
Here is the product information (extracted from log file):
Enterprise => Microsoft SQL Server Reporting Services Version 2009.0100.1600.01 ((KJ_RTM).100402-1539 )
Developer => Microsoft SQL Server Reporting Services Version 2009.0100.1600.01 ((KJ_RTM).100402-1540 )
Regards,
Rakesh Patel
April 29th, 2011 4:18am
Hi Rakesh,
The Image rendering extension generates the EMF format. EMF format works with a single stream containing a single page. Retrieving additional pages requires additional streams. The TIFF format, on the other hand, has multiple pages in a single stream,
hence you are getting multiple pages.
This is documented in the following MSDN article:
Exporting to an Image File
http://msdn.microsoft.com/en-us/library/ms159216.aspx
To handle this situation, you would need to use the persisted streams feature.
Please refer to the following blog, regarding persisted stream.
EMF Rendering and Persisted Streams
http://blogs.msdn.com/b/jgalla/archive/2007/05/24/emf-rendering-and-persisted-streams.aspx
Also the following blog has an example on how to handle the persisted stream (shows with ReportViewer)
Manually Printing a Report
http://blogs.msdn.com/b/brianhartman/archive/2009/02/27/manually-printing-a-report.aspx
Other related blog (s):
SQL Reporting Services 2008 vs SQL Reporting Services 2008 R2 - problem with streamIDs always being nothing
http://social.msdn.microsoft.com/Forums/en-US/sqlreportingservices/thread/b704d524-09a2-43b3-b4f3-708b8def4dea
Note: There are some changes in SSRS 2008 R2 to handle the Persisted Steam better to tackle other scenarios.
Hope this helps.
Thanks.
Cathy Miller
Microsoft Online Community Support
Free Windows Admin Tool Kit Click here and download it now
May 2nd, 2011 1:38pm
Hi Cathy,
Thanks for the links but none of them addresses my issue. Links addresses problem related to Report Viewer and accessing report through Web URL.
My scenario is related to delivery extension. SSRS invoke my delivery extension class for particular report that is scheduled. SSRS pass required information to my delivery extension object and I just call Render method.
I know that EMF works with single stream and thats the reason SSRS 2005 returns multiple streams for report
(1 for each page). This behaviour is broken in SSRS 2008.
Regards,
Rakesh Patel
May 3rd, 2011 8:10am
Hi Cathy,
Today I try to dig into the SSRS assembly (ReportingServicesLibrary) using Reflector and here are my findings.
SSRS pass "Microsoft.ReportingServices.Library.NotificationImpl" object instance as parameter to "IDeliveryExtension.Deliver(Notification)"
method of my delivery extension class. NotificationImpl instance expose property "Report" which hold instance of "Microsoft.ReportingServices.Library.ReportImpl" type. We are calling Render() method of ReportImpl type to generate
report in EMF format.
Render() method of ReportImpl class loop through the streamIds and create array of RenderOutputFileImpl. As there is problem in
SSRS 2008 with streamIds (refer to the link you have provided) it will return single stream.
-------------------------------------------------------------------------------------------
foreach (string str2 in streamIds)
{
RenderedOutputFileImpl impl2 = new RenderedOutputFileImpl(this, str2);
list.Add(impl2);
}
---------------------------------------------------------------------------------------
Is there any workaround for this?
Regards,
Rakesh Patel
Free Windows Admin Tool Kit Click here and download it now
May 4th, 2011 7:23am
Hi Rakesh,
There was a design change in SSRS 208 R2, the behavior that you are seeing is by design in SSRS 2008 R2. Here is the connect site, that is discussing the issue (this also discusses a possbile work around that one of the users are using):
https://connect.microsoft.com/SQLServer/feedback/details/560911/sql-2008-r2-reportexecutionservice2005-broken-with-image-emf
Another connect site that is also discussing the same issue:
https://connect.microsoft.com/SQLServer/feedback/details/573997/with-ssrs-2008-r2-microsoft-reporting-winforms-serverreport-render-method-returns-no-stream-identifiers-for-image-format
The blog,
http://social.msdn.microsoft.com/Forums/en-US/sqlreportingservices/thread/b704d524-09a2-43b3-b4f3-708b8def4dea, addresses the issue in details,
See
http://msdn.microsoft.com/en-us/library/reportexecution2005.reportexecutionservice.render(v=SQL.105).aspx
StreamIds
[out] The stream identifiers. These IDs are passed to the
RenderStream method. You can use them to render the external resources (images, etc.) that are associated with a given report.
If the IMAGE rendering extension is used, the method outputs an empty array inStreamId
Although it's a break change, it does fix a spurious bug regarding stream cache. It was a change in SQL Server 2008 R2 internal RC. Please use DeviceInfo StartPage instread, like"<DeviceInfo><OutputFormat>EMF</OuputFormat><StartPage>2</StartPage></DeviceInfo>".
The workaround is to use the Persisted Stream. The sample from blog
http://blogs.msdn.com/b/brianhartman/archive/2009/02/27/manually-printing-a-report.aspx, although related to reportviewer, shows the example on how to use the Persisted Stream, we will have to use the concept from this sample.
From the connect site,
https://connect.microsoft.com/SQLServer/feedback/details/573997/with-ssrs-2008-r2-microsoft-reporting-winforms-serverreport-render-method-returns-no-stream-identifiers-for-image-format, this might be helpful also:
The reliable way to determine hard page count is to do the same thing that Print Layout and Print Preview do, which is make multiple rendering requests using the persisted streams feature and count the non-empty response streams. The first rendering request
specifies PersistStreams=True, and subsequent requests instead specify GetNextStream=True until the server returns an empty stream. See http://msdn.microsoft.com/en-us/library/ms152835(v=SQL.105).aspx for more information on URL Access parameters. (Note that
the command name PersistStreams should be plural.)
Hope this helps.
Thanks.
Meer Alam
Microsoft Online Community Support
May 8th, 2011 8:58pm
Hi Meer Alam,
Links are reffering the issue while using SOAP API or Report Viewer control. My problem is different. I am writing Delivery extension and calling Render() method of "Microsoft.ReportingServices.Library.ReportImpl" that SSRS pass to my deliver
extension class instance. This (Microsoft.ReportingServices.Library.ReportImpl) class too have issue related to streamids and as a result it does not return requested pages for EMF format.
Can you suggest any workaround for this?
Regards,
Rakesh Patel
Free Windows Admin Tool Kit Click here and download it now
May 10th, 2011 8:39am
Hello Rakesh,
Did you have a chance to take a look into the connect site:
https://connect.microsoft.com/SQLServer/feedback/details/560911/sql-2008-r2-reportexecutionservice2005-broken-with-image-emf? Did you try following the workaround mentioned there, "Posted by
JasonRAC on 6/8/2010 at 11:34 AM"?
--------------------------------------------------------------------------------------------
I no longer use:
Private Function renderReport(ByRef streamIds As String()) As List(Of Metafile)
Dim result As Byte()
Dim ext As String, mimeType As String, encoding As String
Dim warnings As Warning()
result = Client.Render(My.Settings.ReportFormat, My.Settings.DeviceInfo, ext, mimeType, encoding, warnings, _
streamIds)
Dim pages As New List(Of Metafile)()
Dim memStream As New MemoryStream(result)
pages.Add(New Metafile(memStream))
Return pages
End Function
Private Sub renderStream(ByVal streamId As String, ByVal pages As List(Of Metafile))
Dim mimeType As String, encoding As String
Dim result As Byte() = Client.RenderStream(My.Settings.ReportFormat, streamId, My.Settings.DeviceInfo, encoding, mimeType)
Dim memStream As New MemoryStream(result)
pages.Add(New Metafile(memStream))
End Sub
I added a new method to render the report:
Private Function renderReportR2(ByVal Page2Render As Integer, ByVal pages As List(Of Metafile)) As Boolean
Dim result As Byte()
Dim ext As String, mimeType As String, encoding As String, streamIds As String()
Dim warnings As Warning()
Dim retValue As Boolean = True
Try
result = Client.Render(My.Settings.ReportFormat, My.Settings.DeviceInfo.Replace("#PAGE#", Page2Render.ToString("N0")), ext, mimeType, encoding, warnings, _
streamIds)
Dim memStream As New MemoryStream(result)
pages.Add(New Metafile(memStream))
Catch ex As Exception
retValue = False
End Try
Return retValue
End Function
And I changed the runReport method to:
Private Function runReport(ByVal parameters As Dictionary(Of String, String)) As List(Of Metafile)
setParameters(parameters)
Dim pages As List(Of Metafile) = New List(Of Metafile)
Dim bDone As Boolean = False, intCurrentPage As Integer = 1
Do While Not bDone
bDone = Not renderReportR2(intCurrentPage, pages)
intCurrentPage += 1
Loop
Return pages
End Function
And my DeviceInfo string looks like:
<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<StartPage>#PAGE#</StartPage>
<PrintDpiX>96</PrintDpiX><PrintDpiY>96</PrintDpiY>
</DeviceInfo>
Hope this helps someone else - actually I hope someday soon nobody needs this once this is "fixed".
--------------------------------------------------------------------------------------------------------------------
Unfortunately, I could not find any sample that shows how to use the persisted stream, with the "Microsoft.ReportingServices.Library.ReportImpl.Render" method, other than the one from
http://blogs.msdn.com/b/brianhartman/archive/2009/02/27/manually-printing-a-report.aspx
Thanks.
Meer Alam
Microsoft Online Community Support
May 10th, 2011 12:34pm
Hi Meer Alam,
I have gone through the connect site link and used workaround to retrieve all pages of report in EMF format (please refer code in first post). Problem with this workaround in delivery extension is that SP is execute each time I ask for page. So if my report
is of 5 pages then SP will execute 5 times.
Post on connect site use Report Viewer control and that internal use SOAP API to render report. I think Report Viewer control use SessionHeader to place multiple request to SSRS as a result manage to use previously generated dataset from SP.
Microsoft.ReportingServices.Library.ReportImpl.Render method only take rendering type (image, pdf, etc.) and device information as parameter. There is no way to pass other informations that one can with Report Viewer control.
Delivery extension run under SSRS window service process. Its bad design to create proxy of SSRS web service (or report viewer control) in delivery extension class and use SOAP API to render the report.
Regards,
Rakesh Patel
Free Windows Admin Tool Kit Click here and download it now
May 11th, 2011 10:22am
Hello Rakesh,
Unfortunately,
Microsoft.ReportingServices.Library.ReportImpl.Render does not support persisted stream, as you probably already have seen. You would have to use URL Acces (http://technet.microsoft.com/en-us/library/ms152835.aspx)
or ReportViewer API.
I apologize, but, at this point, I could not find any other way to get around the issue.
Hope this clarifies.
Thanks.
Meer Al - MSFT
May 31st, 2011 8:58pm


