Introduction
This article is about two small programs that will allow you to send and receive messages across a normal socket and display the message inside a "balloon" notification.
Background
I was using several applications to communicate messages to various users, and found that the many different methods were becoming somewhat cumbersome. So I hastily slapped together some C# code and came up with the following programs. I had never done any real C# programming before, and it was definitely a learning experience.
Using the Code
The NotifyServer
program is pretty simple. Pick a port number and hit the Start button to begin listening. Hit the Stop button to end the listener.
I created some enum
s to hold the values for my Icon
s:
private enum balloonIcons
{
INFO = ToolTipIcon.Info,
ERROR = ToolTipIcon.Error,
WARN = ToolTipIcon.Warning,
NONE = ToolTipIcon.None
}
private enum logIcons
{
INFO = EventLogEntryType.Information,
ERROR = EventLogEntryType.Error,
WARN = EventLogEntryType.Warning,
NONE = EventLogEntryType.Information,
}
I wanted my application to minimize to the notification area when the minimize button was pressed, so I added the following event handler to the form.Deactivate
event:
this.Deactivate += new EventHandler(this.sendToTray);
void sendToTray(Object sender, EventArgs e)
{
if(this.WindowState == FormWindowState.Minimized)
{
this.Hide();
}
}
When the Start button is pressed, I create a TcpListener
, start it and begin an asynchronous accept:
try
{
tcpListen = new TcpListener(new System.Net.IPEndPoint
(System.Net.IPAddress.Any, Convert.ToInt16(this.txtPort.Text)));
tcpListen.Start();
tcpListen.BeginAcceptTcpClient(new AsyncCallback(this.processEvents), tcpListen);
this.notifyIcon.ShowBalloonTip(0, "NotifyServer",
"Now listening on port " + txtPort.Text + ".", ToolTipIcon.Info);
}
catch(System.Exception error)
{
this.notifyIcon.ShowBalloonTip(0, "NotifyServer",
"Listener could not be started!", ToolTipIcon.Error);
}
The processEvents
routine looks like this:
try
{
StringBuilder myMessage = new StringBuilder("");
if(!EventLog.SourceExists("NotifyServer"))
{
EventLog.CreateEventSource("NotifyServer", "Application");
}
eLog = new EventLog();
eLog.Source = "NotifyServer";
TcpListener processListen = (TcpListener) asyn.AsyncState;
TcpClient tcpClient = processListen.EndAcceptTcpClient(asyn);
NetworkStream myStream = tcpClient.GetStream();
myMessage.Length = 0;
string[] messageArray;
if(myStream.CanRead)
{
StreamReader readerStream = new StreamReader(myStream);
myMessage.Append(readerStream.ReadToEnd());
messageArray = myMessage.ToString().Split("|".ToCharArray());
this.notifyIcon.ShowBalloonTip(Convert.ToInt16(messageArray[0]),
messageArray[2], messageArray[3],
(ToolTipIcon) balloonIcons.Parse(typeof(balloonIcons), messageArray[1]));
eLog.WriteEntry(messageArray[3], (EventLogEntryType)logIcons.Parse
(typeof(logIcons), messageArray[1]));
readerStream.Close();
}
myMessage = null;
messageArray = null;
myStream.Close();
tcpClient.Close();
eLog.Close();
tcpListen.BeginAcceptTcpClient(new AsyncCallback(this.processEvents), tcpListen);
}
The Client
program is an easy to use console application as well. You can use any Client
you want that can send messages across the socket. The calling format of the client
program is:
c:\notifyclient hostname port timeout icon[INFO|WARN|NONE|ERROR] "Title" "Message"
The client
simply creates a TcpClient
, connects to the listener, creates a network stream, and writes to it:
StringBuilder myMessage = new System.Text.StringBuilder();
myMessage.AppendFormat("{0}|{1}|{2}|{3}",args[2],args[3],args[4],args[5]);
try
{
TcpClient client = new TcpClient();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes(myMessage.ToString());
client.Connect(args[0], Convert.ToInt16(args[1]));
NetworkStream stream = client.GetStream();
stream.Write(buffer, 0, buffer.Length);
stream.Close();
client.Close();
Console.WriteLine("Message was sent to host " + args[0] + " on port " + args[1]);
}
catch(System.Exception e)
{
Console.WriteLine("Message was not sent");
}
The message is sent to the server in the following format:
Timeout|Icon|Title|Message
Points of Interest
This was one of the first C# projects I ever did, so I'm sure it's quite messy. I'm still learning about thread safety, delegates, and all the other interesting little "gotchas" that come along with the .NET Framework. I'm sure that there are a lot of things done wrong in this program.
Apparently, there is a min
and max
value for balloon timeouts. The timeout is somewhere between 10 and 30 seconds. You can specify a timeout in between those values and it will be obeyed. However, anything over or under those timeouts is ignored and a default timeout is used instead. The timeout counter doesn't seem to tick when the user is idle.
You can use any type of client that can send information over a socket.
History
- October 22, 2007 - Posted