In my program, the creation of the main form is slow : I have identified that it hangs for around two seconds just before the form's OnCreate event is called. So I suspect this is happening while the components are created.
Since this form has several frames, I wonder if there is a way to "profile" component creation in order to see where I can improve. I suspect the lag comes from the opening of a database table that should not be open at that time (rather later, after some filtering is in place).
If there is a way get an event triggered before/after each component creation, I could do the profiling myself (with codesite for example).
Or maybe it is possible to do the component creation manually ?
Here is a quick and dirty way to work out where the delay is:
Take a copy of the Classes unit source code and place it in your project's source folder. This will ensure that this unit is compiled into your program rather than the one supplied with Delphi.
Modify the code in the constructor of TComponent. All streamed components pass through here during creation. Add code to log the class name, e.g. using CodeSite for instance.
Run your program, and then inspect the resulting log to identify the delay.
If you have many components then just knowing the class might not narrow it down. You might inject logging code into TComponent.SetName instead which will let you log the component's name. However, the basic idea is simple enough, and you should be able to apply it to your setting in order to find out the information you need.
Related
I know how to force forms to appear on the same monitor as the running application, but I do not see how to ask the Help or the Printer Setup dialogs to display on the same monitor. The Help displays where it displayed last time, but we want it to show up on the application monitor. The Printer Setup dialog always seems to appear on the primary monitor
Passing the parent form's Handle to TPrinterSetupDialog.Execute seems to do the trick.
if PrinterSetupDialog1.Execute(Self.Handle) then
//
Using Delphi 7 (where the TPrinterSetupDialog.Execute does not accept a parameter), you have two choices.
The easiest would be to create your own descendant of TPrinterSetupDialog. Execute is virtual in TCommonDialog, the ancestor of TPrinterSetupDialog, where it is overridden. You could override it in your own descendant, use the code in the TPrinterSetupDialog as a basis for your own Execute override, adding overload as well. Your overloaded Execute would accept a ParentHandle: HWND parameter, and set the PrintDlgRec.hWndOwner to that provided window handle.
I thought about trying to write this for you (or at least get it started), but there are additional things you'd have to copy from the Dialogs unit (functions that are defined in the implementation section that wrap some API calls, and the callback function that's used for the dialog's message loop), and I don't have D7 available where I'm at to even try to compile it.
The other alternative (as David Heffernan mentioned in his comment below) would be to call the Windows API PrintDlgEx directly yourself. This is discussed in MSDN, in the Print Dialog Box (Windows) topic. Once again, I don't have D7 available, so I can't really give you an example of using it from Delphi. (I checked, and don't have one tucked away anywhere.)
I'm not sure you can set the help window's position; I think that's done automatically by Windows based on the user's prior use. (I haven't been able to so so, anyway.)
I've started to look at using Omnithread to improve my Delphi Application using multithreading. Creating one or more worker tasks are well covered by the documentation so that long actions that I invoke from button clicks can be replaced by this demo code (Async, CreateTask etc). Where I am having difficulty though is in how to replace my most 'messy' code which operates as follows.
I have a concept of a single class instance that corresponds to a hardware module. The class publishes one or more properties that expose current values and settings for the hardware. Properties might be read only or read / write. For each of these class instances there can be from zero to several display forms visible. A display form has a TTimer and a built list of the aformentioned published properties. This list is iterated to match up suitably named controls such as labels or edit controls and an RTTI mechanism is used to get and set values between the control and its property. The result is a form which provides a nice UI on to the actual hardware module with the side effect than multiple forms can be open, modifying data on one of them causes the others to show that data shortly after. This property monitoring is performed by the TTimer ticking at 300 ms intervals. Each tick causes it to scan through all properties of the class and to refresh the matching control on its form. The timer runs for the lifetime of the open form. Forms are created when needed and then freed (this has the useful performance optimisation that with no forms open to inspect the hardware, the Application must run as fast as possible because no monitoring tasks can be running).
Is there a better way of using threading to access my published properties, rather than using a TTimer in the UI thread? Or would synchronisation issues outweigh any advantages? If threading is useful, how would one create a repeating task such as to emulate the ticking timer?
Imagine i want to parse a binary blob of data. If all comes okay, then all the logs are INFO, and user by default does not even see them. If there is an error, then user is presented with error and can view the log to see exact reason (i don't like programs that just say "file is invaid. for some reason. you do not want to know it" )
Probably most log libraries are aimed at quickly loading, classifying and keeping many many log lines per second. which by itself is questionable, as there is no comfort lazy evaluation and closures in Delphi. Envy Scala :-)
However that need every line be pre-сlassified.
Imagine this hypothetical flow:
Got object FOO [ok]
1.1. found property BAR [ok]
1.1.1. parsed data for BAR [ok]
1.2 found property BAZ [ok]
1.2.1 successfully parsed data for BAR [ok]
1.2.2 matching data: checked dependancy between BAR and BAZ [fail]
...
So, what can be desired features?
1) Nested logging (indenting, subordination) is desired then.
Something like highlighted in TraceTool - see TraceNode.Send Method at http://www.codeproject.com/KB/trace/tracetool.aspx#premain0
2) The 1, 1.1, 1.1.1, 1.2, 1.2.1 lines are sent as they happen in a info sink (TMemo, OutputDebugString, EventLog and so one), so user can see and report at least which steps are complete before error.
3) 1, 1.2, 1.2.2 are retroactively marked as error (or warning, or whatever) inheriting from most specific line. Obviously, warning superseeds info, error superseeds warning and info, etc/
4) 1 + 1.2 + 1.2.2 can be easily combined like with LogMessage('1.2.2').FullText to be shown to user or converted to Exception, to carry the full story to human.
4.1) Optionally, with relevant setup, it would not only be converted to Exception, but the latter even would be auto-raised. This probably would require some kind of context with supplied exception class or supplied exception constructing callback.
5) Multisink: info can be just appended into collapsible panel with TMemo on main form or currently active form. The error state could open such panel additionally or prompt user to do it. At the same time some file or network server could for example receive warning and error grade messages and not receive info grade ones.
6) extra associated data might be nice too. Say, if to render it with TreeView rather than TMemo, then it could have "1.1.1. parsed data for BAR [ok]" item, with mouse tooltip like "Foo's dimensions are told to be 2x4x3.2 metres"
Being free library is nice, especially free with sources. Sometimes track and fix the bug relying solely on DCUs is much harder.
Non-requiring extra executable. it could offer extra more advanced viewer, but should not be required for just any functionality.
Not being stalled/abandoned.
ability to work and show at least something before GUI is initialized would be nice too. Class constructors are cool, yet are executed as part of unit visualization, when VCL is not booted yet. If any assertion/exception is thrown from there, user would only see Runtime error 217, with all the detail lost. At least OutputDebugStreen can be used, if nothing more...
Stack tracing is not required, if needed i can do it and add with Jedi CodeLib. But it is rarely needed.
External configuration is not required. It might be good for big application to reconfigure on the fly, but to me simplicity is much more important and configuration in code, by calling constructors or such, is what really matters. Extra XML file, like for Log4J, would only make things more fragile and complex.
I glanced few mentioned here libraries.
TraceTool has a great presentation, link is above. Yet it has no info grade, only 3 predefined grades (Debug/Error/Warning) and nothing more, but maybe Debug would suit for Info replacement... Seems like black box, only saving data into its own file, and using external tool to view it, not giving stream of events back to me. But their messages nesting and call chaining seems cool. Cools is also attaching objects/collection to messages.
Log4D and Log4Delphi seems to be in a stasis, with last releases of 2007 and 2009, last targeted version Delphi 7. Lack documentation (probably okay for log4j guy, but not for me :- ) Log4Delphi even had test folder - but those test do not compile in Delphi XE2-Upd1. Pity: In another thread here Log4delphi been hailed for how simple is to create custom log appender (sink)...
BTW, the very fact that the only LOG4J was forked into two independent Delphi ports leaves the question of which is better and that both lack something, if they had to remain in split.
mORMot part is hardly separated from the rest library. Demo application required UAC escalation for use its embedded SQLite3 engine and is frozen (no window opened, yet the process never exits normally) if refused Admin grants. Another demo just started infinite stream of AV exceptions, trying to unwind the stack. So is probably not ready yet for last Delphi. Though its list of message grades is excessive, maybe even a bit too many.
Thank you.
mORMot is stable, even with latest XE2 version of Delphi.
What you tried starting were the regression tests. Among its 6,000,000 tests, it includes the HTTP/1.1 Client-Server part of the ORM. Without the Admin rights, the http.sys Server is not able to register the URI, so you got errors. Which makes perfectly sense. It's a Vista/Seven restriction, not a mORMot restriction.
The logging part can be used completely separated from the ORM part. Logging is implemented in SynCommons.pas (and SynLZ.pas for the fast compression algorithm used for archival and .map embedding). I use the TSynLog class without any problem to log existing applications (even Delphi 5 and Delphi 6 applications), existing for years. The SQLite3 / ORM classes are implemented in other units.
It supports the nesting of events, with auto-leave feature, just as you expect. That is you can write:
procedure TMyClass.MyMethod(const Params: integer);
begin
TSynLog.Enter;
// .... my method code
end;
And adding this TSynLog.Enter will be logged with indentation corresponding to the recursive level. IMHO this may meet your requirements. It will declare an ISynLog interface on the stack, which will be freed by Delphi at the "end;" code line, so it will implement an Auto-Leave feature. And the exact unit name, method name and source code line number will be written into the log (as MyUnit.TMyClass.MyMethod (123)), if you generated a .map file at compilation (which may be compressed and appended to the .exe so that your customers logs will contain the source line numbers). You have methods at the ISynLog interface level to add some custom logging, including parameters and custom state (you can log objects properties as JSON if you need to, or write your custom logging data).
The exact timing of each methods are tracked, so you are able to profile your application from the data supplied by your customer.
If you think the logs are too much verbose, you have several levels of logging, to be customized on the client side. See the blog articles and the corresponding part of the framework documentation (in the SynCommons part). You've for instance "Fail" events and some custom kind of events. And it is totally VCL-independent, so you can use it without GUI or before any GUI is started.
You have at hand a log viewer, which allow client-side profiling and nested Enter/Leave view (if you click on the "Leave" line, you'll go back to the corresponding "Enter", e.g.):
If this log viewer is not enough, you have its source code to make it fulfill your requirements, and all the needed classes to parse and process the .log file on your own, if you wish. Logs are textual by default, but can be compressed into binary on request, to save disk space (the log viewer is able to read those compressed binary files). Stack tracing and exception interception are both implemented, and can be activated on request.
You could easily add a numeration like "1.2.1" to the logs, if you wish to. You've got the whole source code of the logging unit. Feel free to ask any question in our forum.
Log4D supports nested diagnostic contexts in the TLogNDC class, they can be used to group together all steps which are related to one compound action (instead of a 'session' based grouping of log events). Multi-Sinks are called Appenders in log4d and log4delphi so you could write a TLogMemoAppender with around twentyfive lines of code, and use it at the same time as a ODSAppender, a RollingFileAppender, or a SocketAppender, configurable at run time (no external config file required).
The Delphi debugger is great for debugging linear code, where one function calls other functions in a predictable, linear manner, and we can step through the program line by line.
I find the debugger less useful when dealing with event driven gui code, where a single line of code can cause new events to be triggered, which may in turn trigger other events.
In this situation, the 'step through the code' approach doesn't let me see everything that is going on.
The way I usually solve this is to 1) guess which events might be part of the problem, then 2) add breakpoints or logging to each of those events.
The problem is that this approach is haphazard and time consuming.
Is there a switch I can flick in the debugger to say 'log all gui events'? Or is there some code I can add to trap events, something like
procedure GuiEventCalled(ev:Event)
begin
log(ev);
ev.call();
end
The end result I'm looking for is something like this (for example):
FieldA.KeyDown
FieldA.KeyPress
FieldA.OnChange
FieldA.OnExit
FieldB.OnEnter
This would take all the guesswork out of Delphi gui debugging.
I am using Delphi 2010
[EDIT]
A few answers suggested ways to intercept or log Windows messages. Others then pointed out that not all Delphi Events are Windows messages at all. I think it is these type of "Non Windows Message" Events that I was asking about; Events that are created by Delphi code. [/EDIT]
[EDIT2]
After reading all the information here, I had an idea to use RTTI to dynamically intercept TNotifyEvents and log them to the Event Log in the Debugging window. This includes OnEnter, OnExit, OnChange, OnClick, OnMouseEnter, OnMouseLeave events. After a bit of hacking I got it to work pretty well, at least for my use (it doesn't log Key events, but that could be added).
I've posted the code here
To use
Download the EventInterceptor Unit and add it to your project
Add the EventInterceptor Unit to the Uses clause
Add this line somewhere in your code for each form you want to track.
AddEventInterceptors(MyForm);
Open the debugger window and any events that are called will be logged to the Event Log
[/EDIT2]
Use the "delphieventlogger" Unit I wrote download here. It's only one method call and is very easy to use. It logs all TNotifyEvents (e.g. OnChange, OnEnter, OnExit) to the Delphi Event Log in the debugger window.
No, there's no generalized way to do this, because Delphi doesn't have any sort of "event type" that can be hooked in some way. An event handler is just a method reference, and it gets called like this:
if assigned(FEventHandler) then
FEventHandler(self);
Just a normal method reference call. If you want to log all event handlers, you'll have to insert some call into each of them yourself.
I know it is a little bit expensive, but you can use Automated QA's (now SmartBear) TestRecorder as an extension to TestComplete (if you want this only on your system, TestComplete alone will do). This piece of software will track your GUI actions and store it in a script like language. There is even a unit that can be linked into your exe to make these recordings directly at the user's system. This is especially helpful when some users are not able to explain what they have done to produce an error.
Use WinSight to see the message flow in real time.
If you really want the program to produce a log, then override WinProc and/or intercept the messages in Application.
The TApplication.OnMessage event can be used to catch messages that are posted to the main message queue. That is primarily for OS-issued messages, not internal VCL/RTL messages, which are usually dispatched to WndProc() methods directly. Not all VCL events are message-driven to begin with. There is no single solution to what you are looking for. You would have to use a combination of TApplication.OnMessage, TApplication.HookMainWindow(), WndProc() overrides, SetWindowsHook(), and selective breakpoints/hooks in code.
Borland's WinSight tool is not distributed anymore, but there are plenty of third-party tools readily available that do the same thing as WinSight, such as Microsoft's Spy++, WinSpector, etc, for tracking the logging window messages in real-time.
As an alternative, to debug the triggered events use the debugger Step Into (F7) instead of Step Over (F8) commands.
The debugger will stop on any available code line reached during the call.
You can try one of the AOP frameworks for Delphi. MeAOP provides a default logger that you can use. It won't tell you what is going on inside an event handler but it will tell you when an event handler is called and when it returns.
I'm developing a application in Lazarus, that need to check if there is a new version of a XML file on every Form_Create.
How can I do this?
I have used the synapse library in the past to do this kind of processing. Basically include httpsend in your uses clause, and then call httpgetbinary(url,xmlstream) to retrieve a stream containing the resource. I wouldn't do this in the OnCreate though, since it can take some time to pull the resource. Your better served by placing this in another thread that can make a synchronize call back to the form to enable updates, or set an application flag. This is similar to how the Chrome browser displays updates on the about page, a thread is launched when the form is displayed to check to see if there are updates, and when the thread completes it updates the GUI...this allows other tasks to occur (such as a small animation, or the ability for the user to close the dialog).
Synapse is not a visual component library, it is a library of blocking functions that wrap around most of the common internet protocols.
You'll need to read up on FPC Networking, lNet looks especially useful for this task.