How To Add Or Change XML Encoding With .NET

Last time I wrote about comparing XML strings in .NET, and continuing that theme I’d like to discuss another handy XML trick.  As the last article pointed out, not all XML strings are created equal.  In fact, sometimes they are missing the necessary XML version and encoding information, like in the following sample XML:

    <SampleField2 value="test value" />
    <SampleField3 type="int">456</SampleField3>

Notice anything missing?   Yes, the declaration information is not at the start of the XML string.  Declaration information like in the below example:

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

Continue reading

How to Compare XML Strings Using .NET

So you want to compare two XML strings together to see if they are equal. Obviously, it would be easy to just compare the two strings using a regular string equality comparison and call it a day. However, what if the XML strings looked like the following:

    <SampleField2 value="test value" />
    <SampleField3 type="int">456</SampleField3>
    <SampleField2     value="test value" />
        <SampleField3 type="int">456</SampleField3></SampleXML>

All of the nodes, attributes and values are the same, but the formatting is way off. Obviously, a string equality comparison between these two would return false. Is there anything that can be done about this? Not to fear, .NET provides a pretty simple solution. Continue reading

Creating Case Insensitive Dictionaries In .NET

For millennia, mankind has looked to the stars and wondered, “How can I create a generic Dictionary in .NET that allows me use case insensitive strings as keys?” Well today that age old question will be answered with this neat trick.

Simply put, all you need to do is add a StringComparer object when constructing a generic Dictionary that uses a string key, and make sure to use on of the IgnoreCase StringComparers that are offered. Below is some sample code to illustrate just how easy this is.

// Create a generic dictionary with a string comparer that ignores case sensitivity.
// This includes the following:
//  - CurrentCultureIgnoreCase
//  - InvariantCultureIgnoreCase
//  - OrdinalIgnoreCase
Dictionary<string, string> stringMap = 
     new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
stringMap.Add("Test Key", "Some value");

// Now try to access or change the corresponding value with the key.
// The case of the key string no longer matters.
stringMap["test key"] = "This will work";
stringMap["TEST KEY"] = "And also this";
stringMap["tEsT kEy"] = "And this as well";
stringMap["tEST kEY"] = "And finally this";

// This can be done with any dictionary that uses a string as the key
Dictionary<string, int> numberMap = 
     new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
numberMap.Add("Test Key", 0);

// Same deal here, you can use any case to get or set the values in the map
numberMap["test key"] = 1;
numberMap["TEST KEY"] = 2;
numberMap["tEsT kEy"] = 3;
numberMap["tEST kEY"] = 4;

And that’s all there is to it.  I hope you enjoy and find this useful.

Richard Franzen
ImageSource, Inc.

Making Command Line Calls In .NET

Sometimes you just need to call a console executable.  Whether it is legacy code or the only interface for 3rd party software, console applications are still used and still need to be interfaced with.  Fortunately, .NET comes with a class built specifically to get that job done.  The Process class, located in the Systems.Diagnostics library, can be called to handle console executables and their command line arguments.  Below is an example on how to call this useful class:

Process proc = new Process();

// First, specify the executable file name and any command line arguments
proc.StartInfo = new ProcessStartInfo("C:\\temp\\CmdLineProgram.exe", 
     "-i \"C:\\temp\\InputFile.txt\" -o \"C:\\temp\\OutputFile.txt\"");

// Next, since we want to run this in our program, we don't want the 
// shell to execute it nor have it display in an external window.
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.CreateNoWindow = true;

// We also want to get any error or output data that the executable might write out.
// This should capture data normally written out to the console screen.
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;

// Now let the executable run.  We'll wait here for it to finish process.

// Gather any exit code information
int exitCode = proc.ExitCode;

// And get the output and error messages.
string errorMsg = string.Empty;
using (StreamReader reader = proc.StandardError)
     errorMsg = reader.ReadToEnd();
}string outMsg = string.Empty;
using (StreamReader reader = proc.StandardOutput)
     outMsg = reader.ReadToEnd();

Hopefully this small sample will help out with making calls to console applications.  Regarding retrieval of exit codes, output and error messages, not all console applications like to output them to the same place.  Sometimes all output messages actually go to the error message, so you may need to look there.  Some trial and error may be necessary, so make sure to test out the code to find what works and what doesn’t.

Speed Up File Management With Enumeration

If you’ve ever had manage a collection files in .NET then you know the drill, you call Directory.GetFiles or DirectoryInfo.GetFiles.  In either case you get an array of files back, either in the form of file name strings or FileInfo objects.  This method works just fine for a small list of files, but when the list size starts to get large, loading a large array into memory can be problematic.  Not only does it consume a large amount of memory, but sorting and looping through this large array can be time consuming.

Continue reading

Index Creation In SQL Azure

Doing some testing in SQL Azure, I found that table creation is a slightly different beast.  Simply using a SQL table creation script generated by the SQL Server Management Studio does not translate into the Azure environment.  I needed to make some modifications first to get the code working correctly, specifically how Indexes are created.

Continue reading