EWS subscribe to streaming notifications in the inbox - c#

I trying to write a Console Application which will establish a connection to a mailbox using EWS and then print a line every time a new email is received.
The end result once I have this working is to turn this into a service, and have a task created every time an email arrives in a certain mailbox, but for now I cant get the Console to write a line upon receipt.
Console Application Project
Program.cs
class Program
{
static void Main(string[] args)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
WebCredentials wbcred = new WebCredentials("myusername", "mypassw0rd");
service.Credentials = wbcred;
service.AutodiscoverUrl("myemailaddress#mydomain.com", RedirectionUrlValidationCallback);
EWSConnection.SetStreamingNotifications(service);
}
internal static bool RedirectionUrlValidationCallback(string redirectionUrl)
{
//The default for the validation callback is to reject the URL
bool result = false;
Uri redirectionUri = new Uri(redirectionUrl);
if (redirectionUri.Scheme == "https")
{
result = true;
}
return result;
}
}
Class Library Project
EWSConnection.cs
public static void SetStreamingNotifications(ExchangeService service)
{
StreamingSubscription subscription;
// Subscribe to streaming notifications in the Inbox.
subscription = service.SubscribeToStreamingNotifications(
new FolderId[] { WellKnownFolderName.Inbox },
EventType.NewMail);
// Create a streaming connection to the service object, over which events are returned to the client.
// Keep the streaming connection open for 30 minutes.
StreamingSubscriptionConnection connection = new StreamingSubscriptionConnection(service, 30);
connection.AddSubscription(subscription);
connection.OnNotificationEvent += OnEvent;
connection.OnDisconnect += OnDisconnect;
connection.Open();
bool status = connection.IsOpen;
Console.WriteLine($"Connection Open:{status}");
}
I can add the OnEvent and OnDisconnect methods if required. What's happening is the console prints
Connection Open:True Press any key to continue . . .
Then, when I send an email to that mailbox nothing happens, no break points are triggered and nothing is output to the console, which is what those two methods do.
Why is my OnEvent method not firing?
Edit - OnEvent & OnDisconnect methods
public static void OnEvent(object sender, NotificationEventArgs args)
{
StreamingSubscription subscription = args.Subscription;
// Loop through all item-related events.
foreach (NotificationEvent notification in args.Events)
{
switch (notification.EventType)
{
case EventType.NewMail:
Console.WriteLine("\n————-Mail created:————-");
break;
case EventType.Created:
Console.WriteLine("\n————-Item or folder created:————-");
break;
case EventType.Deleted:
Console.WriteLine("\n————-Item or folder deleted:————-");
break;
}
// Display the notification identifier.
if (notification is ItemEvent)
{
// The NotificationEvent for an e-mail message is an ItemEvent.
ItemEvent itemEvent = (ItemEvent)notification;
Console.WriteLine("\nItemId: " + itemEvent.ItemId.UniqueId);
}
else
{
// The NotificationEvent for a folder is an FolderEvent.
FolderEvent folderEvent = (FolderEvent)notification;
Console.WriteLine("\nFolderId: " + folderEvent.FolderId.UniqueId);
}
}
}
and
public static void OnDisconnect(object sender, SubscriptionErrorEventArgs args)
{
// Cast the sender as a StreamingSubscriptionConnection object.
StreamingSubscriptionConnection connection = (StreamingSubscriptionConnection)sender;
// Ask the user if they want to reconnect or close the subscription.
ConsoleKeyInfo cki;
Console.WriteLine("The connection to the subscription is disconnected.");
Console.WriteLine("Do you want to reconnect to the subscription? Y/N");
while (true)
{
cki = Console.ReadKey(true);
{
if (cki.Key == ConsoleKey.Y)
{
connection.Open();
Console.WriteLine("Connection open.");
break;
}
else if (cki.Key == ConsoleKey.N)
{
// The ReadKey in the Main() consumes the E.
Console.WriteLine("\n\nPress E to exit");
break;
}
}
}
}

Annoyingly, I was missing the Console.ReadKey() method. It worked as expected once I added this...
static void Main(string[] args)
{
ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2013);
WebCredentials wbcred = new WebCredentials("myusername", "mypassw0rd","myDomain");
service.Credentials = wbcred;
service.AutodiscoverUrl("myemailaddress#mydomain.com", RedirectionUrlValidationCallback);
EWSConnection.SetStreamingNotifications(service);
Console.ReadKey(); //<-- this was missing
}

Bind the methods to the current subscription as this
connection.OnNotificationEvent +=
new StreamingSubscriptionConnection.NotificationEventDelegate(OnEvent);
connection.OnDisconnect +=
new StreamingSubscriptionConnection.SubscriptionErrorDelegate(OnDisconnect);
Here's a example

Related

NetMQ Polling a rep socket with a timeout in a loop

I'm trying to port my code from an obsolete library called CastleMQ to NetMQ but I'm running into some problems.
I prefer to using polling with a timeout, for reliability - I just found that it worked best for me from trial and error compared to just sitting blocking the port indefinitely.
here is my CastleMQ code
public int ZeroPort;
private void ThreadProc()
{
var ctx = new Context();
try {
using (var repSocket = ctx.CreateSocket(SocketType.Rep))
{
string bindAddress = "tcp://*:"+ZeroPort;
repSocket.Bind(bindAddress);
print2("*** BINDING on {0} ***", bindAddress);
bool quit = false;
while (!quit) {
try {
var polling = new Polling(PollingEvents.RecvReady, repSocket);
polling.RecvReady += (socket) =>
{ // using socket.Recv() here is guaranted to return stuff
var msg = socket.Recv();
var msgStr = Encoding.UTF8.GetString(msg);
print2("[REP:{0}] {1}", bindAddress, msgStr);
switch (msgStr) {
case "positions": {
StringBuilder csv = new StringBuilder();
print2("csv: {0}", csv.ToString());
socket.Send(csv.ToString());
break;
}
default: {
socket.Send("Unrecognized Command: " + msgStr);
break;
}
}
};
polling.Poll(POLL_TIMEOUT_MS); // this returns once some socket event happens
} catch (Exception e) {
if (e is ThreadAbortException) {
quit = true;
print2("\n*** EXITED ***");
} else print2(e.ToString());
}
}
}
} catch (Exception e) {
print2(e.ToString());
} finally {
ctx.Dispose();
}
}
here is what I tried to do and then got lost with NetMQ
private void ThreadProc()
{
try {
string bindAddress = "#tcp://*:" + ZeroPort;
print2("*** BINDING on {0} ***", bindAddress);
using (var repSocket = new ResponseSocket(bindAddress))
using (var poller = new NetMQPoller { repSocket })
{
// bool quit = false;
// while (!quit)
// these event will be raised by the Poller
repSocket.ReceiveReady += (s, a) =>
{
// receive won't block as a message is ready
string msg = a.Socket.ReceiveString(); // defeinition for ReceiveString() can't be found
// send a response
a.Socket.Send("Response"); // it doesn't like "Response", do I need to wrap it in some object?
I'm especially confused as how to add a timeout so I can poll with a timeout in a loop the way my CastleMQ code does.
Any pointers would be much appreciated, thanks

Why won't it run everytime I got an incoming message in C#?

I tested this code with placing a breakpoint in Monodevelop, running on a Raspbian. This app needs to communicate with a Windows, with a C# console application.
Although the timer1_Tick method prints the incoming message everytime (and it clearly prints the new message, because there I clear the message variable everytime after an incoming message), it seems to be that the OnNewData doesn't run everytime, when there's an incoming message.
I ask new incoming message with sending the "mes" out in the timer1_Tick.
I don't process the other kind of incoming messages in that method, but for the response for "mes", this place would be the best for processing. The reason is the "mes" creates answer types ("", " type answers), what I can get anytime.
I don't know what is the problem. Any idea? How could this happen, if the textbox is being refreshed nicely after each new incoming message?
public partial class Form0 : Form
{
public static string ReadCharactersIntoString(){
char c='c';
string outputString=String.Empty;
do{
c=(char)streamReader.Read();
outputString=outputString+c;
}while(c!='>');
return outputString;
}
async void OnNewData(object sender, EventArgs e){
message = Form0.ReadCharactersIntoString ();
//work with message variable works unreliable...
//sometimes this method runs, when there's an incoming message, sometimes it's not...
//although tick method prints the message everytime...
//why? how to solve this?
reseter.Set ();
}
public void AcceptMessages(){
while (true) {
try{
if (streamReader!=null && streamReader.Peek () > 0) {
newIncomingDataEvent.Invoke(this,EventArgs.Empty);
reseter.WaitOne ();
}
}catch{
}
}
}
public static async Task Waiting(){
while (message == null || message[message.Length-1]!='>') {
}
}
public static async Task<string> CollectingAnswer(){
await Waiting();
return message;
//when the answer is completely collected, it gives me back
}
public void ConnectionEstablisher()
{
while (true)
{
if (!activeConnection)
{
try
{
socketForServer = new TcpClient(ip, port);
networkStream = socketForServer.GetStream();
streamReader = new System.IO.StreamReader(networkStream);
streamWriter = new System.IO.StreamWriter(networkStream);
streamReader.BaseStream.ReadTimeout = 5000;
streamWriter.BaseStream.ReadTimeout = 5000;
activeConnection = true;
newIncomingDataEvent+=OnNewData;
reseter = new ManualResetEvent (true);
}
catch(Exception e)
{
activeConnection = false;
}
}
}
}
private async void timer1_Tick(object sender, EventArgs e)
{
if (this.Visible && activeConnection)
{
try
{
streamWriter.Write("mes");
streamWriter.Flush();
textBoxSending.AppendText("mes" + Environment.NewLine);
collectAnswer=CollectingAnswer();
outputString=await collectAnswer;
message=null;
textBoxAccepting.AppendText(outputString + Environment.NewLine);
//this always prints the incoming response message...

connect to other computer that is not local

I try to connect from my pc to other pc what I have at home and both are connected to the internet. So I check the other pc with the program MyIpAdress and it is like: 38.xx.xx.xx.
And I have this program:The server:
public delegate void StatusChangedHandler(object sender, StatusChangedEventArgs e);
public class StatusChangedEventArgs : EventArgs
{
// This will store our only parameter / event argument, which is the event message
private string EventMsg;
// We need to define this property in order to retrieve the message in the event handler, back in Form1.cs
public string EventMessage
{
get
{
return EventMsg;
}
}
// The constructor will set the message
public StatusChangedEventArgs(string strEventMsg)
{
EventMsg = strEventMsg;
}
}
class Monitor
{
// Will store the IP address passed to it
IPAddress ipAddress;
// The constructor sets the IP address to the one retrieved by the instantiating object
public Monitor(IPAddress address)
{
ipAddress = address;
}
// Declare the event that we'll fire later
public event StatusChangedHandler StatusChangedEvent;
// The thread that will hold the connection listener
private Thread thrListener;
// The TCP object that listens for connections
private TcpListener tlsServer;
// The thread that will send information to the client
private Thread thrSender;
// Will tell the while loop to keep monitoring for connections
bool ServRunning = false;
public void StartMonitoring()
{
// Get the IP of the first network device, however this can prove unreliable on certain configurations
IPAddress ipaLocal = ipAddress;
if (tlsServer == null)
{
// Create the TCP listener object using the IP of the server and the specified port
tlsServer = new TcpListener(ipaLocal, 1986 );
}
// Start the TCP listener and listen for connections
tlsServer.Start();
// The while loop will check for true in this before checking for connections
ServRunning = true;
// Start the new tread that hosts the listener
thrListener = new Thread(KeepListening);
thrListener.Start();
}
private void KeepListening()
{
TcpClient tclServer;
// While the server is running
while (ServRunning == true)
{
// Accept a pending connection
tclServer = tlsServer.AcceptTcpClient();
// Start a new thread where our new client who just connected will be managed
thrSender = new Thread(new ParameterizedThreadStart(AcceptClient));
// The thread calls the AcceptClient() method
thrSender.Start(tclServer);
}
}
// Occures when a new client is accepted
private void AcceptClient(object newClient)
{
// Set the argument/parameter to a message explaining what just happened
StatusChangedEventArgs evArg = new StatusChangedEventArgs("A client was successfully accepted.");
// Fire the event because a new client was accepted
StatusChangedEvent(this, evArg);
}
}
But if I fill in in the textbox the ipadress: 38.xxx.xxx.xx,
I will get this error:
An unhandled exception of type 'System.Net.Sockets.SocketException'
occurred in System.dll
Additional information: The requested address is not valid in its context
So it can only see Local ipAdresses?
But how to change it, that it also finds not local Ipadresses?
And this is the client application:
public partial class Form1 : Form
{
private string UserName = "Unknown";
private StreamWriter swSender;
private StreamReader srReceiver;
private TcpClient tcpServer;
// Needed to update the form with messages from another thread
private delegate void UpdateLogCallback(string strMessage);
// Needed to set the form to a "disconnected" state from another thread
private delegate void CloseConnectionCallback(string strReason);
private Thread thrMessaging;
private IPAddress ipAddr;
private bool Connected;
public Form1()
{
Application.ApplicationExit += new EventHandler(OnApplicationExit);
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// If we are not currently connected but awaiting to connect
if (Connected == false)
{
// Initialize the connection
InitializeConnection();
}
else // We are connected, thus disconnect
{
CloseConnection("Disconnected at user's request.");
}
}
private void ReceiveMessages()
{
// Receive the response from the server
srReceiver = new StreamReader(tcpServer.GetStream());
// If the first character of the response is 1, connection was successful
string ConResponse = srReceiver.ReadLine();
// If the first character is a 1, connection was successful
if (ConResponse[0] == '1')
{
// Update the form to tell it we are now connected
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { "Connected Successfully!" });
}
else // If the first character is not a 1 (probably a 0), the connection was unsuccessful
{
string Reason = "Not Connected: ";
// Extract the reason out of the response message. The reason starts at the 3rd character
Reason += ConResponse.Substring(2, ConResponse.Length - 2);
// Update the form with the reason why we couldn't connect
this.Invoke(new CloseConnectionCallback(this.CloseConnection), new object[] { Reason });
// Exit the method
return;
}
// While we are successfully connected, read incoming lines from the server
while (Connected)
{
// Show the messages in the log TextBox
this.Invoke(new UpdateLogCallback(this.UpdateLog), new object[] { srReceiver.ReadLine() });
}
}
private void InitializeConnection()
{
// Parse the IP address from the TextBox into an IPAddress object
ipAddr = IPAddress.Parse(txtServerIP.Text);
// Start a new TCP connections to the chat server
tcpServer = new TcpClient();
tcpServer.Connect(IPAddress.Any, 1986);
// Helps us track whether we're connected or not
Connected = true;
// Prepare the form
UserName = txtUserName.Text;
// Disable and enable the appropriate fields
txtServerIP.Enabled = false;
txtUserName.Enabled = false;
txtMessage.Enabled = true;
btnSend.Enabled = true;
btnConnect.Text = "Disconnect";
// Send the desired username to the server
swSender = new StreamWriter(tcpServer.GetStream());
swSender.WriteLine(txtUserName.Text);
swSender.Flush();
// Start the thread for receiving messages and further communication
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
private void UpdateLog(string strMessage)
{
// Append text also scrolls the TextBox to the bottom each time
txtLog.AppendText(strMessage + "\r\n");
}
private void btnSend_Click(object sender, EventArgs e)
{
SendMessage();
}
private void SendMessage()
{
if (txtMessage.Lines.Length >= 1)
{
swSender.WriteLine(txtMessage.Text);
swSender.Flush();
txtMessage.Lines = null;
}
txtMessage.Text = "";
}
// Closes a current connection
private void CloseConnection(string Reason)
{
// Show the reason why the connection is ending
txtLog.AppendText(Reason + "\r\n");
// Enable and disable the appropriate controls on the form
txtServerIP.Enabled = true;
txtUserName.Enabled = true;
txtMessage.Enabled = false;
btnSend.Enabled = false;
btnConnect.Text = "Connect";
// Close the objects
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
public void OnApplicationExit(object sender, EventArgs e)
{
if (Connected == true)
{
// Closes the connections, streams, etc.
Connected = false;
swSender.Close();
srReceiver.Close();
tcpServer.Close();
}
}
}
So I changed this line:
tcpServer.Connect(IPAddress.Any, 1986);
but If I run the server application I will get this error:
I get the same error as by the client:
An unhandled exception of type 'System.Net.Sockets.SocketException' occurred in System.dll
Additional information: The requested address is not valid in its context
Thank you
I show you two Images:This is the Server app. That works
This is the Client app, that doesnt work:
And if I change the code in the client app, like this:
tcpServer.Connect(ipAddr, 1986); Then I will get this error:
Additional information: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond
But I can pin the other pc
In the client program I have this:
private void InitializeConnection()
{
// Parse the IP address from the TextBox into an IPAddress object
ipAddr = IPAddress.Parse(txtServerIP.Text);
// Start a new TCP connections to the chat server
tcpServer = new TcpClient();
tcpServer.Connect(IPAddress.Any, 1986);
// Helps us track whether we're connected or not
Connected = true;
// Prepare the form
UserName = txtUserName.Text;
// Disable and enable the appropriate fields
txtServerIP.Enabled = false;
txtUserName.Enabled = false;
txtMessage.Enabled = true;
btnSend.Enabled = true;
btnConnect.Text = "Disconnect";
// Send the desired username to the server
swSender = new StreamWriter(tcpServer.GetStream());
swSender.WriteLine(txtUserName.Text);
swSender.Flush();
// Start the thread for receiving messages and further communication
thrMessaging = new Thread(new ThreadStart(ReceiveMessages));
thrMessaging.Start();
}
what I have to change then?
Maybe you have to allow TCP connections on your port in the firewall for the applications on both PCs. Make sure that connections from and to the network are allowed.

How do I impersonate a server with Fiddler core?

I'm trying to debug an app without setting fiddler as its proxy.
To do this, I've setup fiddler.core based app that resides on an other computer in the network and added an entry to hosts file.
Here's the app's code:
private static Proxy googleEndpoint;
static void Main(string[] args)
{
List<Fiddler.Session> oAllSessions =new List<Session>();
Fiddler.FiddlerApplication.BeforeRequest += (i) => Console.WriteLine("Before request: "+i.fullUrl);
FiddlerApplication.AfterSessionComplete += (i) =>
{
Console.WriteLine("After request: "+i.fullUrl);
lock (oAllSessions)
{
oAllSessions.Add(i);
}
};
//https://www.google.com.ua/
googleEndpoint = FiddlerApplication.CreateProxyEndpoint(443, true, "www.google.com.ua");
if (null != googleEndpoint)
{
Console.WriteLine("google.com.ua endpoint mounted");
}
else
{
Console.WriteLine("failed to mount google.com.ua endpoint");
}
Console.ReadKey();
SaveSessionsToDesktop(oAllSessions);
}
private static void SaveSessionsToDesktop(List<Fiddler.Session> oAllSessions)
{
bool bSuccess = false;
string sFilename = DateTime.Now.ToString("hh-mm-ss") + ".saz";
try
{
try
{
Monitor.Enter(oAllSessions);
TranscoderTuple oExporter = FiddlerApplication.oTranscoders.GetExporter("SAZ");
if (null != oExporter)
{
Dictionary<string, object> dictOptions = new Dictionary<string, object>();
dictOptions.Add("Filename", sFilename);
// dictOptions.Add("Password", "pencil");
bSuccess = FiddlerApplication.DoExport("SAZ", oAllSessions.ToArray(), dictOptions, null);
}
else
{
Console.WriteLine("Save failed because the SAZ Format Exporter was not available.");
}
}
finally
{
Monitor.Exit(oAllSessions);
}
WriteCommandResponse(bSuccess ? ("Wrote: " + sFilename) : ("Failed to save: " + sFilename));
}
catch (Exception eX)
{
Console.WriteLine("Save failed: " + eX.Message);
}
}
public static void WriteCommandResponse(string s)
{
ConsoleColor oldColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(s);
Console.ForegroundColor = oldColor;
}
but when I'm trying to access https://www.google.com.ua from the target machine, the requests now time out.
Fiddler app shows that it has recieved the request in the BeforeRequest event, but it never sends a reply (AfterSessionComplete never gets called).
Why does this happen and how can I fix it?
How do I do the same for port 80?
I trust you're keeping in mind the fact that, unless you reconfigure the client to trust the FiddlerServer's root certificate, it will not issue a HTTPS request to FiddlerCore. It will instead immediately close the connection upon getting the interception certificate.
What do you see if you attach a BeforeResponse event handler? Does it fire?

WinForm Timers Access Textbox

So I am trying to create a basic WinForm Application that uses SNMP, from snmpsharpnet.
I have two buttons 'Eye' and 'Jitter' that when one is pressed a timer starts which executes SNMP code inside the timer handler every minute.
I am trying to write the SNMP output to a textbox from the timer handler but everything I try either leads to thread exceptions or a continuous running process when I exit the program.
I have tried so many different things to fix those two errors that I may be screwing everything up but here is the code I have:
using System;
using System.Net;
using SnmpSharpNet;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public static bool stop = false;
static bool min = false, sec = false, eye = false, jitter = false;
static string ipAdd = "";
static System.Windows.Forms.Timer timer = new System.Windows.Forms.Timer();
static int alarmCounter = 1;
static bool exitFlag = false;
static TextBox textbox;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
textbox = outputBox;
}
private void IPtext_TextChanged(object sender, EventArgs e)
{
ipAdd = IPtext.Text;
}
private void stopButton_Click(object sender, EventArgs e)
{
stop = true;
timer.Stop();
}
// This is the method to run when the timer is raised.
private static void TimerEventProcessor(Object myObject,
EventArgs myEventArgs)
{
timer.Stop();
// If stop button has not been pressed then continue timer.
if (stop == false)
{
textbox.Clear();
// Restarts the timer and increments the counter.
alarmCounter += 1;
timer.Enabled = true;
/*
textbox.Invoke(
new MethodInvoker(
delegate { textbox.AppendText("fsjdaò"); }));
*/
System.IO.StreamWriter file;
if (eye == true)
{
file = new System.IO.StreamWriter("c:/Users/bshellnut/Desktop/Eye.txt", true);
}
else
{
file = new System.IO.StreamWriter("c:/Users/bshellnut/Desktop/Jitter.txt", true);
}
// SNMP community name
OctetString community = new OctetString("public");
// Define agent parameters class
AgentParameters param = new AgentParameters(community);
// Set SNMP version to 2 (GET-BULK only works with SNMP ver 2 and 3)
param.Version = SnmpVersion.Ver2;
// Construct the agent address object
// IpAddress class is easy to use here because
// it will try to resolve constructor parameter if it doesn't
// parse to an IP address
IpAddress agent = new IpAddress(ipAdd);
// Construct target
UdpTarget target = new UdpTarget((IPAddress)agent, 161, 2000, 1);
// Define Oid that is the root of the MIB
// tree you wish to retrieve
Oid rootOid;
if (eye == true)
{
rootOid = new Oid("1.3.6.1.4.1.128.5.2.10.14"); // ifDescr
}
else
{
rootOid = new Oid("1.3.6.1.4.1.128.5.2.10.15");
}
// This Oid represents last Oid returned by
// the SNMP agent
Oid lastOid = (Oid)rootOid.Clone();
// Pdu class used for all requests
Pdu pdu = new Pdu(PduType.GetBulk);
// In this example, set NonRepeaters value to 0
pdu.NonRepeaters = 0;
// MaxRepetitions tells the agent how many Oid/Value pairs to return
// in the response.
pdu.MaxRepetitions = 5;
// Loop through results
while (lastOid != null)
{
// When Pdu class is first constructed, RequestId is set to 0
// and during encoding id will be set to the random value
// for subsequent requests, id will be set to a value that
// needs to be incremented to have unique request ids for each
// packet
if (pdu.RequestId != 0)
{
pdu.RequestId += 1;
}
// Clear Oids from the Pdu class.
pdu.VbList.Clear();
// Initialize request PDU with the last retrieved Oid
pdu.VbList.Add(lastOid);
// Make SNMP request
SnmpV2Packet result;
try
{
result = (SnmpV2Packet)target.Request(pdu, param);
//textbox.Text = "";
}
catch (SnmpSharpNet.SnmpException)
{
textbox.Invoke(
new MethodInvoker(
delegate { textbox.AppendText("Could not connect to the IP Provided."); }));
timer.Stop();
//outputBox.Text += "Could not connect to the IP Provided.";
break;
}
// You should catch exceptions in the Request if using in real application.
// If result is null then agent didn't reply or we couldn't parse the reply.
if (result != null)
{
// ErrorStatus other then 0 is an error returned by
// the Agent - see SnmpConstants for error definitions
if (result.Pdu.ErrorStatus != 0)
{
// agent reported an error with the request
/*Console.WriteLine("Error in SNMP reply. Error {0} index {1}",
result.Pdu.ErrorStatus,
result.Pdu.ErrorIndex);*/
textbox.Invoke(
new MethodInvoker(
delegate { textbox.AppendText("Error in SNMP reply. " + "Error " + result.Pdu.ErrorStatus + " index " + result.Pdu.ErrorIndex); }));
//outputBox.Text = "Error in SNMP reply. " + "Error " + result.Pdu.ErrorStatus + " index " + result.Pdu.ErrorIndex;
lastOid = null;
break;
}
else
{
// Walk through returned variable bindings
foreach (Vb v in result.Pdu.VbList)
{
// Check that retrieved Oid is "child" of the root OID
if (rootOid.IsRootOf(v.Oid))
{
/*Console.WriteLine("{0} ({1}): {2}",
v.Oid.ToString(),
SnmpConstants.GetTypeName(v.Value.Type),
v.Value.ToString());*/
textbox.Invoke(
new MethodInvoker(
delegate { textbox.AppendText(v.Oid.ToString() + " " + SnmpConstants.GetTypeName(v.Value.Type) +
" " + v.Value.ToString() + Environment.NewLine); }));
//outputBox.Text += v.Oid.ToString() + " " + SnmpConstants.GetTypeName(v.Value.Type) +
//" " + v.Value.ToString() + Environment.NewLine;
file.WriteLine(v.Oid.ToString() + " " + SnmpConstants.GetTypeName(v.Value.Type) +
" " + v.Value.ToString(), true);
if (v.Value.Type == SnmpConstants.SMI_ENDOFMIBVIEW)
lastOid = null;
else
lastOid = v.Oid;
}
else
{
// we have reached the end of the requested
// MIB tree. Set lastOid to null and exit loop
lastOid = null;
}
}
}
}
else
{
//Console.WriteLine("No response received from SNMP agent.");
textbox.Invoke(
new MethodInvoker(
delegate { textbox.AppendText("No response received from SNMP agent."); }));
//outputBox.Text = "No response received from SNMP agent.";
}
}
target.Close();
file.Close();
}
else
{
// Stops the timer.
exitFlag = true;
}
}
private void eyeButton_Click(object sender, EventArgs e)
{
outputBox.Text = "Connecting...";
eye = true;
jitter = false;
stop = false;
timer.Tick += new EventHandler(TimerEventProcessor);
// Sets the timer interval to 5 seconds.
timer.Interval = 5000;
timer.Start();
// Runs the timer, and raises the event.
while (exitFlag == false)
{
// Processes all the events in the queue.
Application.DoEvents();
}
}
private void jitterButton_Click(object sender, EventArgs e)
{
outputBox.Text = "Connecting...";
eye = false;
jitter = true;
stop = false;
timer.Tick += new EventHandler(TimerEventProcessor);
// Sets the timer interval to 5 seconds.
timer.Interval = 5000;
timer.Start();
// Runs the timer, and raises the event.
while (exitFlag == false)
{
// Processes all the events in the queue.
Application.DoEvents();
}
}
private void Seconds_CheckedChanged(object sender, EventArgs e)
{
min = false;
sec = true;
}
private void Minutes_CheckedChanged(object sender, EventArgs e)
{
min = true;
sec = false;
}
}
}
I believe you are running into a deadlock on the UI thread.
TimerEventProcessor() is called by your instance of System.Windows.Forms.Timer, which runs on the UI thread. When the timer goes off, I believe it puts a message into the UI thread's message queue to call your TimerEventProcessor() method. That method in turn calls textbox.Invoke(), which puts another message into the queue and then waits for it to be processed.
Your UI thread is now stuck, as it is in the middle of processing a message, but must wait until another message is processed before it can continue. The calls to Application.DoEvents() do you no good, as they are not being called once your program enters TimerEventProcessor(). (They're also unnecessary, since your button click handlers wouldn't be blocking the UI thread anyway.)
Since the timer runs on the UI thread, you can get rid of the textbox.Invoke() calls and just access textbox directly.
Summary:
Replace your calls to textbox.Invoke() with direct access to textbox
Remove your calls to Application.DoEvents()
Note: if you got the Application.DoEvents() logic from the MSDN example for using a timer, they put it there so that the application doesn't quit once the Main function completes.
Update: You can see if this is truly the issue by replacing your calls to textbox.Invoke with the following code. If this code works, then you definitely have a UI message queue deadlocking issue. Also, if this does resolve the issue, I would not recommend keeping this as the solution, but rather, addressing the deadlocking as suggested above.
// Make the request asynchronously
System.IAsyncResult asyncResult = textbox.BeginInvoke(
new MethodInvoker(
delegate { /* insert delegate code here */ }));
// Process the message queue until this request has been completed
while(!asyncResult.IsCompleted) Application.DoEvents();
// Clean up our async request
textbox.EndInvoke(asyncResult);
Since you seem to have your code working, you can ignore the above test code.
Your problem is not related to the timer and all the Invoke statements you use are not necessary. The System.Windows.Forms.Timer class operates in the UI thread. Look here: http://msdn.microsoft.com/en-us/library/system.windows.forms.timer.aspx

Categories

Resources