How to receive message from a private workgroup queue - c#

I have a private queue on a remote machine that everyone and the anonymous login have full access to. The following code produces and error when trying to receive:
var qpath = #"FormatName:DIRECT=TCP:xx.xx.xx.xx\PRIVATE$\QueueName";
var q = new MessageQueue(qpath);
var msg = new Message();
msg.AttachSenderId = false;
msg.Recoverable = true;
msg.Body = "hello";
q.Send(msg); // <-- this works!
var recMsg = q.Receive(TimeSpan.Zero); // <-- this breaks! :|
The Error message is: Message Queue service is not available.
The sent message are ending up in the queue on the remote machine
The same happens when using OS:MachineName instead of TCP:xx.xx.xx.xx
The queue server is not part of the domain.
Any ideas?

If the remote machine is part of a different domain then:
MSMQ 3.0 applications running on cross-forest computers running a member of the family in non-trusted domains will use the secured remote read API. By default, the MSMQ 3.0 server hosting the queue containing the message to be read requires other domain computers making read requests to establish an encrypted channel, but such a channel cannot be established between non-trusted domains. Thus, remote read requests from cross-forest computers will be rejected. To modify this default behavior and allow the Message Queuing server to accept requests from domain computers that do not establish an encrypted channel, add the
HKLM\SOFTWARE\Microsoft
\MSMQ\Parameters\Security\NewRemoteReadServerAllowNoneSecurityClient
registry entry (a DWORD) and set it to 1.
This is form: Reading Messages from Remote Queues.

Related

"Remote computer is not available" with MSMQ purging

I have a server (say server A) where I configured a private MSMQ for queueing the messages and deployed an application on another server (say server B) to send messages. Server A and server B are not in the same network or domain. We have opened port 1801 on server A for the communication with MSMQ.
And we are using below code for sending messages from Server B to Server A
var queue = #"FORMATNAME:DIRECT=TCP:<remote_server>\private$\<queuename>";
var messageQueue = new MessageQueue(queue);
var message = new Message("Hi Message");
messageQueue.Send(message);
It is working fine if I send messages from Server B to the remote server A.
But if I try to delete all messages from the queue using the application hosted on the server A,it will throw the below exception
remote computer is not available.
I am using the below code for purging the queue.
var queue = #"FORMATNAME:DIRECT=TCP:<remote_server>\private$\<queuename>";
var messageQueue = new MessageQueue(queue);
messageQueue.Purge();
I have set below two properties [UrQueueName] -> Properties -> Security for testing
Set Everyone to Full Control
Set ANONYMOUS LOGON to Full Control.
How can I find out what the exact issue with purging, as I can send the messages to this remote server?
Do I need to open any other ports for purging other than 1801?

Error Code 67 ISO8583

So now I'm building a ISO8583 Payment Gateway application. This application is a client-server application that can act as a client or server. In this case, I'm handling the client side of the application.
At first, I connected the (client)app to a external server. I was sending inquiry message and it ran well (returning success message). Then, i'm trying to run this app as both client and server (run 2 apps and set my ip as ip host), one as client and the other one as a server. I'm sending inquiry message and it keeps returning response code 67 (other error). Meanwhile it's succeed when I run the app as client only.
I don't know if it helps but here's the inquiry method
/// <summary>
/// Send Inquiry Message
/// </summary>
private void SendInquiryMessage()
{
var requestMsg = new Iso8583Message(200);
DateTime transmissionDate = DateTime.Now;
requestMsg.Fields.Add(7, string.Format("{0}{1}",
string.Format("{0:00}{1:00}", transmissionDate.Month, transmissionDate.Day),
string.Format("{0:00}{1:00}{2:00}", transmissionDate.Hour,
transmissionDate.Minute, transmissionDate.Second)));
requestMsg.Fields.Add(11, _sequencer.Increment().ToString());
requestMsg.Fields.Add((int)ISO8583ProtocolFields.PROCESSING_CODE, "341019");
requestMsg.Fields.Add((int)ISO8583ProtocolFields.ADDITIONAL_DATA_61, "5271720012002010802012");
#region Send 0200
SendRequestHandlerCtrl sndCtrl = _client.SendExpectingResponse(requestMsg, 1000, true, null);
sndCtrl.WaitCompletion(); // Wait send completion.
if (!sndCtrl.Successful)
{
Console.WriteLine(string.Format("Client: unsuccessful request # {0} ({1}.",
_sequencer.CurrentValue(), sndCtrl.Message));
if (sndCtrl.Error != null)
Console.WriteLine(sndCtrl.Error);
}
else
{
sndCtrl.Request.WaitResponse();
if (sndCtrl.Request.IsExpired)
_expiredRequests++;
else
_requestsCnt++;
}
latestInquiryMessage = sndCtrl.Request.ReceivedMessage as Iso8583Message;
Console.WriteLine(latestInquiryMessage.Fields[39].Value);
#endregion
}
Anyone know what the problem is? What I could possibly miss?
Thank you!
I don't know which specific ISO-8583 implementation you are attempting to write to but a couple guesses based on what I do see or do not see and what your actual question is.
It seems especially odd that it works when it communicating with the remote server as client but not as both. Where is your communications configuration?
This points to your TCP/IP configuration and my guess is that you are attempting to listen and communicate on perhaps the same port so are not truly completing the TCP/IP handshake. While I believe you technically can listen on a port and communicate out it for a different process I think it unnecessarily complicates things.
So my guess is that what is happening and is your problem is that you are attempting to communicate with yourself, are maybe not getting fully connected and instead of saying "91 - Issuer Not Available" or "96 - System error" it is giving you the odd "67 other error" as it may not have been able to actually send it.
Do you have trace, or have you watched the connectivity with netstat -a 1 or even better Wireshark if you do not have trace to verify that you are getting fully established?

How to read MSMQ messages from a remote machine without installing message queueing on local machine?

There is a remote machine (let's call it MSMQ machine) which has MSMQ installed on it and is used by several other processes. I would like to read the messages on a given private queue of the MSMQ machine from my local machine - BUT, I would like to avoid installing Message Queuing on my machine, since what I need is simply to check and monitor the messages. I will not send nor receive messages (at least won't store them), I just want to "peek" at them.
Is there any way to do this? I have a code more a less like this now:
public string CheckMessageQueue(machine, queue)
{
StringBuilder Ret = new StringBuilder();
var path = machine "\Private$\" + queue;
try
{
MessageQueue mq = new MessageQueue(path);
Message msg = new Message();
msg = mq.Peek();
Console.WriteLine(msg.ToString());
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
if I run the code above I get the error message
"Message Queuing has not been installed on this computer."
No, there is no other way than installing MSMQ on your local machine as well. The client libraries uses the local server to communicate with remote servers.

What is the easiest way to test if a user is connected to our WAN?

A bit of background. I work for a corporation that has a global WAN. External users connect to it through a VPN and must be connected to it in order to have access to their emails and, of course, shared network directories.
I have a .Net application that is published and installed from our website using ClickOnce. User's who both do and do not work for the company have access to this application and it sends requests to a web service that is also published to the web server.
For reasons outside the scope of this question, when a user attempts to log into the application they should connect to the web service server by explicitly referencing the the computer name of the server (i.e. http://**server**/webservice/ws.asmx.) If a user is not connected to our WAN, they need to access it through our web address (i.e. https://**www.companywebsite.com**/webservice/ws.asmx.)
I know how to dynamically set the associated URL with the web service. My problem is that I can't think of an fast, reliable and easy way to test for the WAN connection.
Initially I tried to send a ping request (using the .Net Ping class) to the server with a rather short timeout. However, calling a ping operation against the server, when not connected to the WAN, returns an exception that states
An exeception occurred during the Ping request.
Below is the code associated with the property that tests for the WAN connection. It's simple but it keeps giving me above message when I test this off of our network.
public static bool ConnectedToWAN
{
get
{
try
{
Ping ping = new Ping();
PingReply reply = ping.Send("server", 2000);
return reply.Status == IPStatus.Success;
}
catch (Exception e)
{/* ' An exeception occurred during the Ping request.' */};
}
I would prefer not returning my connection state based off of the exception that I'm getting. Rather, I'd make an explicit call to the network that can validate the connection.
One quick note, I can't check the user's IP. Some of our users work for other organizations that have there own WAN. Since I'm checking their IP within a .Net WinForms application there is a chance that their IP address may be associated with their WAN. Instead, I need to check and see if they are specifically connected to our WAN, not just any WAN.
How can I do this?
I think the question is you need to resolve the host name if there are connected within company network rather than public accessible internet.
if that is the case, you can use DNS.BeginGetHostEntry and using asynchronous method to get the domain name system for specified host computer.
e.g
var host = '**Internal Server Name**';
Boolean isWANConnected = false;
String ConnectMessage ;
AsyncCallback callBack = new AsyncCallBack(GetHostName);
Dns.BeginGetHostEntry(host, callBack, host);
static void GetHostName(IAsyncResult result)
{
string hostname = (string)result.AsyncState;
try
{
IPHostEntry host = Dns.EndGetHostEntry(result)
ConnectMessage = host as String;
}
catch(SocketException e)
{
isWANConnected = false;
ConnectMessage = e.Message;
}
}
Can a user not on the WAN resolve that server IP? If not, you can use a DNS query to determine where you are.

Remote MSMQ Receive Error in C#

I am trying to send and receive from a remote queue. I can get the send to work (I see the message in the queue), however, when I try to receive I get an access denied error. My computer is on a different domain than the remote queue's computer, so I'm pretty sure this has something to do with the issue. Here is the code snippet:
MessageQueue queue = new MessageQueue(#"FormatName:DIRECT=OS:DEVAPP002\private$\queuetest");
queue.Send("This is a test");
Message msg = queue.Receive(); // Kaboom
To test if permissions are your problem, check that the Anonymous User has read/write access to the queue.
The Everyone user means everyone logged in the domain, at least with respect to the queuing service.

Categories