Monday, November 29, 2010

Named Pipes (.NET C#)

Named pipes can be very useful for a variety of functions. I found that a named pipe was the right solution for passing the command line arguments to an already running application (avoiding reloading the application entirely). NamedPipeServerStream and NamedPipeClientStream are the basic classes necessary to create a byte stream pipe between various applications.

A named pipe is a single connection utility. If you make a connection and disconnect you will need to create a new one. You have a few options on how to handle multiple connections with multiple threads. I simply setup a while loop that continued to recreate the named pipe as connections were made and closed. I am sure I still have a lot more to learn about using pipes.


// Server Side
 
NamedPipeServerStream zPipe = new NamedPipeServerStream(PIPE_NAME, PipeDirection.In, 1, PipeTransmissionMode.Message);
zPipe.WaitForConnection();
StringBuilder zBuilder = new StringBuilder();
do
{
    int nLength = zPipe.Read(arrayData, 0, arrayData.Length);
zBuilder.Append(Encoding.UTF8.GetString(arrayData, 0, nLength));
} while (!zPipe.IsMessageComplete);
 
// Client Side
 
NamedPipeClientStream pipeClient = new NamedPipeClientStream(".", PIPE_NAME, PipeDirection.Out);
try
{
pipeClient.Connect(1000);
}
catch (Exception) {return;}
if (pipeClient.IsConnected && pipeClient.CanWrite)
{
    byte[] arrayData = Encoding.UTF8.GetBytes(sMessage);
pipeClient.Write(arrayData, 0, arrayData.Length);
}

Server Pipe
Client Pipe

My previous experience with byte reading and writing to Sockets helped me understand the basics of a pipe. If you have written to streams of any sort you should be able to figure out pipes.

Tuesday, November 16, 2010

ScrollToControl (.NET C#)

If you are using a Panel you may notice that it jumps around when you restore focus. It is actually jumping to the xy position of the current control within the Panel. This is due to implementation calling ScrollToControl. For example I have an application that uses a Panel as a convenient alternative to creating a ScrollableControl. My control is the only one in the Panel and I wanted to take advantage of the background image along with the auto-scroll functionality. My Panel is a specialized derivative of Panel so I went ahead and created the override below:

   1:  protected override Point ScrollToControl(Control activeControl)
   2:  {
   3:      if (m_bDisableScrollToControl)
   4:      {
   5:      return AutoScrollPosition;
   6:      }
   7:      return base.ScrollToControl(activeControl);
   8:  }

Basically I only allow the ScrollToControl if my custom boolean is enabled. In the case of a single control it will likely never be enabled. Instead I just leave the position as-is based on the AutoScrollPosition.

Friday, November 5, 2010

Saving & Loading a Form's state (.NET C#)

Saving and loading the state of a window is a very much appreciated (and often overlooked) feature of an application. There is a slight trick to it though. It is not apparent unless you dig a bit. Based on the state of the Form the Location and Size are not what you expect. If a window is anything but FormWindowState.Normal the Size and Location are not the values you want to save. Instead you need to store the RestoreBounds values of those fields. I have an example implementation below for storing the state of a Form to a string followed by the code to restore it.


   1:  public static string GetFormSettings(Form zForm)
   2:  {
   3:      if (FormWindowState.Normal == zForm.WindowState)
   4:      {
   5:          return zForm.Location.X + ";" + zForm.Location.Y + ";" +
   6:              zForm.Size.Width + ";" + zForm.Size.Height + ";" +
   7:              (int)zForm.WindowState;
   8:      }
   9:      else
  10:      {
  11:          return zForm.RestoreBounds.Location.X + ";" + zForm.RestoreBounds.Location.Y + ";" +
  12:              zForm.RestoreBounds.Size.Width + ";" + zForm.RestoreBounds.Size.Height + ";" +
  13:              (int)zForm.WindowState;
  14:      }
  15:  }
  16:   
  17:  public static void RestoreState(Form zForm, string sInput)
  18:  {
  19:      string[] arraySplit = sInput.Split(new char[] { ';' });
  20:      int[] nValues = new int[5];
  21:      if (5 == arraySplit.Length)
  22:      {
  23:          for (int nIdx = 0; nIdx < arraySplit.Length; nIdx++)
  24:          {
  25:              nValues[nIdx] = int.Parse(arraySplit[nIdx]);
  26:          }
  27:          zForm.Location = new Point(nValues[0], nValues[1]);
  28:          zForm.Size = new Size(nValues[2], nValues[3]);
  29:          zForm.WindowState = (FormWindowState)nValues[4];
  30:      }
  31:  }

MSDN Forms.RestoreBounds

Thursday, November 4, 2010

Dictionary vs. Enum.Parse (.NET C#)

I have often wondered if I should use Enum.Parse or a Dictionary of strings to translation a string to an enumeration value. I have always suspected the Dictionary look up would be faster than the Enum.Parse. I decided it was time to test things out. Here's the sample code:

   1:  enum Place
   2:  {
   3:      Home,
   4:      Work,
   5:      Neither,
   6:      End = Neither
   7:  }
   8:   
   9:  static Dictionary<string, Place> dictionaryPlaces = null; 
  10:   
  11:  static void Main(string[] args)
  12:  {
  13:      const string sHome = "Home";
  14:      const string sWork = "Work";
  15:      const string sNeither = "Neither";
  16:      const string sEnd = "End";
  17:   
  18:      if (!Stopwatch.IsHighResolution) { throw new Exception("No high resolution timer! :("); }
  19:      Stopwatch zStopwatch = Stopwatch.StartNew();           
  20:      dictionaryPlaces = new Dictionary<string, Place>();
  21:      dictionaryPlaces.Add(sHome, Place.Home);
  22:      dictionaryPlaces.Add(sWork, Place.Work);
  23:      dictionaryPlaces.Add(sNeither, Place.Neither);
  24:      dictionaryPlaces.Add(sEnd, Place.End);
  25:      zStopwatch.Stop();
  26:      Console.WriteLine("Dictionary Creation: " + zStopwatch.ElapsedTicks);
  27:   
  28:      for (int nIdx = 0; nIdx < 2; nIdx++)
  29:      {
  30:      Console.WriteLine(Environment.NewLine + "--Dictionary Lookup");
  31:      LookupEnumByDictionary(sHome);
  32:      LookupEnumByDictionary(sWork);
  33:      LookupEnumByDictionary(sNeither);
  34:      LookupEnumByDictionary(sEnd);
  35:   
  36:      Console.WriteLine(Environment.NewLine + "--Enum Lookup");
  37:      LookupEnum(sHome);
  38:      LookupEnum(sWork);
  39:      LookupEnum(sNeither);
  40:      LookupEnum(sEnd);
  41:      }
  42:      Console.ReadLine();
  43:  }
  44:   
  45:  static void LookupEnumByDictionary(string sValue)
  46:  {
  47:      Stopwatch zStopwatch = Stopwatch.StartNew();
  48:      Place ePlace = dictionaryPlaces[sValue];
  49:      zStopwatch.Stop();
  50:      Console.WriteLine(ePlace.ToString() + "(" + zStopwatch.ElapsedTicks + ")");
  51:  }
  52:   
  53:  static void LookupEnum(string sValue)
  54:  {
  55:      Stopwatch zStopwatch = Stopwatch.StartNew();
  56:      Place ePlace = (Place)Enum.Parse(typeof(Place), sValue);
  57:      zStopwatch.Stop();
  58:      Console.WriteLine(ePlace.ToString() + "(" + zStopwatch.ElapsedTicks + ")");
  59:  }

Here's the output:


Dictionary Creation: 15315
 
--Dictionary Lookup
Home(4218)
Work(10)
Neither(2)
Neither(1)
 
--Enum Lookup
Home(10)
Work(5)
Neither(5)
Neither(4)
 
--Dictionary Lookup
Home(2)
Work(1)
Neither(1)
Neither(1)
 
--Enum Lookup
Home(5)
Work(5)
Neither(4)
Neither(5)

The initial hits of the Dictionary construction and initial query are large but if you have a program performing a lot of string to enumeration values the Dictionary would result in the best performance over time. I added the second pass through the loop as I guessed it might further reveal the likely pattern.

Wednesday, November 3, 2010

RSACryptoServiceProvider (.NET C#)

Long ago I wrote a file server that provided encrypted passwords at login. To encrypt the passwords I used RSACryptoServiceProvider. It is a reasonably simple way to generate a public and private key so you can encrypt information and pass it back and forth. The code below passes a new public key (RSAParameters) to the client in the form of an XML serialized object. The code missing in this example is the actual Socket interaction back and forth. The server side also has an RSA.Decrypt call later used to check the validity of the sent password.


   1:  // Server Side
   2:  RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
   3:  RSAParameters zParams = RSA.ExportParameters(false); // false avoids exporting the private key!
   4:  MemoryStream zStream = new MemoryStream();
   5:  XmlSerializer zXSerial  = new XmlSerializer(zParams.GetType());
   6:  zXSerial.Serialize(zStream, zParams);
   7:  // send public key to client
   8:  ...
   9:  // decrypt and check password
  10:   
  11:   
  12:  // Client Side
  13:  RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
  14:  RSAParameters zParams = new RSAParameters();
  15:  XmlSerializer zXSerial = new XmlSerializer(zParams.GetType());
  16:  MemoryStream zStream = new MemoryStream(arrayPostHeader);
  17:  zStream.Seek(0, SeekOrigin.Begin);
  18:  zParams = (RSAParameters)zXSerial.Deserialize(zStream);
  19:  RSA.ImportParameters(zParams);
  20:  arrayEncrypted = RSA.Encrypt(m_zEncoder.GetBytes(sPassword), false);
  21:  // send to server
(line 16) arrayPostHeader is a byte[] related to the Socket message to be sent back to the server
(line 20) arrayEncrypted is a byte[] and sPassword is a string

I recall being very glad that encryption was simple to setup and use!

Looking  back at my old code I can see that line 15 really should just be a typeof. There's really no need to create a new object if you just need the type.

Tuesday, November 2, 2010

ListBox Item Text Update (.NET C#)

ListBoxes are a convenient control that allows you toss any object into it and display the list of items to the user. You can override the ToString method to display your object name as you see fit. Unfortunately you cannot update the name of an item in the list by changing the variables related to your ToString override. I have seen a number of interesting approaches to the problem online. I created one of my own as it seemed like it might work. It looks a bit odd... but the reassignment of an item to itself triggers the necessary update to your text.


listBoxFiles.Items[listBoxFiles.SelectedIndex] = listBoxFiles.Items[listBoxFiles.SelectedIndex];


This is "uh" solution to the problem. I do not recommend it wholesale. It will work well if your ListBox is single selection and not sorted(see below on those). You should also evaluate the alternatives out in google land or wherever you find interesting solutions to annoying problems (back alleys, bingo parlors, or a bottle of alcohol). Plus you may run into some extra fun in the following situations:

Sorted ListBox
  • You are not "adding" items to the list box, just changing the array of items. You will need to set Sorted to false then true to trigger a proper sort.
  • ...and more... ?
Multi-Selection
  • Your selection will need to be carefully managed. The reassignment of multiple items in the array will likely break your selection state at the conclusion of the rename.
  • ...and more... ?

Monday, November 1, 2010

Clean your PC!

This past Saturday I was coding and my computer shut off on its own. It proceeded to shut down a number of times throughout the morning before I finally broke out my vacuum. I took out my nVidia GTX 260 video card to clean it and found a nice healthy layer of dust. I gave everything a decent cleaning and put everything back together. When I powered my PC up the video card was running 10 degrees (Celsius) cooler! I also found that my highest temperature from running a game (Dead Space in this case) was 15 degrees cooler. (around 55)

I've often heard and recommended "reboot your pc" as the obvious answer to most problems. Now I will add "vacuum or blow out the dust in your pc" to my list of simple recommendations when strange things come up.