Saturday, January 31, 2009

Obtaining computer SID and Processor ID using C#

Sometimes you have to track a unique identifier for an application (e.g. license key registration). Here are two small C# methods to get the Windows SID (Security ID) and the motherboard processor ID (may be more than one).

using System;
using System.Linq;
using System.Management;
using System.Security.Principal;

namespace ConsoleTest
{
class Program
{
static void Main(string[] args)
{
new Program().Run(args);
}

private void Run(string[] args)
{
string sid = UserSecurityId();
Console.WriteLine("The SID is: {0}", sid);

string[] processorIds = ComputerProcessorId();
foreach (string id in processorIds)
{
Console.WriteLine("Processor ID: {0}", id);
}
}

public string UserSecurityId()
{
return WindowsIdentity.GetCurrent().User.AccountDomainSid.ToString();
}

public string[] ComputerProcessorId()
{
return new ManagementObjectSearcher("Select * from Win32_Processor")
.Get()
.OfType<ManagementObject>()
.Select(o => o["ProcessorID"].ToString())
.ToArray();
}
}
}

Sunday, January 25, 2009

TFS Lightweight Scrum Template Graphic

Here is an 17" x 11" graphic of the TFS Lightweight Scrum template. It is pretty much the same as the one on the codeplex site (which is terrible quality). The scaling of the graphic is such that you can place it on 8.5" x 11" paper as well.

Enjoy.

Click here for graphic.

Sunday, January 18, 2009

Converting Office 2007 Excel to XML using C#

Don't want Office 2007 installed on your web server to access Excel 2007 content?

Here is a Visual Studio C# solution that demonstrates how to read an Excel 2007 workbook, converting it to XML. You don't need Office 2007 installed in order to do this! Once Excel content is in XML format you can process it easier using transformations tools or other language code.

The solution code uses .NET 3.5 XML support and LINQ. The solution also contains an example console application that will take an Excel 2007 file name on the command-line and convert it to XML via the console. Everything should run out-of-the-box using an example Excel 2007 file that is included; just run the example application and accept the default file name to read.

The quickest way to learn how to use the ExcelReader class, and its options, is to examine the brief Program.cs file in PCarver.OfficeXml.ExampleExcel project. You an register for events to transform cell contents and ignore certain rows (see example code).

Download only the binary files for converting Excel to XML:

Click here for binaries/executables

Download the full Visual Studio Solution:

Click here for Visual Studio 2008 Solution

If you have any bug fixes or nice enhancements, please post a comment and let me know.

Information from Microsoft on these formats is found at:

http://msdn.microsoft.com/en-us/library/aa338205.aspx.

Friday, December 19, 2008

Select random songs for MP3 player

I recently upgraded the firmware on my old Nano Plus MP3 player. As a result, the Windows Media Player, running under Server 2008, won't detect the device any more. Since I periodically toss around 50 random songs on my player for running purposes, and the fact that I'm too cheap to buy another compatible player, I wrote a quick-n-dirty lil' C# Windows Forms application to do this.

The application will simply select n random songs given a bunch of different input and output parameters. The UI looks like:



You have a few nice options like providing regular expression filters for including or excluding certain files. Whatever settings you use will be saved in an XML file in your application data folder.

You can download the C# solution by clicking here. It's not the best code, but hey, I needed it before a race tomorrow.

Tuesday, December 2, 2008

Avoiding Embedded T-SQL in Query String

I've seen folks trying to hack a web site by passing large amounts of hex-encoded T-SQL commands embedded withing a query string...and it's a bit disturbing. I like to be a bit proactive when it comes to this type of thing so I tend to use an a custom HTTP module that I register in my web.config. I write a class and place the file in my App_Code folder, then register it in my web.config like:

<httpModules>
<add name="RestrictionHttpModule" type="HttpModule.RestrictionHttpModule"/>
</httpModules>

The C# class looks something like this:

using System;
using System.Web;

namespace HttpModule
{
public class RestrictionHttpModule : IHttpModule
{
public RestrictionHttpModule()
{
}

#region IHttpModule Members

public void Dispose()
{
}

public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(Application_BeginRequest);
}

private void Application_BeginRequest(object source, EventArgs e)
{
HttpContext context = ((HttpApplication)source).Context;

// watch out for t-sql commands that may be embedded
string query = context.Request.Url.Query.ToLower();
if (!string.IsNullOrEmpty(query))
{
if (query.Contains(";declare") ||
query.Contains("exec(") ||
query.Contains("cast(") ||
query.Contains("convert("))
{
context.Response.StatusCode = 403; // forbidden
}
}
}

#endregion
}
}


This is just an example. My actual handler is a bit more robust. I include code that also allows me to reject remote host IPs, remote host names, and referrer names. Since my global exception handler email includes the full URL for any exceptions, it's easy for me to see which type of remote sites are attempting to hack, login without credentials, etc.

Tuesday, November 25, 2008

Making custom changes in LINQ-to-SQL designer

This post describes a scenario I encountered recently that would require making custom changes in the LINQ-to-SQL designer.

Even given that the Microsoft rumor-mill has tagged LINQ-to-SQL as terminal given the rise of LINQ-to-Entity, I still find LINQ-to-SQL useful for those non-enterprise solutions. As many developers know, the LINQ-to-SQL class designer doesn’t provide much automated support for keeping your database schema up-to-date with the class designer objects (tables, relationships, etc.)

I haven’t found this to be a huge issue since I work around this limitation by deleting and re-adding tables (which automatically updates the dbml code). I’ve steered clear of making any custom changes through the designer so I can perform this simple work around.

Recently I ran into an issue that makes me want to make manual changes in the designer. It has to do to the way the relationship property names are generated. Let’s look at an example.

Consider you have a table named Grades that represents school grades like 1, 2, 3, and so forth. Now assume you have another table named Worksheets that represents individual worksheets for each school grade. This is a typical one-to-many relationship. Two of the Worksheets columns are StoreGrade (where a PDF worksheet is stored on disk) and DisplayGrade (which grade to display this worksheet for). This allows a worksheet to be reused for 4th grade even though it is stored in the 3rd grade folder. The StoreGrade and DisplayGrade are foreign keys of the Grades table.

When using the LINQ-to-SQL designer, the above scenario will create a Grade object will two properties called Worksheets and Worksheets1. When using intellisense, it really isn’t possible to know which of these properties is for StoreGrade and which is for DisplayGrade. It is possible to change the property names created by using the designer properties for each relationship, but that would mean I lose the ability to delete/re-add a table with ease.

I’m continuing to hold off making custom designer changes, but this is one scenario I’ve run across that gives a reason to make custom changes via the LINQ-to-SQL designer.

Saturday, November 8, 2008

Measuring Stability and Abstractness

I've always felt that a proper Object-Oriented design must be focused on package and class relationships, and that those relationships should be loosely coupled.

Bob Martin wrote a book back in 1995 called Designing Object-Oriented C++ Applications Using the Booch Method. Chapter 3 of this book explained how to design a loosely coupled architecture based on cohesion and closure. Then in 2006 Bob and his son wrote Agile Principles, Patterns, and Practices in C#. Chapter 28 of this book revisited the topic of loosely coupled architectures.

I have always felt that this topic is crucial to both architecture and design of Object-Oriented solutions, and thus I often revisit the chapters from these books. I finally decided to encapsulate Bob's content into a single page diagram (taken from the second book).

Click here to get it!

Keep this single-page diagram near and dear to your heart...and read Bob's second book, twice.

Friday, November 7, 2008

Visual Studio macro to insert curly braces

I think the most frequently used set of keystrokes I use in development is the process of inserting two curly braces with a blank line in between them.

I found the following Visual Studio macro once on the Internet. You can add this to your list of Visual Studio macros, then use the keyboard configuration to assign it to a keystroke. I've assigned the macro so that when I press Shift-Return, it inserts two curly braces, a blank line in between them, then places the cursor indented on the blank line...ready to type in a statement. I use this keystroke constantly in development.

The macro works fine in both Visual Studio 2005 and 2008.

Sub InsertCurlies()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "{"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "}"
DTE.ActiveDocument.Selection.LineUp()
DTE.ActiveDocument.Selection.NewLine()
End Sub

Using LINQ's ToLookup

Often times you have a set of data and want to process the data in sets based on some property of the data. For example, you may want to process all employee records based on what state the employee lives in (presumably for tax purposes).

To organize the employees, we need something like a .NET dictionary class, but be able to store multiple employees per key (i.e. state). A dictionary only stores a single object per key so we're out of luck using that class.

This is where the LINQ ToLookup and GroupBy operators come to the rescue. ToLookup is a non-deferred operator and GroupBy is a deferred operator. The example below illustrates how ToLookup can be used to process employee objects, together, based on what state the employee lives in. The GroupBy is basically the same thing, but the data is grouped during enumeration because of its deferred nature.

private class Employee
{
public int ID { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
public string StateAbbr { get; set; }
}

static void Main(string[] args)
{
new Program().Run(args);
}

private void Run(string[] args)
{
List<Employee> employees = new List<Employee>
{
new Employee { ID = 1, LastName = "Scott", FirstName = "Michael", StateAbbr = "CO" },
new Employee { ID = 1, LastName = "Smoe", FirstName = "Joe", StateAbbr = "CA" },
new Employee { ID = 1, LastName = "Lampton", FirstName = "Todd", StateAbbr = "CO" },
new Employee { ID = 1, LastName = "Morgan", FirstName = "Jared", StateAbbr = "WA" },
new Employee { ID = 1, LastName = "Smart", FirstName = "Laura", StateAbbr = "ID" },
new Employee { ID = 1, LastName = "Seashell", FirstName = "Sally", StateAbbr = "CO" },
};

ILookup<string, Employee> folksByState = employees
.ToLookup(e => e.StateAbbr);

foreach (IGrouping<string, Employee> stateGroup in folksByState)
{
Console.WriteLine("\nState: {0}", stateGroup.Key);
foreach (Employee e in stateGroup)
{
Console.WriteLine("{0}, {1}, {2}", e.LastName, e.FirstName, e.ID);
}
}
}

Sunday, November 2, 2008

Install Windows Media Player 11 on Windows Server 2003 SP2

I finally found a method that actually works to install Windows Media Player on Windows Server 2003 SP2. I've executed these instructions several times on a VPC, then on my normal server and it was easy. Works great!

1) Download the Windows Media Player 11 setup file and save to disk (e.g. wmp11-windowsxp-x86-enu.exe).

2) Run the setup file.

3) You should see if a Validation Checker dialog. Just leave this dialog box displayed this without clicking any of the buttons.

4) Search your hard drive for the file "wmp11.exe". Once found, use Windows Explorer and go to the directory where this file resides.

5) Copy all the files from this directory to another temporary directory, then close the Validation Checker dialog.

6) Use Windows Explorer and go to the temporary directory you created.

7) Right-click and change Properties on the following files; set Run in Compatibility Mode (on the Compatibility Tab) to Windows XP:

umdf.exe
wmfdist11.exe
wmdbexport.exe
wmp11.exe

8) Run wmfdist11.exe and follow the setup instructions.

9) Run umdf.exe and follow the setup instructions.

10) Reboot the computer.

11) Run wmdbexport.exe (it will execute without anything being displayed).

12) Run wmp11.exe and follow the setup instructions.

13) Reboot the computer.

14) Windows Media Player 11 should now be installed and ready to use.

15) Remove your temporary directory when you are sure everything is working.

Wednesday, October 8, 2008

Fast file compare using .NET HashAlgorithm.ComputeHash

I recently had a huge set of files in dozens of directories that I knew were somehow different from a backup. I needed to know which files were different (I just needed the file names). Normally I would use software like Beyond Compare, but this was not an option since the two sets of files were in two different remote locations without an option of copying 5G worth of data from one location to the other.

The solution I came up with, which worked out great, was to modify a set of code from my C# Recipe book that computed a hash of two files and compared the hash values. The new code accepts a file pattern, recursively finds all matching files (from the current directory), then writes out each files hash value and file name.

I executed the program on both systems, redirecting the output to a text file, then just had to compare the two text files. Note: Be careful that the FileHash program itself and any redirected output files are not included in the file pattern that you are searching on.

Example:

..\FileHash.exe *.* > ..\hashvalues.systemA.txt


using System;
using System.IO;
using System.Security.Cryptography;

namespace FileHash
{
class Program
{
static void Main(string[] args)
{
new Program().Run(args);
}

private void Run(string[] args)
{
// Create the hashing object.
string[] files = Directory.GetFiles(@".\", args[0], SearchOption.AllDirectories);

foreach (string file in files)
{
using (HashAlgorithm hashAlg = HashAlgorithm.Create())
{
using (FileStream fs = new FileStream(file, FileMode.Open))
{
// Calculate the hash for the files.
byte[] hashBytes = hashAlg.ComputeHash(fs);

// Compare the hashes.
Console.WriteLine(string.Format(
"{0} {1}",
BitConverter.ToString(hashBytes),
file));
}
}
}
}
}
}

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 ...