I was wondering is there a way to load multiple instances of a DLL explicitly (i.e. with LoadLibrary call). Normally, a process loads a DLL just once when LoadLibrary is called (so that a single copy of the library resides in the process' memory) and all consequent calls of LoadLibrary done for the same library would be returning just the same handle of the library, returned by the very first call. To be more specific, I want to be able to load a separate instance of a DLL for each thread created inside of a process. Currently, if I do LoadLibrary in each thread, I just get the same pointer to a single instance of the library residing in the process' address space, and all threads in fact refer to the same functions from the library (here a big mess occurs in my app). Instead, I want each thread to create an individual instance of the library in a separate memory space so that the threads don't interfere with each other when calling functions from the library.
I don't think that is possible (until you create a new process and load the DLL in that process). DLLs are loaded at the process level (hence have entries in Process control block). Although your DLL can detect if new thread is created in the host application so that it can initialize TLS specific data in DLLMain method.
Related
I am working with an application GUI program and a console program, which call a COM object, which calls a worker DLL. Let’s call them ConsoleApp, GUIApp, COM DLL, and Worker DLL. The two Apps use CreateObject (VBasic) or GetProcID(C#) to activate the COM object and call it. In turn, the COM object calls the Worker DLL.
Problem: My goal is to register the COM DLL once, and then to continually develop the worker DLL without having to reregister the COM object all the time. Things work as expected when using the ConsoleApp. I can call it and see a debug message from the Worker DLL. When I change the message and recompile the worker, the next invocation of ConsoleApp shows the expected Mbox message.
But things do not work as expected with the GUIApp. To pick up any new worker DLL code, I must reregister the COM object (of course the GUIApp is not alive during re-registration). But that defeats the purpose of me trying to split the big COM+Worker DLL into two pieces to avoid re-registering the COM object all the time.
I have read many web pages (including here) on COM objects, but have not found answers that might work for my goal of having the registered COM object call a Worker DLL that can change during development.
Q. Is this the normal case that all DLLs referenced and called by a COM object are somehow bound to the COM object at registration time? (Answered above and below.)
Q. Is there any way for me to register the COM object once and have it call a DLL that I can work on in development without constant reregistering the COM (calling) object every time I change the Worker DLL code?
That's my ultimate goal if it is possible (and it seems to work as expected for the ConsoleApp).
UPDATE: RomanR suggested that I use ProcessExplorer to see which process is hanging on to the Worker DLL once GUIApp has been shut down. I could find the Worker DLL when GUIApp was alive but could not find it when GUIApp was shutdown. At the moment, the visible evidence is questioning my statement that the GUIApp never lets go of the Worker DLL. I will have to figure out a way of absolutely showing whether rebooting GUIApp picks up the new versions of Worker DLL.
The problem occurred because I registered the COM object direct from VStudio as part of the build (as Administrator). In the COM VStudio project, the reference properties for Worker.DLL specified Copy Local = True. Therefore, at the time of registration, the COM object was referencing the locally-copied version of Worker.DLL and not the future (later modified) copies of Worker.DLL that were stored elsewhere.
If I set Copy Local = False, I could register the COM object, but it would fail because it could not find the Worker.DLL at runtime.
The easiest solution was to 1) close the GUIApp to release the COM and Worker DLLs, 2) modify the Worker DLL with new code, 3) and copy the new Worker DLL into the COM project\bin\Debug folder where the Copy Local=True operation would put it. That way the registered COM object would pick up the most recent Worker DLL from the expected location.
Another solution (that I have not tried) is to modify the COM code to dynamically load and instantiate Worker.DLL from some dynamic location. That looks like a good approach too, although it does not give compile-time feedback on Worker DLL methods, etc.
I meet a question about the interview test:
When a dll is loaded into memory, which part(s) can be shared between processes?
A. code segment
B. static variable global variable
C. external difinitions and references for linking
D. BSS segment
who can give me an answer and a clear explation?
Processes are actually isolated programs running multiple threads in an OS. Generally operating system policy says, All processes are memory isolated from each other.
Code Segment : [NOT SHARED]
BSS and Static Fields : [NOT SHARED]
Reason is very simple, why a operating system allow process A to access process B's binary? that's security and memory protection violation. process A could corrupt (if write access is given) process B memory.
what about External Definitions?
Here comes the interesting part, External definitions could be statically or dynamically linked.
statically linked library implies definitions are linked at compiled time and programs binary contains It's machine code.
dynamically linked implies definitions are linked just after user commands to load any program in memory. OS calls dynamic library loader to resolve external dependencies of the program by providing shared object's path.
This shared object is cached by operating system in a different page frame, and every time when a program demands for this library, It simply copy It's page frame to process's virtual memory; and do required dynamic linking. This way multiple process have same binary of a single library.
It save RAM memory and time in loading library from disk, Also dynamic linking reduces binary size of the program.
It is also possible that the OS choose to load library again from disk, and thus make two copies of same library. This is a part of dynamic linking operation. I don't go into more depth, but if you are really interested https://en.wikipedia.org/wiki/Dynamic_linker or just ping me in comments section.
But regarding BSS and static fields, It is again not shared; Whenever a write operation is performed on such region (which is shared). Operating System create a new copy of that region for the other process. This makes sure that both process have their own copy of BSS and static fields.
I'm implementing a C++ library that wraps a COM library (IMAPI) to more easily provide the functionality throughout our applications.
It contains wrapper classes for the various interfaces of IMAPI. These are instantiated in the GUI thread of a client application to get information about the drives and their current medium. However, these objects also have functions to e.g. write data to a medium, which is a blocking function call.
Usually I would simply put this blocking function call onto another thread and execute it asynchronous to avoid blocking the GUI. However, since the COM objects were created in the GUI thread, which is initialized with COINIT_APARTMENTTHREADED (STA), this is not possible.
How do I best handle this in my shared library so that its clients do not have to worry about these details? Is the best thing to do to create a thread that belongs to my library that is initialized with COINIT_MULTITHREADED and is responsible for the creation of the COM objects?
I have a dll, which is loaded by the couple of processes. In that DLL source code I have an instance of global variable. Will this global variable be the same in all loaded processes ? Or will it be as the unique variable in each process ?
It will be unique to each process, unless (i) you've written explicit code to share inter-process or (ii) are still using a 16 bit dll.
Is there possible to create a COM-instance in it's own, dedicated, host-process?
I guess some background is needed.
We have an end-user client which has it's central logical components inside an singleton-COM object. (Not propper singleton, but it uses global variables internally, so it would fail.) So that there should be only one instance per exe-file. Convenient while making the client.
However, I should now make a "client-simulator" to test the server-side. I therefore which to make 20 instances of the client-component.
If I could make each instance instanciate in its own exe-host, then the singleton-issue would be handled.
Regards
Leif
I have been struggling with this problem for a few days. I finally found a solution that works. My COM object is written using ATL, so my code snippet will be geared toward that, but the technical solution should be clear. It all hinges on how the class objects are registered. The REGCLS_SINGLEUSE flag is the key. I now have separate processes for each object instance.
In the ATL module, override the RegisterClassObjects() function as follows:
HRESULT RegisterClassObjects(DWORD dwClsContext, DWORD dwFlags) throw()
{
return base::RegisterClassObjects(CLSCTX_LOCAL_SERVER, REGCLS_SUSPENDED | REGCLS_SINGLEUSE);
}
From MSDN regarding REGCLS_SINGLEUSE:
REGCLS_SINGLEUSE
After an application is connected to a class object with
CoGetClassObject, the class object is removed from public view so that
no other applications can connect to it. This value is commonly used
for single document interface (SDI) applications. Specifying this
value does not affect the responsibility of the object application to
call CoRevokeClassObject; it must always call CoRevokeClassObject when
it is finished with an object class.
My theory is that because the registration was removed from public view, it causes a new process to be created for the subsequent instantiations.
This other question mentioned a description of how to use DLLHost as a surrogate process:
http://support.microsoft.com/kb/198891
I've never tried this myself, and I don't know off-hand if you can specify flags for the factories (which control if surrogates can be reused for multiple objects), but maybe you can tweak that via DCOMCNFG or OLEVIEW.
My COM days are long gone, but as far as I remember, there's no built-in way to do that.
It might be easier to rewrite your code so it supports multiple instances than to go the one-process-per-instance route with COM, but here's what you could do:
Use thread-local storage for your global variables and write another CoClass, where each instance owns its own thread through which accesses to the class with the global variables are marshaled. This would at least allow you to avoid the performance impact of DCOM.
Write your own out-of-process exe server (similar to windows' DllHost.exe) to host your COM instances. This requires IPC (Inter-Process Communication), so you either have to code something yourself that marshals calls to the external process or use DCOM (presuming your COM object implements IDispatch)