I am new to MSMQ and suspect I either have my queues configured wrong or programmatically (is that a word?)causing them to get hung up.
When everything starts I can send one message and that works wonderfully. I can see (ie via mmc on that machine) the message in the remote machine queue. I then go to access it and I get my UnsupportedFormatNameOperation error. If I try to send another message I get the same error in the send method that just worked a few seconds earlier.
What is even more frustrating is that my catch is NOT picking up the exception so I was unaware and looking elsewhere (read wasting time) till I explored the queue object in the debugger.
Now if I reset the Message Service on remote I lose my message in the queue and still get the same error. If I reboot same result.
On local (dev machine) if I reset the Message Service I still get the error. If I reboot something gets recycled and I can send exactly one message again.
Further after reboot of dev machine and exploring the queue object on the first run I find that I am getting the error the FIRST time around but it still sends the message.
So I am clearly doing something wrong but clueless as to what.
Here is my send code:
private void SendLoginMessage(...bunch of parms)
{
//hardcoded path? yup!!
MessageQueue msmq = new MessageQueue(#"FormatName:DIRECT=OS:W2K8R2_SQL2K8R2\private$\best_simulator");
try
{
LoginStatusMessage LgnMsg = new LoginStatusMessage()
{
...assign parms to my
};
msmq.Send(LgnMsg);
}
catch (MessageQueueException msmqex)
{
MessageBox.Show(msmqex.Message);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
msmq.Close();
}
}
The description for UnsupportedFormatNameOperation is
The requested operation for the specified format name is not supported.
Message Queuing returns this error when the requested operation is not supported for the specified format name. Operations include trying to open a queue to receive messages by specifying a direct format name.
So I guess your problem may be at your receive code.
Related
Sometimes, about 1 of 10000 rabbit acks I have problem with acking properly.
In scenario with failure when I am acking message A I got no exception. Seems like everything went ok. When I enqueue next message B I am getting exception System.IO.EndOfStreamException: SharedQueue. Stack trace says that exception was thrown in RabbitMQ.Util.SharedQueue.EnsureIsOpen() which is private method.
There is a problem - A message is not acked! I got no exception when acking, but it is still not acked! There is a small chance that two application can get the same message. Is there anything I can do about it?
I already tried to change some settings like:
AutomaticRecoveryEnabled = true;
RequestedHeartbeat = 60;
NetworkRecoveryInterval = TimeSpan.FromSeconds(10);
And wrote a method to test connection before every ack:
public bool HasFullConnection() {
if (!HasServerConnection(Config.ConnectionConfig.HostAddress)) return false;
if (!RabbitMQConnection.IsOpen) return false;
if (!RabbitMQClient.IsOpen) return false;
return true;
}
Unfortunelly - problem still exists.
So, there are a couple of things going on here. First, as you've probably found out by now, the C# client library doesn't handle off-nominal situations very well. Second, and more importantly, your application design requires 100% reliability on acking, which it should not.
A failure rate of 1 in 10,000 (or 0.01%) is reasonably good. If you're only seeing ack failures on 0.01% of your messages, I would consider that to be an acceptable level of failure. Acknowledgements in RabbitMQ are delivered to the broker asynchronously, and are based on the channel and consumer that originally received the message. Many things can happen between the time a message was received and when it was actually acknowledged. Thus, if anything happens which disrupts the consumer, channel, broker, or connection, the message is assumed to have failed and is re-delivered.
This is known as at least once delivery. The alternative to this is at most once delivery (the alternate does not use acknowledgements). So, your system should be designed to handle redelivered messages, assuming you're using at most once delivery.
I have a problem with my Lync client that I am designing. I am running Lync 2013 in UI Suppression mode and I am able to send/receive IM's just fine, and begin audio calls. But a problem occurs when I try to receive an audio conversation from someone else. I get a System.UnauthorizedAccessException when I try to call this line of code:
conv.Modalities[ModalityTypes.AudioVideo].BeginConnect(ModalityCallback, asyncState);
It runs perfectly fine otherwise, and the call goes through okay and I can hear and talk to the other side just fine, but my User Interface freezes and I can't control anything due to this error. Even when the other side hangs up, I have to kill the process in Task Manager.
Here is my InitiateAVStream method, based on the MSDN Join Lync conversation example:
public bool InitiateAVStream()
{
Console.WriteLine("InitiateAVStream");
if (conv.State == ConversationState.Terminated)
{
return false;
}
if (conv.Modalities[ModalityTypes.AudioVideo].CanInvoke(ModalityAction.Connect))
{
conv.Modalities[ModalityTypes.AudioVideo].ModalityStateChanged += _AVModality_ModalityStateChanged;
conv.Modalities[ModalityTypes.AudioVideo].ActionAvailabilityChanged += _AVModality_ActionAvailabilityChanged;
//Accept the notification. If Lync UI is enabled, incoming call notification is closed.
conv.Modalities[ModalityTypes.AudioVideo].Accept();
//Connect the AV modality and begin to send and received AV stream.
object[] asyncState = { conv.Modalities[ModalityTypes.AudioVideo], "CONNECT" };
try
{
conv.Modalities[ModalityTypes.AudioVideo].BeginConnect(ModalityCallback, asyncState);
}
catch (Exception ex)
{
Console.WriteLine(ex.StackTrace);
}
return true;
}
return false;
}
The output message:
A first chance exception of type 'System.UnauthorizedAccessException' occurred in Microsoft.Lync.Model.dll
at Microsoft.Office.Uc.ModalityClass.Connect(ModalityConnectOptions _options, Object _modalityCallback, Object _state)
at Microsoft.Lync.Model.Conversation.Modality.BeginConnect_private(ModalityConnectOptions options, AsyncCallback modalityCallback, Object state)
at Microsoft.Lync.Model.Conversation.Modality.BeginConnect(AsyncCallback modalityCallback, Object state)
at UIPrototype.MeetingForm.InitiateAVStream() in c:\Users\morrissi\Documents\Visual Studio 2012\Projects\UIPrototype\UIPrototype\MeetingForm.cs:line 758
Any input would be greatly appreciated. And it's strange to me that it only occurs when I try accepting an incoming audio call. Everything else works fine. I have not started work on video calls yet, but I will once I get audio working.
Thanks
Edit:
Replacing BeginConnect with BeginRetrieve still throws the same error and produces the same results. Still not sure what to do.
Where are you running your application from? I had a very similar stacktrace and moving the application into "C:\Users\MyUser" resolved the problem for me.
I was able to solve the problem. Apparently when you are connecting just an audio call, the only line you need is
conv.Modalities[ModalityTypes.AudioVideo].Accept();
You do not need to call BeginConnect to connect the audio. Removing BeginConnect prevents the error from being thrown and the audio connects just fine still. BeginConnect is used to connect video.
My problem with the form not loading completely and freezing is unrelated, it appears. That is being caused because I am trying to create a new form within ConversationManager_ConversationAdded. If I try creating a new form on a button click, it loads just fine and works, but it seems to be the event that is preventing it from working properly.
I'm not good enough at this to recognize when an error is being caused by Lync or C# yet.
Current Setup includes a windows service which picks up a message from the local queue and extracts the information and puts in to my SQL database.According to my design
Service picks up the message from the queue.(I am using Peek() here).
Sends it to the database.
If for some reason i get an exception while saving it to the database the message is back into the queue,which to me is reliable.
I am logging the errors so that a user can know what's the issue and fix it.
Exception example:If the DBconnection is lost during saving process of the messages to the database then the messages are not lost as they are in the queue.I don't comit untill i get an acknowledgement from the DB that the message is inserted .So a user can see the logs and make sure that the DBconnection exists and every thing would be normal and we dont lose any messages in the queue.
But looking into another scenario:The messages I would be getting in the queue are from a 3rd party according a standard schema.The schema would remain same and there is no change in that.But i have seen some where i get some format exceptions and since its not committed the message is back to the queue.At this point this message would be a bottle neck for me as the same messages is picked up again and tries to process the message.Every time the service would pick up the same message and gets the same exception.So this loops infinitely unless that message is removed or put that message last in the queue.
Looking at removing the message:As of now if i go based on the format exception...then i might be wrong since i might encounter some other exceptions in the future .
Is there a way i can put this messages back to the queue last in the list instead beginning of the queue.
Need some advice on how to proceed further.
Note:Queue is Transactional .
As far as I'm aware, MSMQ doesn't automatically dump messages to fail queues. Either way you handle it, it's only a few lines of code (Bill, Michael, and I recommend a fail queue). As far as a fail queue goes, you could simple create one named .\private$\queuename_fail.
Surviving poison messages in MSMQ is a a decent article over this exact topic, which has an example app and source code at the end.
private readonly MessageQueue _failQueue;
private readonly MessageQueue _messageQueue;
/* Other code here (cursor, peek action, run method, initialization etc) */
private void dumpToFailQueue(Message message)
{
var oldId = message.Id;
_failQueue.Send(message, MessageQueueTransactionType.Single);
// Remove the poisoned message
_messageQueue.ReceiveById(oldId);
}
private void moveToEnd(Message message)
{
var oldId = message.Id;
_messageQueue.Send(message, MessageQueueTransactionType.Single);
// Remove the poisoned message
_messageQueue.ReceiveById(oldId);
}
I keep receiving an error when i try to Send to the queues
The specified format name does not support the requested operation. For example, a direct queue format name cannot be deleted.
My queue name is stored in a config file and looks like this
"FormatName:Direct=OS:MyComputerName\PRIVATE$\MyQueue"
There are 2 queues that exist, each queue has permissions set so that EVERYONE has Full Control.
SyncUser you can assume = "EVERYONE" or "My_Domain\operator"
//init the queues
qSync = new MessageQueue(queueName + "-sync")
{Formatter = new XmlMessageFormatter(new Type[] {typeof (String)})};
qClient = new MessageQueue(queueName + "-client")
{Formatter = new XmlMessageFormatter(new Type[] { typeof(String) })};
Creating the queues doesn't cause any errors, but I receive errors when i call this Send function
**Send(qSync, "This is a message");** //Example
public void Send(MessageQueue queue, string msg)
{
try
{
queue.Send(msg);
}
catch (MessageQueueException mqx)
{
var e = string.Format("Failed to Send - {0} | {1}", queue.QueueName, mqx.Message);
OnSynchronizerMonitor(new SyncEvent(e));
}
}
Any help would be greatly appreciated.
EDIT
It seems that my messages ARE making it to their remote queue destination, but the application is still throwing that error on every message sent. If I look at the MessageQueues (qSync|qClient) while debugging, that error shows up in several of the inner fields, before it is even used.
I hope someone can confirm this for me as I cant seem to find any forum questions or documentation that support this, but it seems that the MessageQueue has an issue with my Event setup.
I removed the event call and simply hardcoded the queue creation and send in its place within my main process and everything worked fine.
My setup is like so:
A Service - Creates a Processor, a Synchronizer, and sets the events.
Processor starts a thread in which it processes string transactions, on a successful process the transaction needs to be sent via the Synchronizer, so the Processor triggers event.
Synchronizer has already created the queues and is simply waiting for events to be triggered to send messages.
If anyone could shed some light on if this could be a cross thread issue or just a quirk in my system it would be appreciated.
**After a little more research and some trial and error, it seems I get the error due to a cross thread complication with the event. My guess is that it's a similar issue to UI objects being updated from a different thread than the one it was created on. The error is essentially an ownership issue. The messages still go though but the queue complains that its original owner isn't the one that initiated the call.
I'm trying to put a Message back into an MSMQ when an exception is thrown. The following code appears to work but the Message is not put back in the queue?
Message msg = null;
try
{
MessageQueue MQueue = new MessageQueue(txtMsgQPath.Text);
msg = MQueue.ReceiveById(txtQItemToRead.Text);
lblMsgRead.Text = msg.Body.ToString(); // This line throws exception
}
catch (Exception ex)
{
lblMsgRead.Text = ex.Message;
if (msg != null)
{
MessageQueue MQ = new MessageQueue(txtMsgQPath.Text);
MQ.Send(msg);
}
}
Couple of points: The best way to do this would be using a transaction spanning both queues; that way you'll know you won't lose a message.
The second part of it is to be careful about how the queues are created and how you submit messages to the second queue. In particular, MSMQ sometimes appears to "fail silently" when sending a message (though in reality an error message is recorded elsewhere in the dead letter queues), particularly if the transactional options of the send don't match the transactional nature of the target queue.
Is it really your intention to send that message back to the originator? Sending it back to yourself is very dangerous, you'll just bomb again, over and over.
I believe that you're looking to "Peek" at the message. Use: MessageQueue.Peek and if you succeed, then consume the message.
I managed to get the code above to work by creating a new queue and pointing the code at the new queue.
I then compared the 2 queues and noticed that the new queue was multicast (the first queue wasn't) and the new queue had a label with the first didn't. Otherwise the queues appeared to be the same.