|
Hello folks!
I have a DLL that is loaded into a process, in its DLLMain it starts a thread which does some initialization, creates a window and runs a message loop. This works fine. But when the DLL is unloaded i want to stop the thread cleanly, so what i do is post a certain message using PostThreadMessage (or simply PostMessage to the window) to which the thread is suposed to break the message loop, do cleanup and exit. I (try to) post the message when DLLMain is called with DLL_PROCESS_DETACH and then wait for the thread to terminate. The problem is, by the time DLL_PROCESS_DETACH runs the thread has already been terminated and never got the chanche to do any cleanup by "someone else".
So my question is, how could i terminate the thread cleanly when (before) the DLL is unloaded?
Thanks for any replies in advance.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
You really shouldn't be doing that stuff in DLLMain.
It's much safer to add exported initialize and cleanup functions to
the DLL.
More info: DllMain Callback Function[^]
Mark
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Yeah, i know, but the problem is, i have no control over the loading process, so i can't make it call any exported functions in my DLL, all i get is a call to DLLMain upon load and unload. Thanks for the reply, any other ideas maybe?
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
Maybe you could hook FreeLibrary[^] and if hModule is equal to your DLL post your thread message and then call the original.
Best Wishes,
-David Delaune
|
|
|
|
|
I have thought of that, but that seems a bit overkill to do, but i will keep it in mind, thank you.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
You did not mention when your DLL unloads but if the host process is exiting by way of the ExitProcess Function then the first thing that happens is termination of threads. ExitThread is never called, your thread is killed by the TerminateThread Function. Then your DLL is unloaded. At this point your thread is already dead. If you do not have any control ofer the source code/functionality of the host process then there is essentially nothing that you can do. Unless you hook the host process functions of course. Now that I think about it.. hooking FreeLibrary will get you nowhere. ExitProcess would perhaps be a better candidate.
Better yet, you could just design your DLL so it doesn't have to do all this crap when forcibly unloaded.
Best Wishes,
-David Delaune
|
|
|
|
|
Code-o-mat wrote: The problem is, by the time DLL_PROCESS_DETACH runs the thread has already been terminated
By what means has the thread been terminated already?
Why not make it so that DLL_PROCESS_DETACH posts the quit message to the window and then the thread cleans up and exits?
|
|
|
|
|
That's exactly what i did, but as said, when i get the DLL_PROCESS_DETACH the thread has already been killed. I think when the process calls FreeLibrary it automatically kills the threads created by the DLL and then calls the DLLMain function. So i guess it won't be possible to terminate the thread in DLLMain. I will have to find another way, thanks for the reply.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
Just use an event object to synchronize.
1) Create an event object.
2) During Dll unload process, After posting the message to thread, wait for the event to be signaled.
3) When the thread finishes cleanup, it should signal the event and exit.
4) When the event is signaled, delete the event and just exit.
Does this helps?
Regards,
Jijo.
_____________________________________________________
http://weseetips.com[ ^] Visual C++ tips and tricks. Updated daily.
|
|
|
|
|
I simply use WaitForSingleObject with the handle of the thread after posting the message to wait for its termination. This worked fine in other cases, althorough i never before tried it in a DLL.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
There is a variation of the GDI+ Graphics class method "MeasureString" that has an optional parameter "codepointsFitted" that is a pointer to an INT. The documentation states that it is supposed to receive the number of code points that were actually fit into the layout rectangle.
When I try to use this "codepointsFitted" parameter, the INT that is pointed to always has the character count of the input string regardless of whether it indicates that the text bounding rect is larger than the text layout rect.
Has anyone ever gotten this variation of "MeasureString" using the "codepointsFitted" parameter to work? If so, what is the trick to getting that parameter to populate with the correct value?
Status MeasureString(
const WCHAR *string,
INT length,
const Font *font,
const SizeF &layoutRectSize,
const StringFormat *stringFormat,
SizeF *size,
INT *codepointsFitted,
INT *linesFilled
) const;
|
|
|
|
|
Seems to be working fine for me. The layout rect you are passing probably has enough width + height to hold all of your characters. Keep in mind that MeasureString will utilize *all* available space including height. So when it runs out of width it continues to render the text onto the next line. Pass it a HUGE string with a BIG font and see if you get the same results.
My test code:
RectF rSize;
INT iFitted;
INT iLines;
StringFormat format;
format.SetAlignment(StringAlignmentNear);
Font fontBold(L"Arial", 32, FontStyleBold);
CRect rcWin;
GetWindowRect(&rcWin);
RectF rgd(rctWin.left,rctWin.top,rctWin.right,rctWin.top + 32);
graphics.MeasureString(L"Test-Test-Test",-1,&fontBold,rgd,&format,&rSize,&iFitted,&iLines);
I copied and pasted that "Test-Test-Test" string about 20 times back to back to make my string bigger. The function correctly returns how many characers it was able to fit into the rect.
Best Wishes,
-David Delaune
|
|
|
|
|
I thought I had tried everything. You reminded me that I needed one additional tweak to my format flag. I had "StringFormatFlagsNoClip" in there and it was apparently causing the issue.
Thanks for taking the time to help me out. It is greatly appreciated.
|
|
|
|
|
bob16972 wrote: Thanks for taking the time to help me out. It is greatly appreciated.
No problem, I just happened to be working in GDI+ when I came across your post.
Best Wishes,
-David Delaune
|
|
|
|
|
As every one in the whole world knows, each PC has a "media access card" which is uniqe uneversally. I'd like to identify each system through Its MAC Number. can any one help me please?
Thank you masters!
|
|
|
|
|
By using GetAdaptersInfo() function, you could get MAC address. Check here[^] for code snippet.
Regards,
Jijo.
_____________________________________________________
http://weseetips.com[ ^] Visual C++ tips and tricks. Updated daily.
|
|
|
|
|
Thank you. you're so kind.
|
|
|
|
|
Jusef Marzbany wrote: Thank you. you're so kind. Rose
_____________________________________________________
http://weseetips.com[ ^] Visual C++ tips and tricks. Updated daily.
|
|
|
|
|
Do you mean this: http://en.wikipedia.org/wiki/MAC_address[^]? If you do, a MAC address belongs to the network card in the computer (can also belong to a modem or other network-connected device), so if a computer has no network card it has no MAC address either, also if you change the network card (like, you buy a new one) you get a new MAC address, also these can be spoofed. Don't know if this applies to your case or not or if this is usefull information for you or not, but i thought i mention it, maybe it helps some way to clear up possible misunderstandings. Good luck with whatever you are doing.
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
Sometimes, I don't know how do I aprociate. You're so kind. thank you.
|
|
|
|
|
Hi
I have a CString variable in my class like bellow i want to initialize it to nothing which way is best
Here i listed two ways. If any way is best why?
class MyClass
{
CString name;
MyClass()
{
name = _T(""); //way 1
name.Empty(); //way 2
}
}
Thanks in advance
----------------------------
KRISHNA KUMAR T M
|
|
|
|
|
what about
MyClass() : name(_T(""))
{
}
|
|
|
|
|
As far as i know CString's default constructor initializes it to an empty string anyways, so you don't have to do that explicitly. Or am i wrong?
> The problem with computers is that they do what you tell them to do and not what you want them to do. <
|
|
|
|
|
Code-o-mat wrote: CString's default constructor initializes it to an empty string anyways, so you don't have to do that explicitly.
Indeed!
Mark Salsbery
Microsoft MVP - Visual C++
|
|
|
|
|
Hi
Can I write a windows service and create a UI thread in it which should be able to identify / receive windows messages and process them? Is a window / dialog needed for a UI thread so that it can handle windows messages?
Thanx
|
|
|
|