I developed an application that uses FireDAC to connect to a MySQL Database.
But when I try to open it on a workstation, at the moment that I set the Connected := True; on the TFDConnection, the application closes itself without showing an exception. It is surrounded with a try...except, but still doesn't show no error message at all. Here's the code I'm using to set the connection:
procedure TfrmServidor.confConnection;
begin
with conMySQL do begin
DriverName := LeXML.Strings[5];
Params.Add('Server=' + LeXML.Strings[3]);
Params.Add('Port=' + LeXML.Strings[4]);
Params.Add('Database=' + LeXML.Strings[0]);
Params.Add('User_Name=' + LeXML.Strings[1]);
Params.Add('Password=' + LeXML.Strings[2]);
ShowMessage(Params.Text);
end;
try
conMySQL.Connected := True;
except
on e : Exception do
ShowMessage(e.Message);
end;
end;
Where LeXML is a function that reads a XML file with the properties and returns the values on a TStringList.
What is it that i'm doing wrong?
The ShowMessage with the Params Text returns the following:
[Window Title]
Servidor
[Content]
DriverID=MySQL
Server=10.1.1.16
Port=3306
Database=treinamentos
User_Name=treinamentos
Password=masterkey
[OK]
Can anyone help?
Related
I have a MS Access app which I am planning to sell to people however it uses ODBC (MYSQL) to connect to a backend MySQL DB plus obviously needs ms access (runtime at least).
I created an Inno Setup installer to check for installed components however I have come across some issues:
ODBC 64x fails unless you also have ODBC 32x installed
ODBC (either) cant install unless the respective bit Visual C++ 2015-2019 is installed
My registry path for Visual C+ detects the install but not the Bit version!
Ms Access 365 (2019?) isn't detected using my current registry detection methods.
Code used:
function GetHKLM: Integer;
begin
if IsWin64 then
Result := HKLM64
else
Result := HKLM32;
Result := HKLM;
end;
function IsOfficeInstalled: Boolean;
begin
Result := RegKeyExists(GetHKLM, 'Software\Microsoft\Office');
end;
function NormalAccessPath: String;
var
Names: TArrayOfString;
I: Integer;
S: String;
begin
if not IsOfficeInstalled then
Result:=''
else
begin
if RegGetSubkeyNames(GetHKLM, 'Software\Microsoft\Office', Names) then
begin
for I := 0 to GetArrayLength(Names)-1 do
begin
S := 'Software\Microsoft\Office\' + Names[I]+ '\' + 'Access';
if RegKeyExists(GetHKLM, S) then
Result:=S;
S := '';
end
end
end;
end;
function IsNormalAccessInstalled: Boolean;
var
Path: String;
begin
Path:= NormalAccessPath;
if Path <> '' then
Result := True
else
Result := False
end;
function IsMySQLODBC51Installed: Boolean;
begin
// the result was inverted in the original code; the original function returned
// True if the ODBC driver was not installed, False otherwise, and according to
// the function name it should be vice-versa
Result := RegKeyExists(GetHKLM, 'Software\ODBC\ODBCINST.INI\MySQL ODBC 8.0 Unicode Driver');
end;
function IsRuntimeAccessInstalled: Boolean;
begin
Result := RegKeyExists(GetHKLM, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\AccessRuntimeRetail - en-us');
end;
function IsVCInstalled: Boolean;
begin
Result := RegKeyExists(GetHKLM, 'Software\Microsoft\VisualStudio\14.0\VC');
end;
function AddAsTrusted: Boolean;
var
Path: String;
ResultCode: Integer;
begin
Path:= NormalAccessPath;
MsgBox('Adding Trusted Location', mbInformation, MB_OK);
//Exec('C:\Me\freelance\Inno setup script\fixes.bat', '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode)
if Path <> '' then
begin
//if not RegKeyExists(GetHKLM, Path + '\Security') then
// RegWriteStringValue(GetHKLM, Path + '\Security','MedidropUseless', 'MedidropUseless')
if not RegKeyExists(GetHKLM, Path + '\Security\Trusted Locations') then
RegWriteStringValue(GetHKLM, Path + '\Security\Trusted Locations\Location1','Path', 'C:\MediDrop')
end;
Result := True;
end;
So for 2 & 3:
I need to detect visualC's VERSION.
I tested the installer at a new location today and they already had visual C++ 2015 86x so my installed failed for ODBC 64x because visualC 64x was missing. Obviously:
'Software\Microsoft\VisualStudio\14.0\VC'
is not appropriate..
For 4:
As can be seen I am checking Software\Microsoft\Office however this computer did have the 15.0 and 16.0 subfolders (terminology?) but did NOT have ACCESS in them so my installer thought it was not installed.
However.. it was, so I need to find a way of finding this 365 version of access!
Finally, at the end of the install I add a path for trusted location:
function AddAsTrusted: Boolean;
var
Path: String;
ResultCode: Integer;
begin
Path:= NormalAccessPath;
MsgBox('Adding Trusted Location', mbInformation, MB_OK);
//Exec('C:\Me\freelance\Inno setup script\fixes.bat', '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode)
if Path <> '' then
begin
if not RegKeyExists(GetHKLM, Path + '\Security\Trusted Locations') then
RegWriteStringValue(GetHKLM, Path + '\Security\Trusted Locations\Location1','Path', 'C:\[MyAppName]')
end;
Result := True;
end;
Once again due to the 365 issue... this did not work. I created the path correctly in 16.0 but since access wasnt there, I still needed to Enable Content when I opened the app the first time, something I don't want to do.
Does anyone know where I can start to figure the above issues out??
I'm trying to create TSQLConnection at run-time on non-GUI application.
Uses Data.DB, Data.SqlExpr, Data.DBXMSSQL;
...
procedure TFoo.InitializeDB;
begin
if NOT Assigned(SQLCon) then exit;
SQLCon.Params.Clear;
SQLCon.ConnectionName := 'ReportsCon';
SQLCon.DriverName := 'MSSQL';
SQLCon.LoadParamsFromIniFile('C:\ConfigTest\DBTest.ini');
try
SQLCon.Connected := True;
except
on E: Exception Do
LastErr := E.Message;
end;
end;
I got this error
DBX Error: Driver could not be properly initialized. Client library may be missing, not installed properly, of the wrong version, or the driver may be missing from the system path.
For test purpose i created a new GUI project i dropped TButton on the form with the below OnClick event
Uses Data.DB, Data.SqlExpr, Data.DBXMSSQL;
...
procedure TForm12.btn1Click(Sender: TObject);
var
SQLConnection: TSQLConnection;
begin
SQLConnection := TSQLConnection.Create(nil);
try
SQLConnection.ConnectionName := 'ReportsCon';
SQLConnection.DriverName := 'MSSQL';
SQLConnection.LoadParamsFromIniFile('C:\ConfigTest\DBTest.ini');
try
SQLConnection.Connected := True;
except
on E: Exception Do
ShowMessage(E.Message);
end;
finally
SQLConnection.Free;
end;
end;
The code run as expected with no error.
Both EXE and dbxmss.dll are on the same folder
C:\Users\$Name\Documents\Embarcadero\Studio\Projects\Win32\Debug
What am I missing here ?
I am doing develop Indy based application.
Server has several Indy TCP Server components.
So It works under multi-threads and handles mysql db.
I have faced one problem.
That is about the exceptions of MySQL DB in threads.
When serveral threads attack to same db table, then It says me like follows
UniQuery_Mgr: Duplicate field name 'id'
UniQuery_Mgr: Field 'grp_id' not found //of course grp_id field is really existed.
Assertion failure (C:\Program Files (x86)\unidac539src\Source\CRVio.pas, line 255)
Commands out of sync; You can't run this command now
ReceiveHeader: Net packets out of order: received[0], expected[1]
UniQuery_Mgr: Cannot perform this operation on a closed dataset
How to do I ? UniQuery_Mgr is TUniQuery component.
and my query handling code is normally like this
Code 1
sql := 'SELECT * FROM data_writed;';//for example
UniQuery_Mgr.SQL.Clear;
UniQuery_Mgr.SQL.Add(sql);
UniQuery_Mgr.ExecSQL;
Code 2
try
sql := 'SELECT * FROM gamegrp_mgr;';
UniQuery_Mgr.SQL.Clear;
UniQuery_Mgr.SQL.Add(sql);
UniQuery_Mgr.ExecSQL;
if UniQuery_Mgr.RecordCount > 0 then
begin
MAX_GAME_GROUP_COUNT := UniQuery_Mgr.RecordCount + 1;
UniQuery_Mgr.First;
i := 1;
while not UniQuery_Mgr.Eof do
begin
Game_Group_ID[i] := UniQuery_Mgr.FieldByName('grp_id').AsInteger;
Game_Game_ID[i] := UniQuery_Mgr.FieldByName('game_id').AsInteger;
UniQuery_Mgr.Next;
Inc(i);
end;
end;
except
on E : Exception do
begin
EGAMEMSG := Format('GAME group read error: <%s> # %s',[ E.ToString, DateTimeToStr(now)]);
Exit;
end;
end;
Code 3
try
sql := 'UPDATE data_writed SET write_gamegrp = ' + QuotedStr('0') + ';';
UniQuery_Mgr.SQL.Clear;
UniQuery_Mgr.SQL.Add(sql);
UniQuery_Mgr.ExecSQL;
except
on E : Exception do
begin
EGAMEMSG := Format('data updating error: <%s> # %s',[ E.ToString, DateTimeToStr(now)]);
Exit;
end;
end;
My handling DB components is bad ? Other thread-safe method is existed???
I have downloaded and installed MySQL Connector 5.1 x64 so I can use MySQL with Delphi. I can make connection with ODBC and do a connection from my Delphi environment and from MySQL Workbench.
But, when I build my Query at runtime, I get an error saying:
Project AAA.exe raised exception class EOleException with message 'Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another'. Process stopped. Use Step or Run to continue.
My code:
qDates := TADOQuery.Create(Component);
qDates.Connection := FConnection;
qDates.SQL.Text :=
'select ' +
' * ' +
'from ' +
' resulttable ' +
'where ' +
' oid = :oid ' +
' and datedial >= :datebegin and datedial <= :dateend'; // <<-- Exception here
Details:
The exception happens right on the text assignment, before I have a chance to configure parameters.
If I comment out the where clause the assignment goes fine.
This is similar to Using parameters with ADO Query (mysql/MyConnector) but the difference is that I assign whole text at once and I get the exception before I have a chance to configure parameters.
The puzzling part - exact same code works fine on my other machine, but I can not figure out what is different.
Hence the question - what could cause the above exception outside of the Delphi code and MySQL server?
This seems to be a quirk with the MySQL ODBC provider.
If you assign the connection after setting the SQL text, then it will work.
The reason why can be found here.
qDates := TADOQuery.Create(Component);
// do net yet assign TADOConnection to prevent roundtrip to ODBC provider
qDates.SQL.Text :=
'select ' +
' * ' +
'from ' +
' resulttable ' +
'where ' +
' oid = :oid ' +
' and datedial >= :datebegin and datedial <= :dateend';
qDates.Connection := FConnection;
UPDATE
This QC entry explains the exact reason for this problem.
In short, the ADODB unit, patch this line from the RefreshFromOleDB procedure :
Parameter.Attributes := dwFlags and $FFFFFFF0; { Mask out Input/Output flags }
To:
if dwFlags and $FFFFFFF0 <= adParamSigned + adParamNullable + adParamLong then
Parameter.Attributes := dwFlags and $FFFFFFF0; { Mask out Input/Output flags }
in Inno Setup script GetExceptionMessage returns empty message (it contains only colon ":" sign). The last version of Inno Setup (5.4.2) is used.
try
Log('Create IISNamespace');
// Create IIS namespace object
if Length(virtualDirectoryName) > 0 then
begin
IIS := CreateOleObject('IISNamespace');
Log('Get IIsWebService');
WebSite := IIS.GetObject('IIsWebService', IISServerName + '/w3svc');
Log('Get IIsWebServer');
WebServer := WebSite.GetObject('IIsWebServer', IISServerNumber);
Log('Get IIsWebVirtualDir');
WebRoot := WebServer.GetObject('IIsWebVirtualDir', 'Root');
Log('Delete IIsWebVirtualDir');
WebRoot.Delete('IIsWebVirtualDir', virtualDirectoryName);
WebRoot.SetInfo();
end;
except
MsgBox(ExpandConstant('{cm:IISException,'+ GetExceptionMessage +'}'),
mbInformation, mb_Ok);
Log('Uninstall IIS 6 exception: ' + GetExceptionMessage);
end;
The exception occurs during deleting IIsWebVirtualDir.
Is there any way to get exception type or real exception message?
Thanks, Denis.
I just wrote the following example to see if either GetExceptionMessage or ShowExceptionMessage are broken. I used both Inno setup 5.4.2 Unicode and Ansi versions.
[Setup]
AppName=Test
AppVersion=1.5
DefaultDirName={pf}\test
[Code]
function InitializeSetup(): Boolean;
var
I: Integer;
begin
try
I := I div 0; // Raise an exception
except
MsgBox(GetExceptionMessage,
mbError, MB_OK);
ShowExceptionMessage;
end;
result := false;
end;
I also ran CodeAutomation.iss that ships and it worked as expected. Which is contrary to the comment made by Alex K. that it may be broken.
Now that I know that the routines should work, I took your code and made the following setup test Script and ran it and it raised an exception on not finding the ISSNamespace as I don't have it installed.
[Setup]
AppName=Test
AppVersion=1.5
DefaultDirName={pf}\test
[CustomMessages]
IISException =ISS Exception " %1 " occured.
[Code]
const
IISServerName = 'localhost';
IISServerNumber = '1';
IISURL = 'http://127.0.0.1';
function InitializeSetup(): Boolean;
var
IIS, WebSite, WebServer, WebRoot, VDir: Variant;
virtualDirectoryName : String;
begin
virtualDirectoryName := 'test';
try
Log('Create IISNamespace');
// Create IIS namespace object
if Length(virtualDirectoryName) > 0 then
begin
IIS := CreateOleObject('IISNamespace');
Log('Get IIsWebService');
WebSite := IIS.GetObject('IIsWebService', IISServerName + '/w3svc');
Log('Get IIsWebServer');
WebServer := WebSite.GetObject('IIsWebServer', IISServerNumber);
Log('Get IIsWebVirtualDir');
WebRoot := WebServer.GetObject('IIsWebVirtualDir', 'Root');
Log('Delete IIsWebVirtualDir');
WebRoot.Delete('IIsWebVirtualDir', virtualDirectoryName);
WebRoot.SetInfo();
end;
except
MsgBox(ExpandConstant('{cm:IISException,'+ GetExceptionMessage +'}'),
mbInformation, mb_Ok);
Log('Uninstall IIS 6 exception: ' + GetExceptionMessage);
end;
end;
But I made a fatal flaw during the construction of this script that could be your problem.
Check your [CustomMesssages] section make sure you have %1 in the message. Otherwise nothing is returned.