Server side printing with Crystal .NET SDK
Most of the time web printing is done client side; so the end user goes to their local printer to pick up their reports.
However I run into questions from developers whose business needs require printing server side. Many times these printers are printers that are programmatically added to the server “on-the-fly”.
When support questions come in for this type of printing the issue is usually that nothing ends up printing, or an exception like a “Printer Not Found”, “Invalid Printer Name” is thrown.
Typically this is a permissions issue or it is an issue with the name of the printer being set in code. So the first test I have developer do is to either add this code to their application, or add a new ASPX page to their website with this code in it; then run it to see the results:
protected void Button1_Click(object sender, EventArgs e)
foreach (string strPrinter in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
When this runs it should list out your printers that are installed and able to be printed to. These names are also what you should be setting your printer name to in code. If you cannot see your printer here thent first thing to try is to look at Microsoft’s Kbase 184291. This Kbase will explain how to expose your printers to the account running your .NET application.
If you followed this correctly the aboce code should list your printer, if not you can use and application like processmonitor to find your permissions issue, or you can go through the kbase again. Until the above code works our SDK cannot print.
Now if the printer is listed and the Crystal Report still doesn’t print and throws an exception the next thing to do is to print to the same printer from your application directly from the .NET framework. The important thing is to do this as close to the time Crystal fails as possible.
We can accomplish this by catching the exception and print the exception to the printer. If the exception is printed then what this will tell us is if there is an issue with Crystal Reports, trouble shooting with process monitor is a good step. You could also create a forum post or phone case to get direct help from us.
If the exception is not printed to the printer, or the exception throws an exception, then there is another permission issue or the printers are still not setup correctly. Again process monitor may help here. But until you can print to the printer directly from your web application using the .NET framework itself, there is no way Crystal will be able to print to it.
So how do you print the exception to the printer?
1 – Create global StringReader variable:
private System.IO.StringReader myReader;
2 – Add the following function:
private void pdPrintDoc_PrintPage(object sender, System.Drawing.Printing.PrintPageEventArgs e)
// Common code taken from internet, probably MSDN.
float linesPerPage = 0;
float yPos = 0;
int count = 0;
float leftMargin = e.MarginBounds.Left;
float topMargin = e.MarginBounds.Top;
string line = null;
System.Drawing.Font printFont = new System.Drawing.Font(“Arial”, 10);
// Calculate the number of lines per page.
linesPerPage = e.MarginBounds.Height /
// Print each line of the file.
while (count<linesPerPage &&
((line = myReader.ReadLine()) != null))
yPos = topMargin + (count *
leftMargin, yPos, new System.Drawing.StringFormat ());
// If more lines exist, print another page.
if (line != null)
e.HasMorePages = true;
e.HasMorePages = false;
3- Finally encapsulate your Crystal Report’s code in a try-catch and in the catch add this code:
rptdoc.PrintToPrinter(1, true, 1, 1);
catch (Exception ex)
// create a print document object and add a print page handler
System.Drawing.Printing.PrintDocument pdPrintDoc = new System.Drawing.Printing.PrintDocument();
pdPrintDoc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(this.pdPrintDoc_PrintPage);
// Set the printer name from the report
pdPrintDoc.PrinterSettings.PrinterName = rptdoc.PrintOptions.PrinterName;
// Create the error exception and send it to a String Reader
string stringToPrint = “Failed to print report to printer: ” + rptdoc.PrintOptions.PrinterName +”\n” + ex.Message.ToString();
myReader = new System.IO.StringReader(stringToPrint);
Response.Write (“Error Message Sent to Printer”);
Though this code is in C# a simple google search should find you the equivelent in the langauge of your choice.