XE6 ClientDataSet AV attempting to load data from Firebird - delphi

I have a minimalist project with FireDac FDConnection & FDSqlQuery,
DataSetProvider and ClientDataSet, trying to access the example
Employee.FDB that came with the Firebird 2.5 package I downloaded
from SourceForge today.
Everything is set to the defaults as theycame off the palette apart from the database name in the FDConnection's pop-up Information tab and the FDQuery's Sql, which is set to select * from employee.
The FDQuery opens fine but as soon as I try
to open the CDS, in the IDE or running my app, I get an access violation.
This is all my code:
FDQuery1.Open;
Caption := IntToStr(FDQuery1.RecordCount); // this shows 42 on the form's caption
CDS1.Open; // AV here
So, the FDQuery opens ok but the CDS doesn't.
At run time, the exception occurs here:
function TCustomClientDataSet.CreateDSBase: IDSBase;
begin
CreateDbClientObject(CLSID_DSBase, IDSBase, Result);
Check(Result.SetProp(dspropANSICODEPAGE, DefaultSystemCodePage)); <-- Exception here
Check(Result.SetProp(dspropUTF8METADATA, NativeUInt(True)));
Check(Result.SetProp(dspropUTF8ERRORMSG, NativeUInt(True)));
end;
The exception msg is
Project FBTest1 raised exception class $C0000005 with
message 'access vioaltion at 0x0075d05b: read of address 0x00000000'.
In the IDE I get a similar exception if I try to set Active = True on the CDS,
which the message said occurred in DSnap200.Bpl.
The first time it happened at run-time I had some kind of "Incident Report" pop-up
offering to report it to Embarcadero. First time I've seen that.
If I substitute a SqlConnection and SqlQuery for the FDac components, I get
the same error.
So, I guess my question is, can a CDS be provoked into this behaviour simply by using default property settings for a project as simple as this one, i.e. did I miss a step, or is it likely an EMBA QC thing?

Solved! Thanks to Graymatter's suggestion to try Using MidasLib, I've got
to the bottom of the problem and fixed it so that the app now works using Midas.Dll. I'm posting this as an answer, rather than a comment, firstly because it's a bit too long for that, but, more importantly, the cause was actually rather strange and the solution may assist anyone else who runs into the problem.
First, I tried Using MidasLib, and the app ran fine, w/o the AV that the q is about.
So, reassured that the problem doesn't arise with the current MidasLib code, I went
back to trying to get the app to work with Midas.Dll. I checked the Midas.Dll
versions in the XE6 bin directory and \Windows\SysWOW64, and they were both as I
was expecting, 20.0.16277.1276 dated 16 June 2014.
Tracing into CheckDBlient in DataSnap.DSIntf and observing carefully, the penny
dropped and I realised what was happening:
procedure CheckDbClient(const CLSID: TGUID);
[...]
begin
[...]
if DbClientHandle = 0 then
begin
Size := 256;
SetLength(FileName, Size);
if RegQueryValue(HKEY_CLASSES_ROOT, PChar(Format('CLSID\%s\InProcServer32',
[GUIDToString(CLSID)])), PChar(FileName), Size) = ERROR_SUCCESS then
SetLength(FileName, Size) else
begin
[...]
end;
DbClientHandle := LoadLibrary(PChar(FileName));
This gets the path to Midas.Dll from the InProcServer key in its registration, and this
wasn't pointing to XE6's bin directory or SysWOW64, but to another location that was not
of my creation and which contained a version of Midas.Dll dating from 2007. Oddly, unlike a copy I have of the Dll dating from the D7 era, this Dll does not have version info on its property page but it has a creation date of 9 August 2002 and a file size of 351Kb.
So, once I'd found that, fixing the problem was as simple as renaming that Dll so that
the OS won't load it, and re-registering the version in SysWOW64.
Where the rogue Midas.Dll came from isn't clear, but it certainly arrived since
last week, because it isn't in the back-up I happen to have from last Thursday evening.
The only things I've installed since then are a handful of 3rd-party GUI utilities for
managing/accessing Access, IB and Firebird databases, so the culprit seems to have been
one of them.

Related

Can't use DeleteFile() unless running program as admin, even with full control privileges

Our program is something like this:
C:\Main
C:\Main\Utils
C:\Main\App.exe
For C:\Main and all subfolders, we have all privileges for Everyone set to allow Full Control.
In our code, we create a .bmp file:
BmpSt := TMemoryStream.Create;
BmpSt.SetSize(Length(dta));
BmpSt.WriteBuffer(dta[1],Length(dta));
BmpSt.Seek(0,soFromBeginning);
Bmp := '\Main\Util\' + FormatDateTime('YYYYMMDDHHNNSS',Now) + '.bmp';
BmpSt.SaveToFile(Bmp);
if not DeleteFile(Bmp) then begin
ShowMessage('No');
end;
If I don't run App.exe as an administrator, it will never delete the file. However, when I do run it as an administrator, it deletes the file just fine.
Privileges are set to Full Control for Everyone.
I know this might not exactly be a Delphi question since its heavily dealing with Windows UAC, but this code worked fine when our program was in Delphi 5, now we are building it in Delphi 10.
We are also getting similiar issues using a TPrinter object to insert the above .bmp onto a print page, but I'm confident that the issues with DeleteFile will solve those.
Right after using DeleteFile() you can use GetLastError() to get what went wrong and trigger an exception for it with CheckOSError(). Once you know why it is failing you can troubleshoot further.
if not deletefile(bmp) then begin
CheckOSError(GetLastError);
end;

Issue with TFDQuery on a form connecting to a datamodule

I have a datamodule with a TFDConnection connecting to a SQLLite db.
Queries on the datamodule work fine. But if I have a query on a form connecting to the connection on the datamodule when setting Active to true I get the error:
exception message : [FireDAC][Comp][Clnt]-512. Connection is not
defined for [FDQuery1]. Possible reason: Connection and ConnectionName
property values
This happens in design time.
This is with Delphi Tokyo in a Firemonkey mobile app.
I think this may be a FireDAC (or IDE) bug which has been introduced between Delphi Seattle an Tokyo (10.2). I found I could reproduce it as follows:
Create a new multi-device (FMX) project in Seattle.
Add a datamodule to the project and add an FDConnection to it. I configured the FDConnection to use the MSSQL driver, set the connection to use OS Authentication, my local Sql Server and an existing db on it. I set LoginPrompt to false.
I added FDQuery1 to the form, made the form USE the datamodule's unit, then set FDQuery1's connection to the one on the datamodule and added "select * from mytable" as its Sql. Then I set FDQuery1.Active to true in the OI. FDQuery1 opened without complaint. I reset FDQuery1.Active to false, saved the project and closed it.
I closed Seattle, started Tokyo and opened the project. When I set FDQuery1.Active to true, I got the exact same exception message as you have reported. Interestingly, the OI then updates FDQuery1.Active to display True.
I then set FDQuery1.Active to false then true, and the exception did not occur.
I closed and restarted Tokyo, re-opened the project and, again, the first time (but only the first time) I set FDQuery1.Active to true, the exception occurs again.
You are welcome to include the above steps in a problem report to Emba. Btw, I didn't spend any time investigation the run-time behaviour of the project.
At a guess - and it is only a guess - there is a problem somewhere in the IDE which manifests when it has to create an instance of the datamodule so that it's FDConnection can establish the connection needed to open FDQuery1. If that's right, it shouldn't affect the run-time behaviour but like I say, I have not investigated that. If I'm right, I think it's more of an annoyance than a major problem.
Update: This problem seems to be FMX-specific. I repeated steps 1-3 in a new Tokyo VCL project and the exception + error message does not occur, even the first time FDQuery1.Active is set to true.
Update#2: This problem is easily reproducible at run-time. All you need to do is to remove the datamodule from the Project's Forms | AutoCreate list and then, at run-time, attempt to open the FDQuery before the datamodule has been created. Obviously, the work-around is simply to check that the datamodule exists before opening the FDQuery and, if not, to create it in code.
Btw, in a real-world application, personally I wouldn't rely on a TDataSet's Active property setting in the IDE to open the dataset, and always open it in code instead. It's a habit I got into in the early years of Delphi, when there often seemed to be problems with design-time settings of datasets and datasources which referred to a db connection or similar located in another module being "lost" at run-time.
I was getting this same bug using Delphi 10.3 Community Edition in Windows VCL Application. Even though my FDQuery has a valid connection.
I found out in the Embarcadero Delphi CE Bootcamp 2018 course Week 4 of Databases that the problem is because your DataModule was created after your Form.
To fix that you should go to:
Project --> Options --> Application --> Forms
In Autho-create forms you should notice this sequence:
Form1
DataModule1
And you should change the order so DataModule is first:
DataModule1
Form1
In case your connection is placed in the DataModule, you must first connect your connection and then after activated your query. Your query can not be activated before your connection is connected.
Connect in your connection (This can be done in the DataModule);
Activate the query (Let's say it is in your MainForm).
If you create the form before your DataModule, the query will accuse that there is no connection, because the datamodule connection was not created yet.
You also can change the sequence of the created forms programmatically in Project --> View Source.
Check the following code.
program FDSearchInst;
uses
Vcl.Forms,
UnitMain in 'UnitMain.pas' {FormMain},
UnitDataPaths in '..\SharedFiles\UnitDataPaths.pas',
UnitDataModule in '..\SharedFiles\UnitDataModule.pas' {SharedDM: T};
{$R *.res}
begin
ReportMemoryLeaksOnShutdown := True;
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TSharedDM, SharedDM); // Will be created first
Application.CreateForm(TFormMain, FormMain); // Will be created after
Application.Run;
end.
In this code, you may also notice a problem I have been through. There is a comment {SharedDM: T} in front of the DataModule path which is a way to assign a name for your DataModule (when you access the Application --> Forms you will see this name).
This name SharedDM must be different from the file name UnitDataModule, otherwise, it will cause conflict and you'll not be able to run your project.
To explain better, check the following code:
Correct
UnitDataModule in '..\SharedFiles\UnitDataModule.pas' {SharedDM: T};
Incorrect
UnitDataModule in '..\SharedFiles\UnitDataModule.pas' {UnitDataModule: T};

Assertion failure in DBAccess.pas

I am interested in upgrading a suite of software from ODAC v5 to v8.2.8.
One app in particular is causing problems. This application loads one of a set of secondary applications implemented as dlls.
LibHandle := LoadLibrary(PChar(dllname));
if LibHandle <> 0 then
begin
#showForm := GetProcAddress(LibHandle,'ShowMainDllForm');
if (#showForm <> nil) then
begin
try
ShowForm(Application.Handle, #FGlobalVars, 1);
The launcher is fine - it has its own database connection, and I can step through the various ODAC units fairly happily.
However, the dll immediately excepts on attempting to open a cursor. The error is an Assertion Failure in the unit DBAccess.pas, called from MemDs.pas. I have stepped through this and have shown that the assertion failure is correct; Assert(FieldDesc is TCRFieldDesc) is receiving a TFieldDesc from MemDS.CreateFieldDefs().
I am stumped. How can it be that one calling method works fine (the launcher app) and the other (the dll) always fails ?
If anyone has experienced difficulties in this area I would appreciate any information, however tenuous it might sound
We have already fixed this problem. You can either download the latest ODAC version 8.6.12 or modify the line invoking Assert:
in the TCustomDADataSet.GetFieldType method
replace
Assert(FieldDesc is TCRFieldDesc);
with
Assert(IsClass(FieldDesc, TCRFieldDesc));
we use the DEVART MySQL, and SQL connectors. I have experienced the exact issue with the MySQL (MyDAC) connection. However, what I found was this:
In the DBAccess.pas file, the above code change was already there;
Assert(IsClass(FieldDesc, TCRFieldDesc));
But I was still getting the same Assertion error. I stepped in a little further, and found in the CRFunctions unit, I made the following changes, and now my Server connection works perfectly from a dll file:
begin
if IsLibrary then
Result := IsClassByName(Obj, AClass)
else
//------------------------------------
// Danny MacNevin : October 3,2013
// commented out the below line to fix an Assertion Error
// using the TMyConnection in a dll file.
// It was being called from the DBAccess.pas file at line: 7251
// To put this file back to normal, remove the line I added, and
// uncomment the line below...
//------------------------------------
//Result := Obj is AClass;
Result := IsClassByName(Obj, AClass) //Line replaced by Danny
end;

FastReport 4.0. "Claas TfrxReport Not Found" exception ( RAD STUDIO XE2 )

Dear Stackoverflow users. I am in dire need for help. I have been struggling with the embedded in the Embarcadero XE2 RAD studio edition of FastReport 4.0. and more specifically I have been getting the same error, over and over again, which is the misterious "Class TfrxReport Not found" error. Below I submit a part of the code that causes the problems
procedure TForm1.buildReport(Sender: TObject);
var
DevicePic, SymbolPic: TfrxPictureView;
TitleEntry, xmlField: TfrxMemoView;
MasterDataBand: TfrxMasterData;
begin
if not ADOConnection1.Connected then
ShowMessage('Cannot build Report! Please, connect to the DB!')
else
try
//this is where the Class Not Found Exception is Thrown
frxReport1.LoadFromFile('LibreportTemplate.fr3',True);
// frxReport1.LoadFromFile('helloInfineonThree.fr3',True);
if (frxDBDataset1 = nil) then frxDBDataset1 := TfrxDBDataset.Create(Self);
// connect the report to the DATA
frxDBDataset1.DataSource := DataSource1;
frxReport1.DataSet := frxDBDataset1;
except
ShowMessage('Error has Occured! Report Template File Not Found!');
// exit from this procedure!
Exit;
end;
// If no errors have occured, go on building ur report by actually filling it up with data!
// attach dataSet to the masterdata band of the report.
MasterDataBand := frxReport1.FindObject('MasterData1') as TfrxMasterData;
MasterDataBand.DataSet := frxDBDataset1;
// prepare textfields
TitleEntry := frxReport1.FindObject('TitleEntry') as TfrxMemoView;
TitleEntry.DataSet := frxDBDataset1;
TitleEntry.DataField := 'LibFName';
xmlField := frxReport1.FindObject('xmlField') as TfrxMemoView;
// stretch the field if text too big.
xmlField.StretchMode := TfrxStretchMode.smActualHeight;
//get the XML DATA FROM THE DB.
xmlField.DataSet := frxDBDataset1;
xmlField.DataField := 'LibFXML';
// prepare images
DevicePic := frxReport1.FindObject('ImageEntry') as TfrxPictureView;
DevicePic.DataSet := frxDBDataset1;
DevicePic.DataField := 'LIBFIMAGE';
SymbolPic := frxReport1.FindObject('SymbolEntry') as TfrxPictureView;
SymbolPic.DataSet := frxDBDataset1;
SymbolPic.DataField := 'LibFSymbol';
// build and display report
frxReport1.PrepareReport();
frxReport1.ShowPreparedReport;
end;
When building and running the program, I get the following error message "Cannot Find class TfrxReport" and in DebugMode I get the following warning:
Project "MyProject.exe" raised exception class EClassNotFound with message 'Class TfrxReport not Found'.
As commented in the code above, the exception in question is thrown when executing the frxReport1.LoadFromFile('LibreportTemplate.fr3',True); command.
I tried many different approaches for solving the problem, including searching online for a solution. Here is what I did:
Manually create and destroy the frxReport1 object during Form OnCreate and OnClose - ERROR PERSISTS
As suggested in the FastReport ( I couldnt post the link on SO, cause of "Sorry, posts can't contain that content." error) forum thread, replace files in the FastReport 4\LibD16 folder. - ERROR PERSISTS
Recompile FastReport 4 RAD STUDIO 32 bit Version - ERROR PERSISTS
Recompile FastReport 4 RAD STUDIO 64 bit Version - ERROR PERSISTS
Reinstall Embarcadero RAD Studio and FastReport 4 - ERROR PERSISTS
ASK QUESTION IN STACKOVERFLOW - ????
From the thread in the fast-reports forum, it seems that the problem and the respective solution should be ( I QUOTE) :
This error causes by GroupDescendentsWith(TfrxReport, TControl); code.
This code hides TfrxReport from FierMonkey and for some reason
"FindClass" function can't find for TfrxReport class when you're
loading report(only in IDE). If you can't load report or get similar
error with "Couldn't find TfrxReport" message, put this "Link to Files"
files to "Fast
Report\LibD16" dir (replace all).
However the suggested approach DOES not Solve the problem! What should I do? Does anyone have any idea?
I've face this issue as well and I've solved it doing this,
Create a new ProjectGroup and add DPK's suitable for your delphi version (I use XE6).
You'll see the BPL's will divide into runtime and design.
Start compiling runtime fsX (X means version), fqbX, and so on. If you make a mistake in the order you will notice.
Some package need the search path $(BSDCOMMONDIR)/DCP to be added
Compile and install design packages and you'll see the TfrxReport.
You won't see results once design package is installed, I've restarted the IDE and it goes great ;)
With 2 years delay, I hope this could help!
not sure if you got your answer to this question or not... but I was having the same issue in Rad Studio XE4, using Fast Reports 4.0 Pro.
I had placed my report in a data module, which I could create / destroy when needed, and the datasets were found in there as well. I could place a BarCode element in the report designer, however, when running the application, I would get "Cannot find class TfrxBarCodeView".
After a search of the Source folder found in C:\Program Files (X86)\Fast Reports\source\ I opened a source file called frxBarcode.pas which contained the creation of the class "TfrxBarCodeView".
I simply added frxBarCode to my uses list, and all worked perfectly!
Just a thought.
Add RegisterClass(TfrxReport); somewhere on program's startup. Or, right before the line that raises the error.
I would start by
1
putting an absolute, full path to the fr3 file, and
place it in the user's document directory,
just to rule out file access issues. Do you have the source code to FastReport?
I know this is old but to somebody it might come useful.
I just run into similar problem. It never occurred to me there is a
component on the palette of Fast Reports called frxReportTableObject.
Just drop it on the form in question.
Adding frxBarCode to uses solved the problem.

How to avoid System Exception when Runtime Themes are enabled?

I've just ran over something interesting, enabled runtime themes in Project Options and when a hint is shown on a TDCTree(from old Dream components, similar to TTreeView) and the mouse is moved over another node that should show hint, what I get is:
---------------------------
Debugger Fault Notification
---------------------------
Project DRIVE:\path\to\project\MyApp.exe faulted with message: 'system exception (code 0xc000041d) at 0x73c84cad'. Process Stopped. Use Step or Run to continue.
---------------------------
OK
---------------------------
I believe that the same issue occurs within IDE, whenever I try to hover over items when adding items at design time.
If I disable runtime themes in Project Options, no exception, but it shows the "old style XP hint".
Application by itself raises an exception with Event Name "APPCRASH".
Seen quite a few issues related to "runtime themes", but haven't seen any way to avoid these issues without disabling them.
Operating system: Windows 7 x64
Delphi: 2007 with December 2007 and February 2008 updates installed
UPDATE 1:
One way to avoid the issue is:
Procedure TDCTreeToolTip.DoHideToolTip;
Begin
Inherited;
If FToolTipAdded Then
if FTreeNode <> NIL then // fix
DeleteToolTip(ToolTipID,FTreeNode.TreeView.Handle);
FToolTipAdded:=False;
FTreeNode:=Nil;
End;
in unit "dcntree.pas".
it seems that FTreeNode "somehow" gets NIL-ed before the call to DoHideToolTip, so the "System Exception is raised... it still doesn't explain why only when "Runtime themes are enabled"
I don't have time now to investigate this further, but the "trigger" is found, need to figure out "whom" is pulling it.
It seems that at least for now, only the following workaround can be used:
Procedure TDCTreeToolTip.DoHideToolTip;
Begin
Inherited;
If FToolTipAdded Then
if FTreeNode <> NIL then // fix
DeleteToolTip(ToolTipID,FTreeNode.TreeView.Handle);
FToolTipAdded:=False;
FTreeNode:=Nil;
End;
in unit "dcntree.pas".

Resources