执行以下代码时出现异常。有什么想法是错的吗?
string queueName = "FormatName:Direct=TCP:1.1.1.1\\Private$\\test";
MessageQueue queue;
if (MessageQueue.Exists(queueName))
queue = new System.Messaging.MessageQueue(queueName);
else queue = MessageQueue.Create(queueName);
queue.Send(sWriter.ToString());
编辑:
这是异常消息和stacktrace的第一行
无法确定具有指定格式名称的队列 存在。
在System.Messaging.MessageQueue.Exists(String path)
顺便说一句,它适用于本地队列。
答案 0 :(得分:37)
从您的示例中,您似乎正在尝试检查是否存在远程专用队列,但正如MessageQueue.Exists
文档所述:
无法调用存在来验证 存在远程私人队列。
尝试这样做会产生InvalidOperationException
。
如果您确实需要工作流程的此信息,可以使用MessageQueue. GetPrivateQueuesByMachine
方法并迭代结果以查找匹配项。如果你这样做,我建议你阅读Are Remote MSMQ Queues Reliable?,它会深入讨论这种方法。
This post from the excellent "MSMQ from the plumber's mate" blog提出了另一种选择:甚至不检查你的队列是否存在,“但是如果事实证明队列不存在,则处理未传递的消息。” (您需要跟踪管理队列和/或死信队列,但无论如何您应该这样做。)
答案 1 :(得分:4)
试试这个......
public static bool IsQueueAvailable(string queueName)
{
var queue = new MessageQueue(queueName);
try
{
queue.Peek(new TimeSpan(0, 0, 5));
return true;
}
catch (MessageQueueException ex)
{
return ex.Message.StartsWith("Timeout");
}
}
如果队列不存在或者运行应用程序的帐户没有足够的权限来访问它,则异常消息会明确说明。
AND,这适用于FormatName和通常的队列路径。
答案 2 :(得分:2)
检查异常消息的上述答案适用于引发英语异常的系统。我的系统引发了荷兰例外。我得到了“de time-out voor de gevraagde bewerking is verstreken。”因此,它不是一个非常强大的解决方案该异常具有一个属性MessageQueueErrorCode,应该用于检查是否发生了IOTimeout。
所以最好使用
return (ex.MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout);
而不是:
return ex.Message.StartsWith("Timeout");
答案 3 :(得分:2)
我最终得到了来自Svix,Erwin van Dijk和Joseph Daigle的答案。另外,我检查了ArgumentException
:
/// <summary>
/// Checks if a (remote) Microsoft Message Queue is available
/// </summary>
/// <param name="queueName">The name of the Message Queue.</param>
/// <returns>Returns true if the queue is available otherwise false.</returns>
public static bool IsQueueAvailable(string queueName)
{
MessageQueue queue;
try
{
queue = new MessageQueue(queueName);
queue.Peek(new TimeSpan(0, 0, 5)); // wait max. 5 sec. to recieve first message from queue (reduce if necessary)
return true;
}
catch (Exception ex)
{
if(ex is ArgumentException)
{ // the provided queue name is wrong.
return false;
}
else if (ex is MessageQueueException)
{ // if message queue exception occurs either the queue is avialable but without entries (check for peek timeout) or the queue does not exist or you don't have access.
return (((MessageQueueException)ex).MessageQueueErrorCode == MessageQueueErrorCode.IOTimeout);
}
// any other error occurred.
return false;
}
}
答案 4 :(得分:0)
您无法在远程队列上使用Exists方法,因此您必须模拟该远程计算机上的用户:
//usings
using System;
using System.Messaging;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
//Declaring the advapi32.dll
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(
string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
out IntPtr phToken);
private void IterateRemoteMQ()
{
IntPtr userToken = IntPtr.Zero;
bool success = LogonUser(
"REMOTE_USERNAME", //Username on the remote machine
".", //Domain, if not using AD, Leave it at "."
"PASSWORD", //Password for the username on the remote machine
9, //Means we're using new credentials, otherwise it will try to impersonate a local user
0,
out userToken);
if (!success)
{
throw new SecurityException("Logon user failed");
}
//Go through each queue to see if yours exists, or do some operation on that queue.
using (WindowsIdentity.Impersonate(userToken))
{
MessageQueue[] Queues = MessageQueue.GetPrivateQueuesByMachine("192.168.1.10");
foreach (MessageQueue mq in Queues)
{
string MSMQ_Name = mq.QueueName;
}
}