cancel
Showing results for 
Search instead for 
Did you mean: 

Running multiple Crystal engines

Former Member
0 Kudos

Hello,

Currently, we have an application that has worked quite well with multiple crystal engines installed. A client can have a report that exports as they expect in say Crystal Reports 10 and also create new reports against Crystal Reports 11 (or Release 2). The client specifies (within a table in the our DB) which version of crystal to use with a given report and we have a report engine factory that returns the appropriate crystal engine to use for processing the report.

Now the problem...

I recently brought down the trial version of Crystal Reports 2008 and have attempted to create a .NET factory to deliver this report engine. If I only have Crystal Reports 2008 accessed from our application, it will work as expected (for the most part - some features from the RDC no longer exist - but that is another story). As soon as I attempt to run a report that requires a different crystal engine, the next engine in always fails.

For example, if I run a Crystal 11 report after a successful Crystal 2008 report I will receive an "Invalid TLV record" error during the call of the "OpenReport" method. At first I thought this was a possible bug in my code, but if I do the opposite (run the Crystal 11 report first then Crystal 2008), the Crystal 11 report will work without problems and then a Crystal 2008 report I will receive the error "Retrieiving the COM class factory for component with CLSID XXX failed due to the following error: 80000003" during the "OpenReport" method.

Has anyone else experience this problem? If so, is there a way to work around it?

Thanks in advance any help you can provide,

Tom

Accepted Solutions (1)

Accepted Solutions (1)

Adam_Stone
Active Contributor
0 Kudos

It appears that you are trying to use the RDC with CR2008. Unfortunately, CR XIR2 was the last version that shipped this SDK, there may be some of the files with CR2008 but they are not supported for public use. You must move to using the .NET SDK to use within Visual Studio .NET.

Former Member
0 Kudos

Thanks for the response.

No, as I stated I've created a .NET implementation of our report engine factory for Crystal 2008. If the client sets up a report to be run under this version, I use the .NET implementation. If the client chooses an earlier version of Crystal, it uses the original RDC.

It appears as if side-by-side crystal engines really don't work right anymore, but I'm hoping someone will have a "This is what you can do.." thought.

Thanks,

Tom

former_member183750
Active Contributor
0 Kudos

Interesting behavior. Let me try to duplicate it and get back

former_member183750
Active Contributor
0 Kudos

Thomas, I did a quick test and was not able to reproduce the issue. Here is what I did:

1) For simplicity, I used saved data reports

2) .NET 2005 app using the CR 2008 assemblies.

3) Code:

reportdocument1.Load("C:\Crystal\Chart.rpt")

CrystalReportViewer1.ReportSource = reportdocument1

4) VB 6 app using CR XI release 2 RDC

5) Code:

Set myReport = myApplication.OpenReport(CommonDialog1.FileName)

CrystalActiveXReportViewer1.ReportSource = myReport

CrystalActiveXReportViewer1.CrystalActiveXReportViewer1.ViewReport

Test 1) I ran the .net app. Left the report on the screen. Ran the VB 6 app, same report. No errors

Test 2) As above, different report. No errors.

Test 3) I ran the VB 6 app 1st left report on the screen. Ran .NET app second. No error

Test 4) As above, different report.

Test 5) I ran the .net app. Closed the app. Ran the VB 6 app, same report. No errors

Test 6) As above, different report.

Test 7) I ran the VB 6 app 1st. Closed the app. Ran .NET app second, same report. No error

Test 😎 As above, different report. No error.

It may be a good idea to see if you can duplicate the issue with two new simple apps using code as above...

Also, I am a bit confused on when you say you created a .NET factory. Can you define that? Do you mean a .NET app?

Former Member
0 Kudos

Ludek,

Thanks for trying to recreate this. A factory is a design pattern used to deliver objects of a similar interface to a requesting application.

In our case, I've create a report engine factory that at this point allows clients that own versions of Crystal Reports to generate them in the version that provides the best results for their needs. The original factory was written in VB6 because Crystal had the RDC object model. I have standard interface methods like "OpenReport", "CloseReport", etc that mimic the same method calls that exist. If a method has changed within the crystal engine that isn't a problem because the calling app simply knows to call the "OpenReport" method on our interface. Then our "OpenReport" method calls the appropriate method (which in the example is the "Load" method on the crystal engine) found on either the RDC or the .NET Crystal engine.

This is a very powerful implementation because clients can slowly migrate reports from earlier versions of crystal to newer version. We did this because our clients found that most of the time formating/layout changes on almost every version of Crystal and they need to "tweak" the report to get it to look the way the want. Some clients have hundreds of reports to migrate. This gives them time to migrate.

Now, I'm creating a new factory all implemented in .NET that currently only returns the Crystal 2008 engine. This implementation must be exposed as a COM interface because our application still runs in VB6 at the moment (plus we have to continue to support the other crystal engines). So with that, our application really has no crystal specific code in it, just calls to our generic interfaces to the engines, then we have a dll that converts these generic methods into the actual calls into the appropriate engine.

Your example doesn't really put both "engines" within one VB application. You would need to create a .NET dll that delivers the work over COM to truly match my scenario. I'm going to try and put together a very simple example of the two libraries (dlls) without a factory so you can see what I'm talking about.

Thanks,

Tom

Edited by: Thomas Yacko on Jul 9, 2008 8:40 AM

--- I realized that the "OpenReport" method is actually the "Load" method on the .NET engine method call list. Sorry. ---

former_member184995
Active Contributor
0 Kudos

Running our .NET assemblies through COM is not supported or tested on our end. It would not be expected to work in that scenario. Good luck and I hope you find a way to get it to work.

Jason

Former Member
0 Kudos

Jason,

Thanks for the response!

OK, so I still think this is a problem and I've proven it by only writing .NET code. Here is what I did. I created three C# projects within a solution:

1. A Crystal 11 Release 2 project that simply implements an interface that has three methods on it (OpenReport, RecordSelectionFormula, and CloseReport). This project implements the .NET Crystal objects from Crystal 11 Release 2).

2. A Crystal 2008 project that simply implements an interface that has three methods on it (OpenReport, RecordSelectionFormula, and CloseReport). This project implements the .NET Crystal objects from Crystal 2008).

3. A Windows project that simply calls on both of the above projects (both are referenced in this project) and calls "OpenReport", then "RecordSelectionCriteria" (in a MessageBox), and finally "CloseReport".

"OpenReport" - uses ReportDocument.Load.

"CloseReport" - uses ReportDocument.Close - extremely slow process!!!

"RecordSelectionFormula" - uses ReportDocument.RecordSelectionFormula (my interface implements a set/get)

As you can see I'm using NO COM at all. When running this test project, I get the "Retrieving the COM class factory for component with CLSID XXX failed due to the following error: 80000003." error even in this case.

Below is an example of the "Windows project" code. I have the entire example in a zip file that I can deliver to someone if they want to see exactly what I'm talking about. I just didn't see a way to attach the example zip file with this post.

=====================================================================

using System;

using System.Collections.Generic;

using System.Windows.Forms;

namespace TestProj

{

static class Program

{

/// <summary>

/// The main entry point for the application.

/// </summary>

[STAThread]

static void Main()

{

Application.EnableVisualStyles();

Application.SetCompatibleTextRenderingDefault(false);

try

{

TestProj.CrystalEngine crystal11Release2 = new CrystalEngine();

crystal11Release2.OpenReport("Place your report name here...");

MessageBox.Show(crystal11Release2.RecordSelectionForumla);

crystal11Release2.CloseReport();

// You will see this error with a COM error even though no COM is being used in the project???

TestProj.Crystal2008 crystal2008 = new Crystal2008();

crystal2008.OpenReport("Please your report name here...");

MessageBox.Show(crystal2008.RecordSelectionForumla);

crystal2008.CloseReport();

}

catch (Exception excep)

{

MessageBox.Show(excep.Message);

}

Application.Exit();

}

}

}

=====================================================================

Just to reiterate, I have no COM implemented in this example and yet the same problem occurs.

Any assistance with this problem would be greatly appreciated.

Thanks again,

Tom

Answers (3)

Answers (3)

Former Member
0 Kudos

Thanks, Trevor.

The error message is the same as the original post. I just rebooted the webserver and the report now runs correctly. Is there a limit on how long a dll can stay in memory? We haven't restarted this webserver in quite a while.

If necessary, I can log a support case, I was just hoping that given the current discussion here an answer might be a bit more readily forthcoming.

FYI, for the powers that control your website, I heartily urge them to invest in an overhaul. It's extremely difficult to find any useful information, and the terminology around logging support cases is truely wierd adn counter-intuitive.

Thanks again for your feedback.

Cheers!

Rich

Former Member
0 Kudos

Hi, I'm getting this error in a production application as of today. We have several versions of crystal on the webserver that hosts our browser applications. We're using .net code only. I'm not aware of any changes on this server, and the first report of this just reached me a few minutes ago. Due to the progression of application development, older applications have not yet been updated to use Crystal 2008. FYI, in production, we're using Crystal 2008 Runtime Service Pack 0 (zero) for .Net compatibility.

We have not had any issues running multiple versions of the runtime until just now.

I really need an answer on this to resolve the production problem.

Any ideas?

Thanks!

Rich

former_member200290
Contributor
0 Kudos

If this truly is a production issue I would suggest purchasing a support case. As our forum's rules of engagement <<https://www.sdn.sap.com/irj/scn/wiki?path=/display/home/rulesofEngagement>> say "Never assume that you are entitled to an answer. Remember: this is a community forum; people have jobs just like you and respond voluntarily. Perhaps nobody knows the answer."

The issue being reported in this is mostly concerning one application trying to reference multiple versions of Crystal, not necessarily multiple applications each referencing a specific version of Crystal. Nor have you given any error messages.

Trevor

former_member200290
Contributor
0 Kudos

Hi Tom,

I think I know what is going on in this case. Our ReportDocument object, though is a Managed .NET object it in turn calls COM object. The COM object in this case is the ReportClientDoc object which instantiates an In-Process Reoprt Application Server (In-Proc RAS). In-Proc RAS is our RAS server service that only exists inside the calling application's memory space.

What I believe is happening is that though you are calling the two different versions of Crystal in two different classes the In-Poc RAS server created by each of these projects are being created in your main application's memory space, and that these two different versions are conflicting with each-other.

In the same way you cannot have two of different versions of our server products on the same server you cannot have two of our In-Proc RAS services inside the Application. If you were to call these classes from two seperate executables it would work.

However this leads into another reason why you may have difficulty using our .NET framework from a COM application. Basically from a COM application you will be calling through Interop the .NET framework, which in turn through COM interop will be calling our In-Proc RAS. I am not certain but I feel that when you start going through multiple Interops you are increasing your chances of things not going 100%.

Trevor

Former Member
0 Kudos

Guys

I am having the same issue. Due to the fact that the ability to read and modify the SQLQueryString property is no longer possible in 2008 (please put this back in, beg beg), in order to move to 2008 i have had to implement the ability to run some reports in XI R2 and some in 2008 (for some of the new cross tab features in 2008). However I run into the same problem. It appears to me as follows.

1. If the user runs the application and only uses the reports that use the XI R2 engine there are no errors

2. If the user runs the application and only uses the reports that use the 2008 engine there are no errors

3. If they run a report in XIR2 and then run a report in 2008 they get an error when trying to run the 2008 report. The error says

Message OLE IDispatch exception code 0 from CrystalDecisions.CrystalReports.Engine: Retrieving the COM class factory for component with CLSID {D7F5D7C3-B06C-4CAC-BC47-A06E66D2EE9B} failed due to the following error: 80000003... (OLE IDISPATCH EXCEPTION CODE 0 FROM CRYSTALDECISIONS.CRYSTALREPORTS.ENGINE: RETRIEVING THE COM CLASS FACTORY FOR COMPONENT WITH CLSID {D7F5D7C3-B06C-4CAC-BC47-A06E66D2EE9B} FAILED DUE TO THE FOLLOWING ERROR: 80000003..)

4. If they run a report in 2008 and then run one in XIR2, when they run the one in XIR2 they get the TLV error

Message OLE IDispatch exception code 0 from Crystal Reports ActiveX Designer: Invalid TLV record... (OLE IDISPATCH EXCEPTION CODE 0 FROM CRYSTAL REPORTS ACTIVEX DESIGNER: INVALID TLV RECORD..)

To me this is saying that the services and resources used to run these reports are not getting unloaded completely when i close a report and hence the wrong version of the resources is being picked up and used to view the reports when they swap versions.

Questions:

1.Is this your take on the issue?

2. How can i completely unload all resources used by the RDC and .Net SDK when i close the viewer

or put another way, whats the best way to close the viewer so that ALL resources are closed. Please answer this irrespective of whether you think it's the issue or not

3. Tom, did you find a solution?

Thanks

John

former_member183750
Active Contributor
0 Kudos

As per Trevor's explanation, using the two engine versions has the potential to cause issues. Unless Tom has found an alternative solution, you are stuck with creating ADO .NET datasets and passing those to the reports. Since you have a SQL query, this should be possible(?). Re. putting "SetSQL" query back. I do not think this will happen. Setting SQL queries was leading to all kinds if issues between different databases, etc., and a dataset should resolve that.

Ludek

Former Member
0 Kudos

Thanks I am in the process of trying that.

Still one question though. If this is an issue with the in proc server being loaded in memory and staying there. I could solve this issue by being able to clear it from memory between calls. How do i do that?

Thanks

former_member200290
Contributor
0 Kudos

Really I don't know. If we look at pure .NET, just creating a .NET application then referencing a .NET managed library, there really isn't a way to unload it from your application. It will stay loaded forever or your application closes. This is by-design, and the way Microsoft made the .NET framework work.

You can test this by referencing something like the managed Microsoft report dll and creating a new blank Microsoft report. When destroying the object the managed library stays in memory.

The only technical way around this that I have been able to find is to create a seperate application domain and have the libraries loaded there. However I don't know how to create new app domains, nor how they work, so I cannot guarentee you that this is a viable option.

The short of the story is that once the .NET framework loads a dll, it stays loaded.

Trevor