How to get message constantly from remote IBM MQ - c#

I created a windows service that will connect to remote MQ and get the message as MQSTR format but after getting the message I didn't closed connection to remote MQ . My windows service will continuously check if data is available in remote MQ or not but after getting one message I need to restart my service to get the another message from remote MQ . Can anyone tell me what I need to do to get message constantly from remote MQ . Any clue or any link will do fine . Please Help
My C# windows service code is like this :
Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading.Tasks;
namespace MQ_listner
{
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
Service1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Linq;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MQ_listner
{
public partial class Service1 : ServiceBase
{
private MQReader MQReader;
private string _serviceName = "MQ_Listener";
private DateTime _TimeStart;
private bool _run = true;
private Thread _thread;
int WaitWhenStop = 0;
private DateTime _TimeEnd;
private TimeSpan _TimeDifference;
private TimeSpan _TimeElasped = new TimeSpan(0);
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
try
{
EventLog.WriteEntry(_serviceName + "was started at" + _TimeStart.ToString());
_run = true;
_thread = new Thread(new ThreadStart(StartMQListenerService));
_thread.IsBackground = true;
_thread.Start();
}
catch (Exception ex)
{
EventLog.WriteEntry(_serviceName + "was not started . Error Message : " + ex.ToString());
}
}
protected override void OnStop()
{
_run = false;
_thread.Join(WaitWhenStop);
_TimeEnd = DateTime.Now;
_TimeDifference = _TimeEnd.Subtract(_TimeStart);
_TimeElasped = _TimeElasped.Add(_TimeDifference);
EventLog.WriteEntry(_serviceName + "was stopped at " + _TimeEnd.ToString() + "\r\n ran for total time :" + _TimeElasped.ToString());
}
// MQ connection service
public void StartMQListenerService()
{
try
{
if (_run)
{
if (MQReader == null)
{
MQReader = new MQReader();
MQReader.InitializeConnections();
EventLog.WriteEntry(_serviceName + "MQ connection is established");
}
}
}
catch (Exception ex)
{
System.Diagnostics.EventLog.WriteEntry(_serviceName, ex.ToString());
System.Diagnostics.ProcessStartInfo startinfo = new System.Diagnostics.ProcessStartInfo();
startinfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startinfo.FileName = "NET";
startinfo.Arguments = "stop" + this.ServiceName;
Process.Start(startinfo);
}
}
}
}
****MQReader.cs****
using System;
using IBM.WMQ;
using System.Diagnostics;
using System.IO;
using System.Xml;
using System.Linq;
using System.Xml.Linq;
using System.Configuration;
namespace MQ_listner
{
internal class MQReader
{
public MQReader()
{
}
public void InitializeConnections()
{
MQQueueManager queueManager;
MQMessage queueMessage;
MQGetMessageOptions queueGetMessageOptions;
MQQueue queue;
string QueueName;
string QueueManagerName;
string ChannelInfo;
string channelName;
string PortNumber;
string transportType;
string connectionName;
QueueManagerName = ConfigurationManager.AppSettings["QueueManager"];
QueueName = ConfigurationManager.AppSettings["Queuename"];
ChannelInfo = ConfigurationManager.AppSettings["ChannelInformation"];
PortNumber = ConfigurationManager.AppSettings["Port"];
char[] separator = { '/' };
string[] ChannelParams;
ChannelParams = ChannelInfo.Split(separator);
channelName = ConfigurationManager.AppSettings["Channel"];
transportType = ConfigurationManager.AppSettings["TransportType"];
connectionName = ConfigurationManager.AppSettings["ConnectionName"];
String strReturn = "";
try
{
queueManager = new MQQueueManager(QueueManagerName,
channelName, connectionName);
strReturn = "Connected Successfully";
queue = queueManager.AccessQueue(QueueName,
MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING);
queueMessage = new MQMessage();
queueMessage.Format = MQC.MQFMT_STRING;
queueGetMessageOptions = new MQGetMessageOptions();
queue.Get(queueMessage, queueGetMessageOptions);
strReturn = queueMessage.ReadString(queueMessage.MessageLength);
}
catch (MQException exp)
{
strReturn = "Exception: " + exp.Message;
}
string path1 = #"C:\documents\Example.txt";
System.IO.File.WriteAllText(path1, strReturn);
}
}
}
Can anyone tell me what is wrong in my code? Do I need anything to add here to get message constantly from remote MQ . Please Help . Any link or clue will do fine .
EDIT
after certain amount of time I need to restart my service to fetch data from remote mq . Can you tell me why windows service needs to restart to fetch data . Any clue? any idea ?

Where is your queue close and queue manager disconnect? If you connect and/or open something, you must make sure you close and disconnect from it. I would strongly suggest you take an MQ programming course. Or go to the MQ Technical Conference which has sessions on programming MQ.
I posted a fully functioning C# MQ program that retrieves all of the messages on a queue at MQQueueManager message pooling
Here is an updated version of your MQReader class that should give you the right idea. Note: I did not test it. I leave that for you. :)
Also, you should be putting your connection information in a Hashtable and pass the Hashtable to the MQQueueManager class.
using System;
using IBM.WMQ;
using System.Diagnostics;
using System.IO;
using System.Xml;
using System.Linq;
using System.Xml.Linq;
using System.Configuration;
namespace MQ_listner
{
internal class MQReader
{
private MQQueueManager qManager = null;
private MQMessage inQ = null;
private bool running = true;
public MQReader()
{
}
public bool InitQMgrAndQueue()
{
bool flag = true;
Hashtable qMgrProp = new Hashtable();
qMgrProp.Add(MQC.TRANSPORT_PROPERTY, MQC.TRANSPORT_MQSERIES_MANAGED);
qMgrProp.Add(MQC.HOST_NAME_PROPERTY, ConfigurationManager.AppSettings["ConnectionName"]);
qMgrProp.Add(MQC.CHANNEL_PROPERTY, ConfigurationManager.AppSettings["Channel"]);
try
{
if (ConfigurationManager.AppSettings["Port"] != null)
qMgrProp.Add(MQC.PORT_PROPERTY, System.Int32.Parse(ConfigurationManager.AppSettings["Port"]));
else
qMgrProp.Add(MQC.PORT_PROPERTY, 1414);
}
catch (System.FormatException e)
{
qMgrProp.Add(MQC.PORT_PROPERTY, 1414);
}
if (ConfigurationManager.AppSettings["UserID"] != null)
qMgrProp.Add(MQC.USER_ID_PROPERTY, ConfigurationManager.AppSettings["UserID"]);
if (ConfigurationManager.AppSettings["Password"] != null)
qMgrProp.Add(MQC.PASSWORD_PROPERTY, ConfigurationManager.AppSettings["Password"]);
try
{
qManager = new MQQueueManager(ConfigurationManager.AppSettings["QueueManager"],
qMgrProp);
System.Console.Out.WriteLine("Connected Successfully");
inQ = qManager.AccessQueue(ConfigurationManager.AppSettings["Queuename"],
MQC.MQOO_INPUT_AS_Q_DEF + MQC.MQOO_FAIL_IF_QUIESCING);
System.Console.Out.WriteLine("Open queue Successfully");
}
catch (MQException exp)
{
System.Console.Out.WriteLine("MQException CC=" + mqex.CompletionCode + " : RC=" + mqex.ReasonCode);
flag = false;
}
return flag;
}
public void LoopThruMessages()
{
MQGetMessageOptions gmo = new MQGetMessageOptions();
gmo.Options |= MQC.MQGMO_WAIT | MQC.MQGMO_FAIL_IF_QUIESCING;
gmo.WaitInterval = 2500; // 2.5 seconds wait time or use MQC.MQEI_UNLIMITED to wait forever
MQMessage msg = null;
while (running)
{
try
{
msg = new MQMessage();
inQ.Get(msg, gmo);
System.Console.Out.WriteLine("Message Data: " + msg.ReadString(msg.MessageLength));
}
catch (MQException mqex)
{
if (mqex.Reason == MQC.MQRC_NO_MSG_AVAILABLE)
{
// no meesage - life is good - loop again
}
else
{
running = false; // severe error - time to exit
System.Console.Out.WriteLine("MQException CC=" + mqex.CompletionCode + " : RC=" + mqex.ReasonCode);
}
}
catch (System.IO.IOException ioex)
{
System.Console.Out.WriteLine("ioex=" + ioex);
}
}
try
{
if (inQ != null)
{
inQ.Close();
System.Console.Out.WriteLine("Closed queue");
}
}
catch (MQException mqex)
{
System.Console.Out.WriteLine("MQException CC=" + mqex.CompletionCode + " : RC=" + mqex.ReasonCode);
}
try
{
if (qMgr != null)
{
qMgr.Disconnect();
System.Console.Out.WriteLine("disconnected from queue manager");
}
}
catch (MQException mqex)
{
System.Console.Out.WriteLine("MQException CC=" + mqex.CompletionCode + " : RC=" + mqex.ReasonCode);
}
}
public void StopIt()
{
running = false;
}
}
}
Whenever you stop the service, make sure it calls the StopIt method in MQReader.

Related

How do i pass a variable value from Console application to windows form application in C# (visual studio)

I am doing a project in which i have to send the variable data from my console application project to windows form application( i have to write that data into textbox). I am trying to pass a variable val to my form and below code is what i tried to do but passed value(num variable in windows form) is zero instead of 1 (serial.Val in console application which is passed as argument and then i am calling the form).
Can anyone please help me with that ?
This is my windows forms code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using WindowsFormsApplication2;
namespace WindowsFormsApplication2
{
public partial class Serial_comm_1 : Form
{
//private static int temp;
private DateTime Datetime;
string indata;
static SerialPort COMport;
// private static int num;
public Serial_comm_1(int num)
{
InitializeComponent();
string Port_Name = "COM3"; // Store the selected COM port name to "Port_Name" varaiable
int Baud_Rate = 9600; // Convert the string "9600" to int32 9600
COMport = new SerialPort(Port_Name, Baud_Rate);
COMport.Parity = Parity.None;
COMport.StopBits = StopBits.One;
COMport.DataBits = 8;
COMport.Handshake = Handshake.None;
COMport.RtsEnable = true;
COMport.DtrEnable = true;
TextBox_Transmit_Data.Text = num.ToString();
//try to open the port
#region
try
{
COMport.Open();
textBox_System_Log.Text = "";
}
catch (UnauthorizedAccessException SerialException) //exception that is thrown when the operating system denies access
{
MessageBox.Show(SerialException.ToString());
textBox_System_Log.Text = Port_Name + Environment.NewLine + Baud_Rate;
textBox_System_Log.Text = textBox_System_Log.Text + Environment.NewLine + SerialException.ToString();
COMport.Close();
}
catch (System.IO.IOException SerialException) // An attempt to set the state of the underlying port failed
{
MessageBox.Show(SerialException.ToString());
textBox_System_Log.Text = Port_Name + Environment.NewLine + Baud_Rate;
textBox_System_Log.Text = textBox_System_Log.Text + Environment.NewLine + SerialException.ToString();
COMport.Close();
}
catch (InvalidOperationException SerialException) // The specified port on the current instance of the SerialPort is already open
{
MessageBox.Show(SerialException.ToString());
textBox_System_Log.Text = Port_Name + Environment.NewLine + Baud_Rate;
textBox_System_Log.Text = textBox_System_Log.Text + Environment.NewLine + SerialException.ToString();
COMport.Close();
}
catch //Any other ERROR
{
MessageBox.Show("ERROR in Opening Serial PORT -- UnKnown ERROR");
COMport.Close();
}
#endregion
}
private void Button_Transmit_Data_Click(object sender, EventArgs e)
{
//Local Variables
string Port_Name = "COM3"; // Store the selected COM port name to "Port_Name" variable
int Baud_Rate = 9600; // Convert the string "9600" to int32 9600
string Data = TextBox_Transmit_Data.Text; //Store the string in Textbox to variable "Data"
COMport.ReadTimeout = 3500; //Setting ReadTimeout =3500 ms or 3.5 seconds
Console.WriteLine(COMport.IsOpen);
COMport.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
//Program1 prog = new Program1();
//If we are able to open the port
if (COMport.IsOpen == true)
{
COMport.WriteLine(Data); // Send Data
textBox_System_Log.Text = Port_Name + Environment.NewLine + Baud_Rate;
textBox_System_Log.Text = textBox_System_Log.Text + Environment.NewLine + Data + " Written to Port" + Environment.NewLine;
}
else
{
TextBox_Received_Data.Enabled = true; // Enable the Receive Groupbox
MessageBox.Show("Unable to Write to COM port ");
COMport.Close();
}
}
private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
indata = sp.ReadLine();
this.Invoke(new EventHandler(display_data_event));
}
private void display_data_event(object sender, EventArgs e)
{
Datetime = DateTime.Now;
String time = Datetime.Hour + ":" + Datetime.Minute + ":" + Datetime.Second;
textBox_System_Log.AppendText(time + "\t\t\t" + indata + Environment.NewLine);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void label1_Click(object sender, EventArgs e)
{
}
private void textBox_Received_Data_TextChanged(object sender, EventArgs e)
{
}
private void TextBox_Transmit_Data_TextChanged(object sender, EventArgs e)
{
}
}
}
This is my trail of console application:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WindowsFormsApplication2;
using System.Windows.Forms;
namespace ConsoleApplication1
{
class Program1
{
private int val;
public int Val
{
get { return val; }
set { val = value; }
}
static void Main(string[] args)
{
Program1 serial = new Program1();
serial.Val = 1;
System.Windows.Forms.Application.Run(new Serial_comm_1(serial.Val));
//Serial_comm_1 serial_form1 = new Serial_comm_1(serial.Val);
}
}
}
From your app you want to start the other app:
// Create a new Process
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo = new System.Diagnostics.ProcessStartInfo();
process.StartInfo.FileName = #"C:\Projects\Temp912\bin\Debug\Temp912.exe";
process.StartInfo.Arguments = "Test Argument";
process.StartInfo.UseShellExecute = false;
process.Start();
Now from your Windows Form App, modify the Main method:
using System;
using System.Windows.Forms;
namespace Temp912
{
static class Program
{
[STAThread]
static void Main(string[] args)
{
string arg1 = "";
if ((args != null) && (args.Length > 0))
{
arg1 = args[0];
MessageBox.Show("Arg1: " + arg1, "Arg App Started With Parameter");
}
else
{
MessageBox.Show("Arg1: N/A", "Arg App Started Without Parameter");
}
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
}
If you need to pass the parameter value(s) to your Main Form, expose a property or properties on your form, and set the value(s) before you launch the form.
Edit Per Question:
Form Code
public string MyProperty { get; set; } // change the data type to int or whatever
Than in Program.cs, instead of:
Application.Run(new Form1());
Do this:
// create an instance of your form
Form1 form1 = new Form1();
// set the property or properties
form1.MyProperty = arg1;
Then call:
// this is should work, I didn't test this like the other code
Application.Run(form1);

Running a python script in a windows service application (no user logged on)

Running a python script (developed in an other department) by a C# Windows Service application.
I wrote a console application which executes a python script. Now I tried to transform the console app into a Windows Service. The Windows Service is working without the script propper (loggin in event log). The service stopped at the point of starting ProcessStartInfo.
public string Run()
{
_pySkript.WorkingDirectory = _workinDirectory;
_pySkript.FileName = _pythonPath;
_pySkript.Arguments = string.Format("{0} {1} {2} {3} {4} {5} {6}", a, b, c, d, e, f, g);
_pySkript.UseShellExecute = false;
_pySkript.RedirectStandardOutput = true;
_pySkript.CreateNoWindow = true;
_pySkript.RedirectStandardError = true;
_pySkript.RedirectStandardInput = true;
_pySkript.ErrorDialog = false;
_pySkript.WindowStyle = ProcessWindowStyle.Hidden;
using (Process process = Process.Start(_pySkript))
{
using (StreamReader reader = process.StandardOutput)
{
string result = reader.ReadToEnd();
OnScriptRunFinished();
return result;
}
}
}
Thank you to #BugFinder for his support. At the end it was a spelling mistake.
Example solution:
First project: Logic.csproj
using System;
using System.Diagnostics;
using System.IO;
namespace Logic
{
public class RunScript
{
string _parameterString = string.Format("{0} {1} {2} {3}","main.py", "Testuser", "TestPw", "MyEnviroment");
string _resultCon;
public string Start()
{
ProcessStartInfo _pySkript = new ProcessStartInfo();
_pySkript.WorkingDirectory = #"D:\GitRepos\ScriptRunner\PyScript\";
_pySkript.FileName = "python";
_pySkript.Arguments = _parameterString;
_pySkript.UseShellExecute = false;
_pySkript.RedirectStandardOutput = true;
_pySkript.CreateNoWindow = true;
_pySkript.RedirectStandardError = true;
_pySkript.RedirectStandardInput = true;
_pySkript.ErrorDialog = false;
_pySkript.WindowStyle = ProcessWindowStyle.Hidden;
try
{
using (Process process = Process.Start(_pySkript))
{
using (StreamReader reader = process.StandardOutput)
{
_resultCon = reader.ReadToEnd();
}
}
}
catch (Exception ex)
{
_resultCon = ex.ToString();
}
return _resultCon;
}
}
}
Second project: ScriptRunner.csproj
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Logic;
namespace ScriptRunner
{
class Program
{
static void Main(string[] args)
{
var runMyScript = new RunScript();
Console.WriteLine(runMyScript.Start());
}
}
}
Third project: ScriptRunnerService.csproj
using System.Diagnostics;
using System.ServiceProcess;
using Logic;
namespace ScriptRunnerService
{
public partial class ScriptRunService : ServiceBase
{
public ScriptRunService()
{
InitializeComponent();
eventLog1 = new EventLog();
if (!EventLog.SourceExists("MySource"))
{
EventLog.CreateEventSource(
"MySource", "MyNewLog");
}
eventLog1.Source = "MySource";
eventLog1.Log = "MyNewLog";
var runMyScript = new RunScript();
var output = runMyScript.Start();
eventLog1.WriteEntry(output.ToString(), EventLogEntryType.Information);
}
protected override void OnStart(string[] args)
{
eventLog1.WriteEntry("In OnStart.", EventLogEntryType.Information);
}
protected override void OnStop()
{
eventLog1.WriteEntry("In OnStop.", EventLogEntryType.Information);
}
}
}
Install Service:
You need InstallUtil.exe to install the service!
installutil -i ScriptRunnerService.exe
Windows-Key: r
services.msc -> Start Service
eventvwr.msc -> Check Logs
Uninstall Service:
installutil -u ScriptRunnerService.exe
Finde complete solution incl. python script on GitHub

How to read data from MSMQ in C# ? (please note - Data is not written in C# )

I am using nodejs, msmq and .net as technology stack in my project. I am collecting data from hardware using nodejs script and writing into MSMQ.
I want to read this MSMQ in .net but I am getting below error.
In addition I am not able to receive the message as well.
Error
System.Xml.XmlException: Data at the root level is invalid. Line 1, position
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
'objMessage.ConnectorType' threw an exception of type
'System.InvalidOperationException'
'objMessage.Body' threw an exception of type 'System.Xml.XmlException'
//Nodejs script
const msmq = require('updated-node-msmq');
const queue = msmq.openOrCreateQueue('.\\Private$\\EEG');
queue.send(records);
// C# code
if (MessageQueue.Exists(#".\Private$\EEG")){
objMessageQueue = new MessageQueue(#".\Private$\EEG");
}
objMessage = objMessageQueue.Receive();
objMessage.Formatter = new XmlMessageFormatter(new Type[]
{typeof(Payload) });
var message = (Payload)objMessage.Body;
I am able to solve the issue. Instead of using message.Body I have used message.BodyStream and converted that data into binary format. here's my solution.
using System;
using System.Messaging;
using System.Data.SqlClient;
using System.Data;
using Newtonsoft.Json;
using System.IO;
using System.Text;
namespace NeuroskyListener
{
class Program
{
public static bool isRunning;
private static MessageQueue messageQueue;
public static void Main(string[] args)
{
InitializeQueue();
Console.ReadLine();
}
private static void InitializeQueue()
{
string queuePath = #".\Private$\eegNew";
if (!MessageQueue.Exists(queuePath))
{
messageQueue = MessageQueue.Create(queuePath);
}
else
{
messageQueue = new MessageQueue(queuePath);
}
isRunning = true;
messageQueue.Formatter = new XmlMessageFormatter(new Type[] {typeof(string) });
messageQueue.ReceiveCompleted += OnReceiveCompleted;
messageQueue.BeginReceive();
}
private static void OnReceiveCompleted(object source, ReceiveCompletedEventArgs asyncResult)
{
try
{
MessageQueue mq = (MessageQueue)source;
if (mq != null)
{
try
{
System.Messaging.Message message = null;
try
{
message = mq.EndReceive(asyncResult.AsyncResult);
BinaryReader reader = new BinaryReader(message.BodyStream);
int count = (int)message.BodyStream.Length;
byte[] bytes = reader.ReadBytes(count);
string bodyString = Encoding.UTF8.GetString(bytes);
eegPayload lst = JsonConvert.DeserializeObject<eegPayload>(bodyString);
}
catch (Exception ex)
{
// LogMessage(ex.Message);
}
if (message != null)
{
//Payload payload = message.Body as Payload;
Console.WriteLine(message.Body);
//if (payload != null)
//{
// receivedCounter++;
// if ((receivedCounter % 10000) == 0)
// {
// string messageText = string.Format("Received {0} messages", receivedCounter);
// LogMessage(messageText);
// }
//}
}
}
finally
{
if (isRunning)
{
mq.BeginReceive();
}
}
}
return;
}
catch (Exception exc)
{
//LogMessage(exc.Message);
}
}
}
}

Detecting Printer configuration changes in c#

Is there a way to detect a configuration changes in printers using C#?
I have thread in c# which usually sleeps and I want it to be notified when there is any change in configuration (like someone adds/removes/updates the printer or someone changes the default printer). Once it is notified, it will display simple message.
Is this possible using C#.NET or Using WMI? I have already gone through the solution available but none of them seems to be suitable for the requirement I have.
You can monitor the printer configuration changes using the __InstanceModificationEvent event and the Win32_Printer WMI class
Try this sample.
using System;
using System.Collections.Generic;
using System.Management;
using System.Text;
namespace GetWMI_Info
{
public class EventWatcherAsync
{
private void WmiEventHandler(object sender, EventArrivedEventArgs e)
{
Console.WriteLine("TargetInstance.Name : " + ((ManagementBaseObject)e.NewEvent.Properties["TargetInstance"].Value)["Name"]);
}
public EventWatcherAsync()
{
try
{
string ComputerName = "localhost";
string WmiQuery;
ManagementEventWatcher Watcher;
ManagementScope Scope;
if (!ComputerName.Equals("localhost", StringComparison.OrdinalIgnoreCase))
{
ConnectionOptions Conn = new ConnectionOptions();
Conn.Username = "";
Conn.Password = "";
Conn.Authority = "ntlmdomain:DOMAIN";
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), Conn);
}
else
Scope = new ManagementScope(String.Format("\\\\{0}\\root\\CIMV2", ComputerName), null);
Scope.Connect();
WmiQuery = "Select * From __InstanceModificationEvent Within 1 " +
"Where TargetInstance ISA 'Win32_Printer' ";
Watcher = new ManagementEventWatcher(Scope, new EventQuery(WmiQuery));
Watcher.EventArrived += new EventArrivedEventHandler(this.WmiEventHandler);
Watcher.Start();
Console.Read();
Watcher.Stop();
}
catch (Exception e)
{
Console.WriteLine("Exception {0} Trace {1}", e.Message, e.StackTrace);
}
}
public static void Main(string[] args)
{
Console.WriteLine("Listening {0}", "__InstanceModificationEvent");
Console.WriteLine("Press Enter to exit");
EventWatcherAsync eventWatcher = new EventWatcherAsync();
Console.Read();
}
}
}

Lan Ip Scanner using Windows Phone 7

I'm trying to write a remote control application to Windows Phone 7.
All goes OK, but i can not make IP scan over net.
Connected param in Socket class works badly. To use it i need to connect to any IP, then send anymessage - it's Ok. But timeout is too long - about 10 secs(for turned off Pcs).
I need to scan about 256 IPs, and 2560 seconds - is too long.
I tried to write timeout by my self. It works, but after some time application stops.
I can not understand why. No exceptions. Phone just stops attempts to connect and visual studio crashes sometimes.
If there is overflow - where can it be?
Here is some code:
(TryHost is runnung in FOR cycle. Only one start at a time, Searcher.AddHost() runs next iteration of TryHost)
AsynchronousClient:
public void TryHost(string host)
{
SocketAsyncEventArgs socketEventArg = new SocketAsyncEventArgs();
DnsEndPoint hostEntry = new DnsEndPoint(host, _port);
// Create a socket and connect to the server
Socket sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
socketEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(SocketEventArg_Completed1);
socketEventArg.RemoteEndPoint = hostEntry;
sock.NoDelay = true;
socketEventArg.UserToken = sock;
try
{
sock.ConnectAsync(socketEventArg);
}
catch (SocketException ex)
{}
}
void SocketEventArg_Completed1(object sender, SocketAsyncEventArgs e)
{
switch (e.LastOperation)
{
case SocketAsyncOperation.Connect:
ProcessConnect1(e);
break;
case SocketAsyncOperation.SendTo:
connected = false;
ProcessSend1(e);
break;
case SocketAsyncOperation.Receive:
sended = false;
ProcessReceive1(e);
break;
default:
throw new Exception("Problems");
}
}
private void ProcessReceive1(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
// Received data from server
string dataFromServer = Encoding.UTF8.GetString(e.Buffer, 0, e.BytesTransferred);
if (dataFromServer.IndexOf("<EOF>") > -1)
{
Searcher.AddHost(dataFromServer);
}
}
else
{
Searcher.AddHost(null);
}
}
private void ProcessSend1(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
Socket sock = e.UserToken as Socket;
sended = true;
sock.ReceiveAsync(e);
Thread.Sleep(500);
if (sended)
{
sock.Dispose();
Searcher.AddHost(null);
}
}
else
{
Searcher.AddHost(null);
}
}
private void ProcessConnect1(SocketAsyncEventArgs e)
{
if (e.SocketError == SocketError.Success)
{
byte[] buffer = Encoding.UTF8.GetBytes("Knock" + "!" + sessionId + "<EOF>");
e.SetBuffer(buffer, 0, buffer.Length);
sock = e.UserToken as Socket;
connected = true;
sock.SendToAsync(e);
e.ConnectSocket.NoDelay = false;
Thread.Sleep(500);
if (connected)
{
sock.Dispose();
}
}
else
{
sock.Dispose();
Searcher.AddHost(null);
}
}
i'm using static class Searcher. UI button starts search from StartSearch() metod wich prepares class to search, and run methods in AsyncClient variable. When AssyncClient request is timed out or answered by host, AssyncClient runs AddHost() method
and Searcher prepares next IP, then start TryHost() again
static Searcher:
using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Threading;
namespace PivotApp1 {
class PartedIp
{
public string FirstPart;
public string LastPart;
public PartedIp(string first, string last)
{
FirstPart = first;
LastPart = last;
}
}
public class SearchArgs : EventArgs
{
private List<string> message;
public SearchArgs(List<string> msg)
{
message = msg;
}
public List<string> Message
{
get { return message; }
}
}
public static class Searcher
{
static bool searching = false;
static string phoneIp = "";
static string ipTemplate = "";
static int currentLookingIp;
static int stopIp;
static List<string> answers = new List<string>();
static AsynchronousClient newC;
static int chBound = 255;
static int lwBound = 255;
public static event EventHandler SearchComplete = delegate { };
public static void SayItsOver(List<string> message)
{
SearchComplete(null, new SearchArgs(message));
}
static AsynchronousClient searcher;
static string CheckIp()
{
string phoneIp = null;
try
{
MyIPAddress finder = new MyIPAddress();
finder.Find((address) =>
{
phoneIp = address == null ? "Unknown" : address.ToString();
});
}
catch (Exception e)
{
throw new Exception();
}
if (phoneIp == "Unknown")
{
return null;
}
else
{
return phoneIp;
}
}
static PartedIp PrepareForSearch(string phoneIp)
{
IPAddress ipForTest = new IPAddress(10);
if (IPAddress.TryParse(phoneIp, out ipForTest))
{
string[] splittedIp = phoneIp.Split('.');
PartedIp phonePartedIp = new PartedIp(splittedIp[0] + '.' + splittedIp[1] + '.' + splittedIp[2] + '.', splittedIp[3]);
return phonePartedIp;
}
else return null;
}
public static void StartSearch(AsynchronousClient newC)
{
phoneIp = CheckIp();
if (phoneIp != null)
{
searching = true;
newC = newC1;
PartedIp partedIp = PrepareForSearch(phoneIp);
ipTemplate = partedIp.FirstPart;
stopIp = Int32.Parse(partedIp.LastPart);
currentLookingIp = stopIp - 1;
newC.TryHost(ipTemplate + currentLookingIp);
}
else
Deployment.Current.Dispatcher.BeginInvoke(() => {
MessageBox.Show("Error in Ip detection");
});
}
static void NextHost()
{
if (searching)
{
currentLookingIp--;
if (currentLookingIp == 0)
currentLookingIp = 255;
}
}
static public void AddHost(string answer)
{
if (searching)
{
if (answer != null)
{
answers.Add(answer);
}
NextHost();
if (currentLookingIp == stopIp)
{
SayItsOver(answers);
searching = false;
}
else
{
newC.TryHost(ipTemplate + currentLookingIp);
}
}
}
} }
I debugged this a lot of time. My start ip = 192.168.0.103. My Server Ip = 192.168.0.100.
Search working perfectly, until 192.168.0.19(no PCs here). Even if i start my search from 192.168.0.20 it crashed.
Another dead zone is 192.168.0.1 and next 192.168.0.255.
Also - manual starting of TryHost() works fine. Problems begin when I'm trying to automate search.
What's wrong?
I spent a few days on it and just do not know what to do.

Categories

Resources