Delphi.
How from DLL to learn Handle the appendix which has caused this DLL?
That is necessary: Knowing Handle appendices, I wish in Dll to use this Handle at creation of dialogues, because dialogue created as TOpendialog.Create(nil) sometimes it appears under the main window of the basic form. And so, in DLL I would make:
application.handle:=GetExeHandle; // GetExeHandle - How to learn?
Opendialog1:=TOpendialog.Create(application);
...
So it is correct?
The only time your DLL shows a dialog box is when the host application calls a function from your DLL. Include the parent window handle as one of the function's input parameters so that the EXE can tell you which handle to use. Do not attempt to discover the handle yourself. As a library developer, you cannot guess what the host application is doing.
If you don't want to include the handle on every function call, then add an initialization function that users of the DLL need to call before any other functions. Pass the handle in the initialization and then store it in a variable in your DLL so that other functions can use the value when they need it.
Unless you use runtime packages (and you don't, or not the right ones), you are in for a world of pain.
Your library will have its' own copy not only of (T)Application but also of thread sycnhronization queue and event (and everything else).
What you are trying to do can seem to work, but it may (and it will) break anytime cause any complex dialog, regardless if VCL or WinAPI, does its' own message pumping, which will bypass the applications' idle and synchronization handling, resulting in reentrancy issues and random stalls or deadlocks.
You may try to handle a lot of the cases by copying the applications' handles, events etc. to the DLL's globals upon its' initialization (is I tried to do), but (not only) if you use anything like TApplication or TThread in the DLL, it will break sometimes.
You can avoid these problems if you use the right BPL runtime packages in your app and the library, as they will share the same namespace and globals as the application using them.
Related
I'm implementing a DLL containing a shared ADO Connection by using the ConnectionObject property of TADOConnection and passing it across DLL boundaries into other instances of TADOConnection. I need to make sure COM is initialized, so I need to call CoInitialize / CoUninitialize. Currently it's in the context of a VCL main thread, but could be elsewhere in another thread, which of course requires its own instance of COM. I'm not currently implementing multi-threading.
Where is the appropriate place to call these; inside the DLL (during loading/unloading), outside the DLL (calling process), or both? Considering it's only one thread, shouldn't it be only one time outside the DLL in the original process?
I'm assuming the original calling thread should be solely responsible for this, since COM runs in the context of a thread. Of course calling them on both sides shouldn't hurt any, however it would also create multiple COM instances.
Long story short... Is it "safe to be safe" in this case? Or is it important to only keep one COM instance?
You should not be doing this in the DLL. Make it part of the contract between the DLL and the host that the host is responsible for initializing COM.
The DLL cannot be expected to initialize COM because the host may already have done so. And use a different threading model. Once COM has been initialized then future attempts to initialize will fail if they attempt to change the threading mode.
So, don't initialize COM in your DLL. Require the host to do so.
I have written a dll in d-7. It functions correctly. It gets loaded when an application starts and unloaded when it exists.
Now, that dll must also work on the server side of that application, being loaded from the COM+ surrogate (dllhost.exe) as the server is based on com+ technology.
The problem is that one process may have only one handle for loaded library. I cannot have separate handles on each LoadLibrary call.
In com+, one dllhost.exe can serve many clients, which means that if I load an external library it gives the same instance for each clients calls.
So:
1) Is it possible to somehow workaround this problem?
2) Or Is it possible to directly create instance of the class which resides in this dll for each client call?
3) Or How to make a dll thread-safe by instantiating an internal class for each call.
Thanks for suggestions in advance!
Since a DLL uses the local memory of the thread/process that calls it, I'm not sure you're really going to have a "problem". You do not want to have the DLL maintain some global information because that will only lead to threading nightmares.
If you have a function within the DLL return an object reference (effectively a handle) you can also guarantee that each instance gets its own information to play with and not stomp on other processes or threads. Define the function to return your TWhatever object, have the DLL create it ( TWhatever.Create() ) and return it to the calling process. It would then be up to the calling process to free the object. If you need COM+ compatibility then it should be possible to use an interface reference (IWhatever) and return that from your function.
If each thread deals with its own object instance (or interface reference) then you could have the DLL serve as many threads and processes as you wish.
Your question is confusing to me so I'm not sure if I answered it correctly. :p
I am moving some functions to a shared DLL (I want to have some called as a Windows hook).
The actual functions are currently in a unit, and it happens to have some initialization and some finalization code.
I was initially thinking on doing a direct transformation from a unit to a library. So I moved the initialization code in between the main begin and end.. But then I realized I had no place to move the finalization code. I should create and register an special DLL entry point, instead.
My question is. Can I leave the unit with all the functions and the initialization and finalization codes and just create a library stub that uses the unit? will the finalizationit be called?
Code in the initialization sections of the units in the DLL will run when the DLL is first loaded in to the process. The finalization sections fire when the DLL is unloaded from the process.
Eugene is right that you can have more fine-grained control using DLLProc but this is usually only needed for per-thread resources, e.g. thread local storage.
I would point out that there are serious limitations on what can be done during DLLMain which is ultimately where these initialization/finalization sections originate when inside a library. The MSDN documentation basically says that you can do some things, but that there is no list of acceptable behaviour. The closest it comes is to saying that you can call functions in kernel32. Otherwise, all bets are off!
There are lots of articles on the web that describe the issue, but beyond the MSDN topic for DLLMain that I've linked above, I would recommend reading Microsoft's Best Practices for Creating DLLs.
The helpful advice that MSDN offers is that the library can mandate that its users call an initialization function before using the DLL. A corresponding finalization function would be called once you were finished with the DLL. The use of comctl32.dll adopts this idiom, see InitCommonControlsEx.
In my own code I prefer an alternative approach. The initialization sections of all my units register initialization and finalization methods. Then, on the first call to any exported function from my library, the initialization methods are run, in the order in which they were registered. This is not a problem for me to implement because I am already controlling all entry/exit points to my library.
I realise this is more than you asked for, but you may find it helpful to avoid some rather hard to debug problems.
The initialization of a unit will be called if its a program and if its a library.
Same for the finalization.
So yes, you can leave the unit as it is and export the required functionality.
I'd suggest that you implement a DLLMain and handle different situations (process attach, thread attach etc) by calling dedicated procedures/functions for each situation. Then you can call the needed procedures/functions from initialization and finalization, if you need to switch from DLL to unit. The reason is that you might need some fine-grain control when the DLL is attached/detached to/from the thread (which will happen when you set a system-wide hook).
This happend to me as well.
I found out that I had a unit, that initialization section that create a thread or doing some stuff, when the dll is registered.
I have removed this initialization section, and it worked fine.
Since, the initialization is required for .exe application but not for dll application,
there is a variable flag in the system utility, called ModuleIsLib
just do:
initialization
if not ModuleIsLib then
begin
// initialization stuff for .exe file
end;
This can be done also for finalization section as well.
hope it helped..!
I'm currently attempting to integrate a DLL (FooEmulation) into an existing project.
The DLL assumes that it will only be used to emulate one Foo at a time, and uses a lot of static globals as a result.
However, I want to be able to manage thousands of Foo instances at once.
I have the source to the original DLL, so I could convert all of the static globals into parameters that would be passed in (whether directly or via a handle), but the DLL is being maintained separately and I'd like to avoid forking/merging if at all possible.
One technique I found was to load multiple dynamically generated copies of the DLL, but that is too resource-heavy for the scale I need.
I also can't afford to create a process or thread for each Foo.
Is it possible to keep multiple copies of the DLL's static memory and restore it per use of the DLL?
How do I locate it? Am I even allowed to touch it?
When you load the DLL multiple times into the same process all the static data is shared, period. You'll have to redesign the library so that all those objects can be created dynamically as you need them during the runtime.
I am assuming you're on windows since there's nothing telling me otherwise..
Take a look here, which is the documentation for DLLMain in Windows.
DLLMain has a parameter that tells you if
A process is attaching (loading your DLL)
A process is detaching (unloading your DLL)
A thread is attaching (loading the per thread parts of your DLL)
A thread is detaching (unloading the per thread parts of your DLL)
If you catch the process or thread events and allocate (attach) / free (detach) a new instance of your statics, I think this would solve your problem. It's a little hacky, but it would work...
You have to be careful what you do in DLLMain as well. Look in the docs for the warnings about blocking in any way in DLLMain.
When we created our program, it closed properly under XP, but under Vista, even though the program is closed, the process is often still running until I open task manager and manually kill the process.
Any suggestions on how to make sure this is closed when we close the program? What a pain.
Mark Gundy
www.magchat.com
The debugger will be your friend here. Step through the shutdown until you get stuck. That'll be the best bet.
But... assuming for some reason the debugger is affecting the behaviour, or can't be used for some other reason:
A few earlier replies suggest using FastMM. This has been the default memory manager for delphi since D2006. You can try flipping on the options to report memory leaks... but that'll only work after you've finished shutting down the process, which is what isn't working. :) So I doubt it will help you much in this case. The full version of FastMM, as opposed to the standard one packaged with delphi, might have some other helpful features... But I can't recall any that would help here.
To inspect your app while it's stuck, you could try the sysinternals tools, like Process Explorer & Process Monitor. Process Monitor may show you if it's choking on any ACCESS_DENIED errors, etc, and the stack trace at the time of the error. Process Explorer could be especially useful, by listing all the handles your process is still holding open, and allowing you to view the stack of all its living threads. A familiar function or two, in the stack traces of any hung threads, may send you hunting in the right area.
Are you using multiple threads? If one of them can't terminate for some reason, it'll hang the cleanup process.
The short answer is that you have a bug in your application. So, have you tried debugging it?
If you have the Delphi IDE installed on Vista, run the app from the IDE and break it when it 'hangs'. Chances are that you'll have a thread that hasn't terminated itself, and the VCL is waiting for it to finish.
If you don't have the IDE installed on vista, you can probably use the remote debugger, but I'm not familiar with this.
What do you call to close your program? Try using
Application.Terminate;
To force all forms to close and the process to exit.
It probably means you have some memory leak - some resource is not released.
If your application instantiates COM objects, check that you properly close them.
If you use older version of Delphi, you can try to locate possible memory leaks with FastMM
Edit, examples as requested:
I had two situations where application sometimes would stay resident in memory after exit. Both applications would disappear from taskbar, but they would be still active - visible in task manager. Both applications were created with Delphi 7.
First application has one main window with panel in which ather forms are embedded. Each form is standard TForm. Each form is created first time user requests it. Everything worked without problems in test environment, but users reported that from time to time, application would remain in memory, usually after longer usage - when user displayed almost all of the forms in application. I could not replicate this behavior while testing. That was first time I found out about FastMM. When I first run application with FastMM, it reported that some of forms embedded in main form were not released. This version was tested at user site and it turned out that 2 forms that have lots of data aware components would hang up and prevent application from exiting. When I added code that makes sure that all created forms are released before main form, application never hung up on exit.
Second example is application that uses COM to activate GIS editor (Geomedia) to manipulate some map data. I imported type libraries and created Delphi wrapper object. Some of created objects were not freed when application ends. Application icon disappeared from task bar, but application and GIS editor were still active and visible in task manager. Again, it did not happen every time application run. I included FastMM in application and it reported that some objects were not freed. I made sure that every created object gets freed and after that application did not hang on exit any more.
... and if you need to close single form, then use:
Form.Close;
GUI AND HANDLER DELETED. Reference and some parts of memory is left to provide access to variables, constants, etc.
If you need to hide ( something like Minimize, only GUI is cleared ) form, then:
Form.Hide;
GUI is cleared, leaving internal resources untoauched ( reference, handler, memory )
If form is dynamic ( created at runetime ), then use:
Form.Destroy;
ALL RESOURCES WILL BE CLEARED FROM MEMORY, leaving reference and handlers attached so you could access its location in memory.
If form is dynamic and you will not use it for the same interface, then:
Form.Free;
ALL RESOURCES, REFERENCES, HANDLERS ARE DELETED. I recommend to use this to VCL TComponent class, not for TForm class.
Also, there is Form.FreeAndNill, but my guess that it deleted all memory and loaded handlers, only allowing to use same memory space in the same interface again... (I might be wrong though).
P.S. I hope I am not writing wrong things as the last time I read the theory was a long, long time ago... and it was about Destructor DESTROY in general ...
P.P.S ALSO PLEASE BE CAREFUL if you're writing a Vista-ready app - that it includes UAC Handling with manifests / runtime code and SuperBar compatibility requirement. Also Aero requires some additional megabytes to output file due its Aero feature ... :P