I have been using Crystal Reports to create crappy looking reports in my VB (yes, many many years ago,) VB.Net, and C# apps. I like it because I know it well and it is functional for the most part. However, every new version of Crystal Reports brings in a lot of new headaches. I have been maintaining an application which was kept as 32 bit app primarily because of Crystal Reports. So, this weekend, I decided to try to convert the app to 64 bit anyway.
My original environment was:
C# .Net 3.5 framework
Crystal Reports designed in XI
Reports use an Access MDB file with linked tables to various data sources.
I upgraded the environment to:
C# .Net 4.0 framework
Crystal Reports designed in XI
CR Run time upgraded to 13.0.4000.x.
CR for visual studio also upgraded to 13.0.26.x.
Reports still use an Access MDB file with linked tables to various data sources.
The original code to switch the Access database was as following:
My original environment was:
C# .Net 3.5 framework
Crystal Reports designed in XI
Reports use an Access MDB file with linked tables to various data sources.
I upgraded the environment to:
C# .Net 4.0 framework
Crystal Reports designed in XI
CR Run time upgraded to 13.0.4000.x.
CR for visual studio also upgraded to 13.0.26.x.
Reports still use an Access MDB file with linked tables to various data sources.
The original code to switch the Access database was as following:
string reportFile = "AppReport.rpt"; var rep = new ReportDocument(); rep.Load(reportFile); rep.Database.Tables[0].Location = @"c:\temp\run-rime-access.mdb"; crystRep.ReportSource = rep;Things worked as expected when I compiled the code explicitly as 32 bit (X86 mode.) 64 bit exe simply would not run with a variations of errors as followng:
Exception thrown: 'System.Runtime.InteropServices.COMException' in CrystalDecisions.CrystalReports.Engine.dll An unhandled exception of type 'System.Runtime.InteropServices.COMException' occurred in CrystalDecisions.CrystalReports.Engine.dll Error in File AppReport 11476_6424_{59713F00-ED10-4E5B-928E-1D8AC1A7832B}.rpt: Failed to load database information.
I googled and surprisingly did not find any solutions, which worked for me. I tried the uselegacyv2runtimeactivationpolicy attribute in app.config and/or assembly directives as suggested by SAP and StackOverflow posts, to no avail.
At this time, I also felt that it will be good idea to convert the mdb file to accdb, later editions of Microsoft Access database. Surprise, this version of Crystal still does not give a choice to connect to accdb, Access files. So, I started looking into ODBC connection options. I finally got it to work in 64 bit environment.
Here is what you need to do make all this work.
- Install CR for visual studio on your development machine. It's free. It's the same version for 32 and 64.
- Install CR 64 bit run time on the development machine. It is available for free at SAP site. You can install 32 bit run time at the same time.
- Install 64 bit ACE Driver on your development machine. You cannot install 64 bit driver at the same time. If you have 64 bit office installed on your machine, the installer will not even let you install 32 bit ACE driver.
- Here comes the hard part. You have to design you report using a 32 bit data source. As you can see if you do not have 32 bit ACE driver installed on your machine, you can not create a DSN for it. Crystal Reports does offer support for accdb natively. I overcame this issue by using a mdb version of the same access database. Look at the screenshot below. You can see that I have a dsn ash-lab-64bit, which uses 64 bit ACE driver. However in Crystal Reports designer I only see ash-lab-32bit dsn, which uses natively supported mdb (DAO) driver in Crystal Reports.
Good so far! You have designed the report using a 32 bit ODBC DSN. At run time we need to change this DSN to a DSN less connection.
C# Code to make it all work in 64 bit run time environment:
- Get rid of uselegacyv2runtimeactivationpolicy attribute from app.config.
- Use the following code if you still like DSN based connections. Keep in mind that every client will need this connection on his/her machine.
string reportFile = "Example3.rpt"; var rep = new ReportDocument(); rep.Load(reportFile); ConnectionInfo tConnInfo = new ConnectionInfo(); tConnInfo.DatabaseName = @"c:\temp\__run-time.accdb"; tConnInfo.ServerName = "ash-lab-64bit"; tConnInfo.Password = ""; foreach (CrystalDecisions.CrystalReports.Engine.Table crTable in rep.Database.Tables) { crTable.LogOnInfo.ConnectionInfo = tConnInfo; crTable.ApplyLogOnInfo(crTable.LogOnInfo); } crystRep.ReportSource = rep;
- Use the following if you like DSN less connection. This is what I prefer.
string reportFile = "Example3.rpt"; var rep = new ReportDocument(); rep.Load(reportFile); rep.DataSourceConnections[0].SetConnection(@"DRIVER=Microsoft Access Driver (*.mdb, *.accdb);UID=admin;UserCommitSync=Yes;Threads=3;SafeTransactions=0;PageTimeout=5;MaxScanRows=8;MaxBufferSize=2048;FIL=MS Access;DriverId=25;DefaultDir=C:\temp;DBQ=C:\temp\__run-time.accdb","",false); crystRep.ReportSource = rep;
Compile your code with "ANY CPU" or 64 bit setting.
Software do you need to make it work on the client machine:
- Crystal report 64 bit run time, available for free at SAP site.
- Microsoft's 64 bit ACE driver.
Add a comment