Sunday, June 20, 2010

Wake-on-LAN using C#

I recently set my personal computer to sleep after 30 minutes of inactivity. This seemed reasonable since I was normally only on the computer for a few hours a day.

I quickly realized that when I tried to remote desktop into it, if the computer was asleep it wouldn't connect (duh). I then modified the network interface settings to Wake-on-LAN and enhanced the security a bit by only waking on a "magic packet".

Then I wrote a interface where I can visit a web page and send the "magic packet" to my computer in order to wake it up. I won't go into the whole interface, but the code below demonstrates how to send the "magic packet" from C#. See the wiki article on details about what the "magic packet" is:

http://en.wikipedia.org/wiki/Wake-on-LAN

Also, don't forget to open any inbound or outbound ports on your firewall!

private void SendMagicPacket(string destinationHost, int destinationPort)
{
   // the header frame of 6 bytes of 255
   List<byte> datagram = new List<byte> { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };

   // load the mac address (for demo purposes, set it to zeros)
   byte[] macAddress = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

   // 16 sequences of the MAC address
   for (int i = 0; i < 16; ++i)
   {
      datagram.AddRange(macAddress);
   }

   //
   // you don't have to do both below, but both are shown
   //

   // send directly to an IP address
   using (UdpClient client = new UdpClient())
   {
      client.Connect(destinationHost, destinationPort);
      client.Send(datagram.ToArray(), datagram.Count);
   }

   // broadcast it
   using (UdpClient client = new UdpClient())
   {
      client.Connect(IPAddress.Broadcast, destinationPort);
      client.Send(datagram.ToArray(), datagram.Count);
   }
}

Friday, June 18, 2010

Global.asax and precompiled web sites (aspnet_compiler.exe)

I recently deployed a precompiled VS 2010 (.NET 4) website using the aspnet_compiler. For the most part the site would start, but certain things would cause an exception when accessing objects in the Application object (which are initialized in the Application_Start of Global.asax.cs).

It turns out the issue was I didn't deploy the "precompiledApp.config" file that had been generated. For whatever reason, if you don't deploy this file, one of the things that occurs is the code of your Global.asax.cs isn't executed.

Lesson learned...always deploy the precompiledApp.config file.

Sunday, June 13, 2010

Visual Studio 2010 Pro Power Tools

I recently installed the Microsoft VS 2010 Pro Power Tools. You won't be disappointed in the many cool things it adds to Visual Studio 2010.

Visit Microsoft here to download.

Just a few of the items I really like:
  • Totally new window/tab interface with color-coding and sorting
  • Current line highlighting (finally!)
  • Move current line up or down with Alt-Up/Down arrow
  • Triple-click to select entire line
  • Syntax highlighting in method intellisense

Definitely download and give this a whirl! You won't be disappointed.

Sunday, March 7, 2010

SQL: Inserting a row column based on existing sequence number

Recently I needed to insert a row into a Microsoft SQL database that had a column value that had to be based on an increasing sequence number from other rows in the same table.

For example, each row in the table already might have a column called "SequenceNum" that represented an increasing number for each row. The sequence number would need to be specific to some other key in the table, for example, a "Message" column.

A MAX statement would need to be used to determine the next sequence number, but to ensure that two processes/threads don't each execute the SQL statement at the same time (and end up with the same SequenceNum), a lock would need to be used to isolate each process/thread. One possible SQL statement might be:

-- Assume you have a parameter for Message called @MessageKey
INSERT INTO TableA (SequenceNum, Message)
SELECT
ISNULL((SELECT MAX(SequenceNum) + 1 FROM TableA WITH (TABLOCKX) WHERE Message = @MessageKey), 1)
, @MessageKey

The ISNULL statement is used in case this is the first row inserted for a specific message.

Thursday, February 11, 2010

XML Utility: Remove comments and whitespace

Itching for that lil' utility to have your XML massaged a bit? This program will modify your XML by removing the whitespace and/or comments.

http://mathfactcafe.com/util/xmlstrip.aspx

Friday, February 5, 2010

WCF: appSettings values not seen in nested web.config files

I recently ran into an issue with an WCF application that had services in sub-folders AND each one had it's own web.config file. When the app pool was reloaded after a period of time, appSettings would appear to have vanished when using the standard ConfigurationManager to retrieve them.

The WCF services were derived from a common base class that used some appSettings values. I had to place each service in sub-folders so each service could have their own copy of the appSettings values used by the base class. There are other known problems with WCF and web.config files; these are resolved by adding the aspNetCompatibilityEnabled element to the ServiceModel section of the web.config. I had already done this to fix earlier issues.

This new problem seemed to occur after the app pool was reloaded after being idle. It is like the service didn't even see the web.config in the sub-folder.

To fix the issue I had to create a separate Configuration object and manually point it to use the web.config from the virtual path of the web service in the sub-folder. I created a tiny helper class to read the appSettings for the web services:
/// <summary>
/// This class is used to retreive appSettings values from a configuration file.  Special
/// support is provided when nested web.config files are used since pre .NET 4.0 are broken
/// in terms of nested web.config settings.
/// </summary>
public class WcfAppSettings
{
   private readonly Configuration _config;

   public WcfAppSettings()
   {
      VirtualPathExtension extension = OperationContext.Current.Host.Extensions.Find<VirtualPathExtension>();
      _config = WebConfigurationManager.OpenWebConfiguration(extension.VirtualPath);
   }

   public string this[string key]
   {
      get
      {
         return _config.AppSettings.Settings[key].Value;
      }
   }
}

Then I can then use the above class like:
WcfAppSettings appSettings = new WcfAppSettings();
string x = appSettings["MySettingKey"];

This appears to have fixed the issue. This is supposed to be fixed in .NET 4.0.

Wednesday, January 13, 2010

Word 2007 footnotes appearing on wrong page

I like to create a nice looking document when I'm tasked to do so. This includes using footnotes in Word 2007. I recently found that Word sometimes puts a footnote on the wrong page (especially if I have more than one footnote on a page). You can adjust the line spacing of the footnote to correct this (once I complete a document, I go back and modify all the footnotes even if they are on the correct page).
  1. Put your cursor in the footnote
  2. Modify the paragraph
  3. Set the Line Spacing to "Exactly" and "At" 10.5 pts which is a bit larger than the default footnote font size of 10 pts.
That should do it!

Friday, January 1, 2010

How do you handle configuration differences for environment (dev, QA, prod) using Visual Studio?

When executing a software application, there are always differences in configuration, depending on the environment. These configuration changes may include references to a database server, contact email addresses, or how exceptions are handled. I was recently doing some research on how Visual Studio 2010 handles this.

The question I would like to pose to folks is:

"What is your thoughts and/or model for building and deployment of the software bits? How do you use Visual Studio or other tools to build and deploy a "kit" to an environment?"

Tuesday, December 29, 2009

Nested web.config files and connectionStrings (entry has already been added)

When using the Entity Framework (EF) recently, I ran into a situation where I received the following error message:
The entry 'myConnectionstring' has already been added...web.config line: 47
After investigating I found out this was due to my use of web.config files in nested directories. Here is the situation...

I have a reusable EF DAL (data access layer) that is used by several web services on a single web site. Several of these web services are in sub-folders with their own web.config files. This allows me to have custom settings for each service as well as being able to easily xcopy an entire directory and know I have all the correct settings. For the EF I have a connectionStrings key in the config files. In addition to the nested web.config files, I have the top-level config which also has the EF connectionStrings key.

When I tried to access a web service I would get the error above because .NET was merging the web.config files and found duplicate connectionString keys. To fix this I just had to add the following element within the connectionStrings section, directly before my key:
<remove name="myConnectionString" />
To facilitate knowing I can easily xcopy any web service, it is good practice to add this to all the web.config files, even the top-level one.

Sunday, December 27, 2009

XDocument / XElement - Save using a StringWriter as UTF-8 rather than UTF-16

One thing I find myself having to do on frequent projects is to save XML to a text file. I tend to use the .NET XDocument or XElement classes and use the Save() method. Once and a while I need to call Save() using a TextWriter. By default, when I do this the XML is written using a UTF-16 processing instruction as:

<?xml version="1.0" encoding="utf-16"?>

More often than not you want UTF-8; .NET XElement won't even read the UTF-16 contents back in using the Load() method (and things like IE won't be able to view it in the browser). To work around this problem I derive a new StringWriter and override the Encoding method:

public class StringWriterWithEncoding : StringWriter
{
private Encoding mEncoding;
public StringWriterWithEncoding(Encoding encoding)
{
mEncoding = encoding;
}

public override Encoding Encoding
{
get { return mEncoding; }
}
}

Now just use the new class and the XElement.Save() method to write as UTF-8:

XElement xml = XElement.Parse("<root/>");
using (StringWriterWithEncoding writer = new StringWriterWithEncoding(Encoding.UTF8))
{
xml.Save(writer);
Console.WriteLine(writer.ToString());
}

Wednesday, December 16, 2009

The row value(s) updated or deleted either do not make the row unique or they alter multiple rows

I was working with a Microsoft SQL database today (not mine thank goodness) that had duplicate rows; the table had no primary key defined. When I went to go delete the duplicate row (or even change it), I got the error:

The row value(s) updated or deleted either do not make the row unique or they alter multiple rows(2 rows)

It was somewhat hard to figure out how to delete the duplicate row. In the end, I was able to delete it by doing:

SET ROWCOUNT 1
DELETE FROM myTable WHERE statmentToSelectTheDuplicateRow

Another reason why to always define primary keys so you don't even get into this situation.

Can't RDP? How to enable / disable virtual machine firewall for Azure VM

Oh no!  I accidentally blocked the RDP port on an Azure virtual machine which resulted in not being able to log into the VM anymore.  I did ...