|
Hi Experts,
I have tried to implement WM_ENDSESSION in my CMainFrame class.
But I could not track it niether system logoff or system shutdown.
Please let me know how to implement and track this?
|
|
|
|
|
I find WM_ENDSESSION message's [^] wParam and lParam are quite informative about. Don't you?
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
|
|
|
|
|
I added WM_ENDSESSION handler to CMainFrame class of SDI application:
void CMainFrame::OnEndSession(BOOL bEnding)
{
CFrameWnd::OnEndSession(bEnding);
if(bEnding)
AfxMessageBox(_T("System is getting shutdown"));
else
AfxMessageBox(_T("System is getting log off"));
}
I am getting AfxMessageBox(_T("System is getting shutdown")) on system log off but not getiing any message at system shutdown.
When I click on shutdown button I am not getting any message. How could I get it?
|
|
|
|
|
Use the WM_QUERYENDSESSION message instead.
Best Wishes,
-David Delaune
|
|
|
|
|
Hello everyone,
Two questions about message pump in COM STA.
1. The term "message pump", means message queue? Pushing message into the message queue? Or retrieve message from the message queue?
2. What is the impact if the message pump is not alive in STA? It will block method invocation from other apartment?
thanks in advance,
George
|
|
|
|
|
I've never know message pump to mean anything other than extracting messages from the queue in an ordinary fashion.
All sorts of things can post messages into the queue, but you only handle then in a controlled fashion.
As for COM. I've never implemented a message queue - just Interfaces with methods, so I can't help you there.
But if I'm right STA stands for *single* threaded apartment. Wouldn't other apartments get their own copy of the com object, so it wouldn't block? If you start doing singleton tricks, then that would be your own problem, and you should only do tricks with your eyes open.
Iain.
Iain Clarke appears because CPallini still cares.
|
|
|
|
|
Thanks Iain!
Informative reply. I am not doing any tricks, I mean for general implementation for STA, if the message pump is blocked by STA owning thread, invocation from other apartment to the current STA will be block? Right?
regards,
George
|
|
|
|
|
George_George wrote: for general implementation for STA, if the message pump is blocked by STA owning thread, invocation from other apartment to the current STA will be block? Right?
Yes.
Calls from other apartments implies that the interface has to be marshalled.
When the call is made the RPC will send(!) a message to the STA thread. If that STA doesn't pump messages the call will block. This can happen even if the STA has a message pump but the thread is already inside a message handler or doing something else instead of pumping messages.
This is the same problem as sending messages from one thread to another instead of posting them. The difference between sending and posting is that posting doesn't wait until the message is handled, which means that you cannot deadlock when posting messages but you certainly can when sending them.
However, the RPC in this aspect send messages since all calls return a HRESULT which means that it has to wait for the result before it returns to the caller.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Thanks Roger,
You mean marshelling from one apartment will use SendMessage other than PostMesssage? Do you have any documents for that? (I have not learned that before)
regards,
George
|
|
|
|
|
George_George wrote: You mean marshelling from one apartment will use SendMessage other than PostMesssage?
I think you misunderstood me a little bit...
It's not setting up the actual marshalling with calls to e.g. ::CoMarshalInterThreadInterfaceInStream() or using the GIT that results in a sent message, it's the function call from the other apartment via the marshalled interface that causes this. The message sending happens behind the scenes of the proxy/stub implementation, unless we're talking about free-threaded apartments and that's way too early to talk about so forget about that for now.
Concentrate on using the STA and calling servers inside it from other apartments.
As for documents regarding this, I assume you've already found a great place to start in Lim Bio Liong's article[^] since you've posted a comment there.
Other good references are the books that he refers to in the article.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Thanks Roger!
I have read Lim's article and also the book Inside COM. But they both not mentioned whether a call from other apartment to STA will use SendMessage or PostMessage in stub/proxy.
Since you mentioned it in last post, I am just interested how do you think it will use SendMessage?
(not PostMessage or anything else?)
regards,
George
|
|
|
|
|
Well, in a technical detail calls between apartments may, or may not, use ::SendMessage() . Whether it's an actual ::SendMessage() or ::PostMessage() call doesn't matter and is irrelevant.
The behaviour from the client point of view is the same; it works as if you've used ::SendMessage() .
This is my point:
You asked if the call would block and the answer to that is simply 'yes'.
The RPC runtime will actually use ::PostMessage() to place a COM message in the message queue of the server, BUT the proxy will wait for the answer until the server responds.
This can be read in e.g. "Essential COM" by Don Box, chapter 5. If you have a MSDN Library (2005) installation you will also find this chapter as a book excerpt below "Win32 and COM Development". However, I was unable to find it at MSDN online.
Keep in mind that the server and client may not be located on the same machine which would make it impossible to use communication between the server and the client based on window messages. The network has to be involved.
But even if the network is involved, the same rules apply; the call from the client will block and the server must have a message loop that's not deadlocked.
According to my experience it seems to help programmers starting with COM calls crossing apartment boundaries to think of the call as if the message was sent using ::SendMessage() . The reason to even bring that up is that even a beginner have to know that an apartment exposing interfaces must have a message loop. It also assumes that the programmer is familiar with the problems using ::SendMessage() . If the COM beginner is told from the start that ::PostMessage() is used, chances are that he/she would believe that the call somehow would not block.
Regarding why the call is blocking, the simple reason is that each COM interface call must return a HRESULT and the result is unknown until the call has been serviced. For lengthy operations the server should, and usually would, use a callback interface to inform the client about the progress of the asynchronous operation. But this is asynchronous and non-blocking at a higher level.
If you still have question, please explain what you're trying to do that make you ask these questions.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Cool Roger,
I understand and agree with all of your points, except the below one, "the server must have a message loop that's not deadlocked.", how message loop prevent server from deadlock?
regards,
George
|
|
|
|
|
George_George wrote: how message loop prevent server from deadlock?
Perhaps I didn't put that very clear...
What I meant was when the message loop has called a message handler, the thread doesn't pump messages unless the message handler provides functionality for that.
The message pump of the server normally pumps other messages than COM messages, which means that the STA thread may be busy when a call is made from a COM client.
Example:
Let's say you have a COM server in the main application thread and you've spawned a worker thread and marshalled an interface to the server into the worker thread.
You send a user defined message from the main thread to the worker thread with ::SendMessage() , which boils down to a call via the marshalled interface. The deadlock is now a reality since the STA where the server lives doesn't pump messages, it's waiting for the ::SendMessage() call to return.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Thanks Roger,
1.
I am confused about your sample. You have one process and two threads. Which thread is the STA owning thread which create the COM component? The main process or the worker process?
2.
Roger Stoltz wrote: marshalled an interface to the server into the worker thread.
You mean worker thread is COM client, and main thread is COM server (STA). Worker thread marshelled an interface to the COM server STA?
regards,
George
|
|
|
|
|
George_George wrote: You have one process and two threads.
Exactly.
George_George wrote: Which thread is the STA owning thread which create the COM component?
The main thread of the application is the STA thread where the server is created. This is an ordinary in-process server situation. Calls to the server from this thread in the client are simply function calls.
The server may be any server that can be created as an in-process server, i.e. by calling ::CoCreateInstance( ..., CLSCTX_INPROC_SERVER ) .
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Thanks Roger,
This is what you mentioned before about your sample. In my understanding, the main thread should be the STA thread which contains the COM component, the worker thread should be the thread as client to invoke/use the main thread.
Why do you think the main thread will send message to the worker thread? I think in order for the worker thread as COM client to invoke the main thread, it should send message to the main thread?
Please feel free to correct me if I am wrong.
--------------------
You send a user defined message from the main thread to the worker thread with ::SendMessage()
--------------------
regards,
George
|
|
|
|
|
George_George wrote: Why do you think the main thread will send message to the worker thread?
This was only an example of how the message queue of the STA thread can be blocked.
It has nothing to do with your code.
"It's supposed to be hard, otherwise anybody could do it!" - selfquote "High speed never compensates for wrong direction!" - unknown
|
|
|
|
|
Thanks Roger,
I think I almost get your idea. Let me repeat to see whether my understanding is correct.
1. You create main thread (STA) and the worker thread (as COM client);
2. Worker thread will call the main thread, through marshelling;
3. When the main thread receives the method call in (2), it will call some method in worker thread through ::SendMessage, and will wait for reply from worker thread;
4. Since worker thread in (2) will be in wait status for main thread to return its call, the method call from main thread to the worker thread in step (3) will be blocked -- since the worker thread is in waiting status.
My understanding correct?
I think it is a situation when the main thread and the worker thread will wait for each other at the same time, it should be called deadlock??
regards,
George
|
|
|
|
|
Iain Clarke wrote: Wouldn't other apartments get their own copy of the com object, so it wouldn't block?
The following assumes the object being created lives in STAs:
- If another thread creates the object and the thread is a STA then a new object is created "in" that thread.
- If another thread creates the object and the thread is NOT in a STA then the object is created in an STA and the interface pointer is marshaled back to the creating thread.
Steve
|
|
|
|
|
Makes sense. I'm just glad I didn't pretend to be all expert! (For a change)
Iain.
Iain Clarke appears because CPallini still cares.
|
|
|
|
|
Cool and makes sense, Steve!
regards,
George
|
|
|
|
|
Hi all...
I'm trying to set the focus on my edit box with the help of following code
PostMessage(GetDlgItem(hPage1, IDC_EDIT1), WM_SETFOCUS, 0, 0);
This works fine as it set the focus but when i try to write anything on edit box it doesn't accept... Also when i press TAB button after that it behaves normally i.e it allows you to write...
what could be the problem??
Thanks..
Ash..
|
|
|
|
|
AFAIK, the WM_SETFOUCS message is not used to set foucs to a control. But it is send to notify that the window has got the Focus.
You should use SetFoucs() function to set focus to a control.
|
|
|
|
|
Thanks for your reply Naveen..
I tried SetFocus Also but using SetFocus doesn't set Focus on edit box..Also i tried to set focus using SendMessage with appropriate parameter but it behave like PostMessage only...
Ash..
|
|
|
|