I am developing a Delphi 10 Seattle based application that performs multiple tasks using FireDAC's toolset to performe backup, restore and maintenance routines on Firebird databases.
The components included in this toolset (TFDIBBackup, TFDIBRestore and TFDIBValidade) all have the Verbose option, that lets you intercept the output of it and be able to output it to somewhere in order to read it.
I'm trying to output that to a memo, but I'm having some problems with it.
The main problem is: the process gets significantly slowed down the bigger the database, the more lines you output is directly related to the amount of time it takes to backup / restore the database. If you disable verbose completely the amount of time that the process takes drops down to like, 10% of the overall time. It's insane.
During my experiments I found out that if I use another thread to output the verbose to the memo, the process doesn't take that big of a hit in performance, it's like 90% of the non-verbose option, which is great. But I've ran into an issue, using threads makes the application create some sort of stack of threads that will eventually be outputted to the memo, but the problem is that the process itself is already done and the lines will keep being outputted to the memo for a long time.
If I don't use threads to do this, the process takes the big hit on it's performance and the application gets essentially locked down until the process is done.
Does anyone know of any good ways to output the verbose of this toolset without locking down the UI or cause the problem that I explained above?
I decided to implement AmigoJack's suggestion of using AllocConsole()
and Writeln()
to display Firebird's verbose output. It works quite well and doesn't lock my application's GUI.
To prevent the user from closing the application when closing the console you are able to get the handle to that console and then remove the close button.
You will need to declare this function first:
function GetConsoleWindow: HWND; stdcall; external kernel32;
And this is the code to allocate a new console and then hide the button:
var
handle: HWND;
consoleMenuItem: HMENU;
begin
AllocConsole();
handle := GetConsoleWindow;
if IsWindow(handle) then
begin
consoleMenuItem := GetSystemMenu(Handle, False);
if IsMenu(consoleMenuItem) then
begin
DeleteMenu(consoleMenuItem, SC_CLOSE, MF_BYCOMMAND);
end;
end;
end;
Just remember to add a way for the user to call FreeConsole()
in order to get rid of the console when you don't need it anymore, or call it yourself.