I have an application that can send a message to another application. Under pre-Win8 systems, that works fine. You give it the class or title, it uses enumwindows and finds the target window. With Win8, you can only enumerate top level windows, which means the TApplication class. The sending side is happy with that, but the receiver isn't.
To catch the message I'm using this code within my target form ...
function Tmain.AppMsgHookFunc(var wmsg : TMessage) : Boolean;
begin
Result := False;
if wmsg.Msg = WM_COPYDATA then begin
// Post the caught message back to this form.
postmessage (handle,wmsg.Msg,wmsg.WParam,wmsg.LParam);
end;
end;
... and then activate this with application.hookmainwindow etc.
This never fires. I see that if I use sendmessage to send myself the message then it does fire, but if I use postmessage that doesn't work, even on XP. Any suggestions?
WM_COPYDATA is a sent message. The system marshals data cross-process. In order to do so, the system must know that the message has been processed in order to be able to tidy up the resources used to make the cross-process marshalling happen. And the way that the system knows that the message has been processed is by forcing you to send it synchronously. That means you must use SendMessage rather than PostMessage.
The documentation also contains this information, although you do need to know how to interpret it.
An application sends the WM_COPYDATA message to pass data to another application.
Note the use of the word "sends". That is code for the message being synchronous.
Raymond Chen discusses this issue here: Why can't I PostMessage the WM_COPYDATA message, but I can SendMessageTimeout it with a tiny timeout?
The important difference from the standpoint of messages like
WM_COPYDATA is that with sent messages, the window manager knows when
message processing is complete: When the window procedure returns. At
that time, it can free the temporary buffers used to marshal the
message from the sender to the recipient. If the message were posted,
the window manager would never be sure.
Suppose the message is placed in a MSG structure as the result of a
call to GetMessage. Now the window manager knows that the receiving
thread has the potential for taking action on the message and the
buffers need to be valid. But how would it know when the buffers can
be freed? "Well you can wait until the exact same parameters get
passed in a MSG structure to the DispatchMessage function." But what
if the message loop discards the message? Or what if it decides to
dispatch it twice? Or what if it decides to smuggle it inside another
message?
Posted messages have no guarantee of delivery nor do they provide any
information as to when the message has been definitely processed, or
even if it has been processed at all. If the window manager let you
post a WM_COPYDATA message, it would have to use its psychic powers
to know when the memory can be freed.
Related
After logon, i would like to send a chat message to the Guild channel.
I'm currently listening for events:
PLAYER_ENTERING_WORLD
GUILD_ROSTER_UPDATE
Once those have fired (in order), i'd like to send a chat message. However, it never sends.
Code:
print("Should_send")
SendChatMessage(msgToSend, "GUILD");
It's also worth noting that if i then trigger this manually, it works.
I do see the "Should_send" print statement appearing in the default chat window each time - as expected. I've also checked that "msgToSend" contains content - and is less than 255 characters.
So, when can i call SendChatMessage?
Ok, in order to be able to send a chat message to guild, you need to wait for the event "CLUB_STREAM_SUBSCRIBED" to fire.
This is due to the Guild channel becoming a "community" channel of sorts - previously, it seems this wasn't required.
So, adding an event listener:
frame:RegisterEvent("CLUB_STREAM_SUBSCRIBED");
Resolves the issue.
You will likely need to set a flag for the event, then print later on another event.
You can send chat messages any time after you see the welcome message or after the welcome message was posted. Which is pretty soon after you able to receive events from your frames.
Here is what I would do to complete a similar mission:
Just put your send code in a macro to test it first. Don't worry about timing the message until you see it work in a macro.
You can make your own print to send generic messages to the chat window which should always work similar to:
function MyPrint( msg, r, g, b, frame, id)
(frame or DEFAULT_CHAT_FRAME):AddMessage(msg, r or 1, g or 1, b or 0, id or 0)
end
-- put these in your event handlers
MyPrint("event PLAYER_ENTERING_WORLD")
MyPrint("event GUILD_ROSTER_UPDATE")
And use that for debugging instead.
You need to divide and conquer the problem, because there are so many things that could be wrong causing your issue, no one here can really have a definitive answer.
I know for sure that if you try to write to chat before the welcome message with print it at least used to not work. I remember spooling messages in the past until a certain event had fired then printing them.
I want to write a mote-mote radio communication program, and want the receiver acknowledges back to the sender. I know the PacketAcknowledgements is recommended, but there are some questions I'm not sure about this interface.
1. If I use it in the sender mote,should i also uses interface Receive in the module of the sender mote
2. Should I write extra code in the receiver mote? Should I use interface PacketAcknowledgements too?
3. command error_t requestAck(message_t *msg) and command bool wasAcked(message_t *msg) should be used when and where
No.
No.
You need to call requestAck on a packet you're about to send just before calling send from interface AMSend or Send. Be sure to check an error code returned by requestAck, because FAIL indicates that the communication layer doesn't support synchronous acknowledgements (it depends on the radio chip and driver you use). Once the packet is sent, i.e., inside event sendDone (or later), call wasAcked, which returns true if the packet was acknowledged by the receiver.
More info in:
https://github.com/tinyos/tinyos-main/blob/master/tos/interfaces/PacketAcknowledgements.nc
I'm struggling with exception handling inside my Datasnap REST Service (Delphi XE3 but also tried with Delphi 10 Seattle). I have written half a dozen Windows Service over the years and I always include a TApplicationEvents component so that I can log any Application Exceptions to the Windows Event Log.
However, this behaviour is not happening with a Datasnap Service. The TApplicationEvents.OnException event never gets fired, so I assume something else is eating the exception and handling it before it gets here.
The exception is displayed in the web service method's result, which is fine because it means I can at least display something on the client side, but I'd also like to catch it before then so that I might be able to handle different exceptions server-side.
The only consistent way I have managed so far is to wrap each individual method in a try..except block, and handle the exception in each method, before re-raising the exception. However, with a Web Service of 20 methods and growing, this isn't really going to scale up.
I have also tried implementing the OnError, OnTrace and other events of the some of the Datasnap components (TDSServer, TDSHTTPService, TDSTCPServerTransport, etc.) but these never seem to get fired either.
Has anyone come across anything like this, please?
Tl;Dr: it's not implemented in a usable fashion (in 10.1 Berlin).
I came across the same problem and after reading through a lot of source, I found no practical solution.
So an exemplary (my) StackTrace would look like this:
MyClass::MyServerMethod()
/* skipping some funny unimportant RTTI/TValue handling here */
System::Rtti::TRttiMethod::Invoke
Dsreflect::TDSMethod::Invoke(TObject, TDSMethodValues)
TDSServerConnectionHandler::DbxExecute(const TDBXExecuteMessage)
TDSServerCommand::DerivedExecuteUpdate
TExecuteCallback
TDSService::Execute(const string, const TRequestCommandHandler, TExecuteCallback)
TDSService::ProcessRequest(const string, const TRequestCommandHandler, TExecuteCallback)
TDSRESTService::ProcessREST(const string, const string, const TArray<Byte>, const TRequestCommandHandler)
TDSRESTService::ProcessGETRequest(const string, TStrings, TArray<Byte>, TRequestCommandHandler)
TDSRESTServer::DoDSRESTCommand(TDSHTTPRequest, TDSHTTPResponse, string)
TDSRESTServer::DoCommand(TDSHTTPContext, TDSHTTPRequest, TDSHTTPResponse)
Dshttpwebbroker::TDSRESTWebDispatcher::DispatchRequest(TObject, Web::Httpapp::TWebRequest, Web::Httpapp::TWebResponse)
Note: This depends entirely on your usage of DataSnap. In the above case requests are passed into the DataSnap API through TDSRESTWebDispatcher (comming from TIdCustomHTTPServer).
Every Exception raised in a ServerMethod will end up in TDSService::ProcessRequest.
In this procedure every Exception is caught and ONLY its Message is added to a TRequestCommandHandler->CommandList.
Further down the Message is written as JSON/DBX command to the output.
So we can never handle the Exception Object and access the StackTrace or other information. So this alone is unacceptable and has to change
The good news is, that this procedure is virtual and can be overwritten. The bad news is, that in the example above you would have to extend TDSRESTService with your own ProcessRequest procedure (including your errorhandler), TDSRESTServer with own DoDSRESTCommand (in there the TDSRESTService is created in a monstrously large procedure) and TDSRESTWebDispatcher (depending on your usage).
My personal recommendation is to don't use DataSnap.
Note: At the point of writing this, I haven't found any invoke of the OnError event.
I am working on the project where I communicate with another device over COM port.
For incoming data I am using VaComm1RXchar event, there I store the message into the array and increment msgIndex which represents number of messages.
Then I call the function where I work with this message.
Inside this function is this timeout cycle where I wait for this message:
while MsgIndex < 1 do
begin
stop := GetTickCount;
if (stop - start)> timeout then
begin
MessageBox(0, 'Timeout komunikace !', 'Komunikace', MB_OK);
exit(false);
end;
sleep(10);
end;
The strange thing for me is that, when have it like this above then it always end with timeout. But when I put on there before this while cycle a ShowMessage('Waiting') then It works correcly.
Does anyone know what can caused this and how can I solve it? Thanks in advance!
We can deduce that the VaComm1RXchar event is a synchronous event and that by blocking your program in a loop you are preventing the normal message processing that would allow that event to execute.
Showing a modal dialog box, on the other hand, passes message handling to that dialog so the message queue is properly serviced and your Rx events and handled normally.
You can be certain this is the case if this also works (please never write code like this - it's just to prove the point):
while MsgIndex < 1 do begin
stop := GetTickCount;
if (stop - start)> timeout then begin
MessageBox(0, 'Timeout komunikace !', 'Komunikace', MB_OK);
exit(false);
end;
Application.ProcessMessages; // service the message queue so that
sleep(10); // your Rx event can be handled
end;
If there is a lesson here it is that RS-232 communication really needs to be done on a background thread. Most all implementations of "some chars have been received" events lead to dreadful code for the very reason you are discovering. Your main thread needs to be free to process the message that characters have been received but, at the same time, you must have some parallel process that is waiting for those received characters to complete a cogent instruction. There does not exist a sensible solution in an event-driven program to both manage the user interface and the communication port at the same time on one thread.
A set of components like AsyncPro**, for example, wrap this functionality into data packets where synchronous events are used but where the components manage start and end string (or bytes) detection for you on a worker thread. This removes one level of polling from the main thread (ie: you always get an event when a complete data packet has arrived, not a partial one). Alternatively, you can move the communication work to a custom thread and manage this yourself.
In either case, this is only partly a solution, of course, since you still cannot stick to writing long procedural methods in synchronous event handlers that require waiting for com traffic. The second level of polling, which is managing a sequence of complete instructions, will still have you needing to pump the message queue if your single procedure needs to react to a sequence of more than one comport instruction. What you also need to think about is breaking up your long methods into shorter pieces, each in response to specific device messages.
Alternatively, for heavily procedural process automation, it is also often a good idea to move that work to a background thread as well. This way your worker threads can block on synchronization objects (or poll in busy loops for status updates) while they wait for events from hardware. One thread can manage low level comport traffic, parsing and relaying those commands or data packets, while a second thread can manage the higher level process which is handling the sequence of complete comport instructions that make up your larger process. The main thread should primarily only be responsible for marshalling these messages between the workers, not doing any of the waiting itself.
See also : I do not understand what Application.ProcessMessages in Delphi is doing
** VAComm may also support something like this, I don't know. The API and documentation are not publicly available from TMS for ASync32 so you'll need to consult your local documentation.
What happens is that a modal message loop executes when the dialog is showing. That this message loop changes behaviour for you indicates that your communications with the device require the presence of a message loop.
So the solution for you is to service the message queue. A call to Application.ProcessMessages in your loop will do that, but also creates other problems. Like making your UI become re-entrant.
Without knowing more about your program, I cannot offer more detailed advice as to how you should solve this problem.
I have come to the point of thinking that the onWrite Event of a ClientSocket is redundant when I directly write bytes into the socket connection via SendBuf().
Is my point of thinking somewhere in the desert?
The Delphi Documentation is also somewhat bad because it just sais: "Write a routine for the onWrite event to write into the socket connection."
OnWrite is used when you're using asynchronous IO (when you have ClientType = ctNonBlocking, in other words). It's called when the socket's ready for you to send data.
Thus, your thinking's only half in the desert: if you're using ctBlocking, then don't bother with OnWrite at all. If you need that thread to send data and get on with other stuff at the same time, then use ctNonBlocking and write to the socket in OnWrite.
When you use async sockets, Windows will send your socket a CM_SOCKETMESSAGE, handled by TCustomWinSocket.CMSocketMessage. When that message has its SelectEvent property set to FD_WRITE, the OnWrite's (ultimately) invoked.
The magic ingredient here is the call to WSAAsyncSelect in TCustomWinSocket.DoSetAsyncStyles.