Retrieve return value from executable inside a C# application

C#, English No Comments »

Recently, I encountered some difficulties trying to read the return value from an executable file. I’m was trying to call SpamAssassin from within a C# console application and couldn’t retrieve it’s return value. Since the exit code indicates whether an email is spam or ham, I had to find a way to receive that value. After struggling a bit, I found out that instead of calling directly SpamAssassin, I had first to call cmd.exe and handle it, as an argument, the path to the SpamAssassin executable. The code ended as following:

Process p = new Process();
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.UseShellExecute = false;
p.StartInfo.Arguments = @" /C C:\spamassassin.exe -e -L < C:\SPAM_TEST.MAI";
p.StartInfo.FileName = @"C:\WINDOWS\System32\cmd.exe";
p.OutputDataReceived += (sender, arguments) => Console.WriteLine("Received output: {0}", arguments.Data);
p.Start();
p.BeginOutputReadLine();
p.WaitForExit();
Console.WriteLine("Exit code: " + p.ExitCode);
p.Close();

Here is a screenshot of the console after calling cmd.exe with a ping command:

launch_exe_from_console

Query CouchDB from a C# application

C#, English No Comments »

For a couple of years now, I have been following Damien Katz’s blog entries.  I subscribed to it mostly because I got fascinated reading his story about how he got to rewrite the Lotus Notes’s Formula Engine. In a couple of months, he was able to make a complete re-write of a programming language and make the engine more than 3 times faster!

Damien Katz also happens to be the founder and CEO of CouchDB. For those how are not familiar with this technology, here is a brief description:  CouchDB is a free and open source documented-orientated database engine. It was designed mostly to serve as a database for web applications.  Traditionally, a relational database management system (RDBMS) presents the data to the user as relations i.e. as a set of tables with each table consisting of a collection of rows and columns. In change, CouchDB stores data as a collection of JSON documents. For example, here is how a document about different chocolates is stored on my local server:

JSON document

Since data is stored as a flat collection of documents without any scheme describing its internal relations, the engine is capable of storing large scale objects.  But how can semi-unstructured data (i.e. without relations) be queried? The views allows you to define functions to query  the documents of a database but without affecting the underlying document.  For example, the simplest view returns a table containing all the documents in your CouchDB server. The function goes as follow:

function(doc) {
emit(null, doc);
}

And outputs my chocolate document:

{"total_rows":1,"offset":0,"rows":[
{"id":"chocolates","key":null,"value":{"_id":"chocolates","_rev":"2-4066442969","name":null,"cacao_porcentage":null,"country":null}}
]}

Since CouchDB was build on the web, it’s no surprise it has its own HTTP API to consult it. If you are a heavy Windows user like me, you will need to switch your old query analyzer for your browser. This is what makes CouchDB a fresh and interesting abstraction.  Everything (or almost) will now be done using the HTTP API. As Jeff Atwood once pointed out, the web browser address bar is becoming the new command line. This is becoming so true with CouchDB it’s almost scary!

Since CouchDB hit recently 1.0, I was tented to give it a try using a simple C# application. First you will need to download the latest build. I got mine from a question on Stackoverflow but you can also download it from the official wiki. Although CouchDB is able to run on Windows, it is not yet officially supported. Once you have the files on your computer, you’re almost done! If you downloaded the first build mentioned you will only need to launch the couch_start.bat file inside the bin directory and the server will be loaded in seconds:

couchdb_start

The console should now appear and tell you to relax:

couchdb_console

You should now be able to navigate to your server at: http://127.0.0.1:5984/_utils. In order to query your CouchDB server, you will require a C# API. Several API already exists. I gave it a try with SharpCouch. I attached a small console C# project that uses SharpCouch to list all databases available inside your server:

couchDB_list_db

Older version of StringEnum throws error when accessed by multiple threads

C#, English No Comments »

A C# enumeration refers to a set of named constants. Every value inside an enumerator list has a default integer type which starts at zero and, if not specified otherwise, gets automatically increased by one:

enum WebsiteType {
Blog = 0,
News = 1,
Youtube = 2  };

Which is completely equivalent to:

enum WebsiteType {
Blog,
News,
Youtube  };

But not to:

enum WebsiteType {
Blog = 2,
News = 4,
Youtube = 6  };

Enumeration values can only be associated with integer values, if you want to associate an enum value with a string you will need to enhance the enumeration’s behavior. To achieve it,  I have been using the “StringEnum” class from the Code associate .NET project for quite a while now.  The StringEnum class is a helper class that allows you to associate string value to enum values such as:

public enum Animal {
[StringValue("Domestic cat")]
CAT = 0,
[StringValue("Domestic dog")]
DOG = 1,
[StringValue("Domestic golden fish")]
FISH = 3
}

Once you need to retrieve the value associated with a specific value of the enumeration, you can do the following:

string enumValue = "";
enumValue = StringEnum.GetStringValue(Animal.CAT))

It offers a very practical behavior that I have been using throughout a lot of different projects. Nevertheless, I recommend you to use the up-to date version of the class since the one I have been using is not thread safe. I downloaded it a while ago and never bothered to check for a newer version.

Recently, I created a small ASP.NET image gallery for a contest around the anniversary of the Mexican revolution and independence. People were given the right to upload an image and to vote for an image. I configured log4net in such a way that every error that got caught was sent to me by email. It is that way I discovered that an error is sometimes raised when different threads are working with the StringEnum class. I found it quite interesting since I have been using log4net and StringEnum on a lot of projects and the error had never be thrown before.

For performance reason, the StringEnum class holds a static hashtable with all the string values from the enumeration. This helps reducing the look-up costs caused by the reading of the enumerator’s attributes. When you request the StringValue of a particular enumeration value, the StringEnum class queries its hashtable. If it founds the value then it returns it otherwise it adds the new requested value.

The problem is that the hashtable is a static attribute which means it is shared by all the instances of the StringEnum class. Since there is no control over the insertion into the hashtable, when several threads were accessing it, a “System.ArgumentException” could be thrown:

error_stringEnum

Although the error message is shown in Spanish, it is quite clear that a thread was trying to add a value to the hashtable that already existed! This is not a big surprise since the MSDN documentation states that a “Hashtable is thread safe for use by multiple reader threads and a single writing thread“.  When working with multiple writing threads, things starts to go wrong.

I uploaded a small 2008 Visual Studio solution with a performance test that I applied to the old, the new version of the StringEnum class, and also to a custom version I wrote. Before writing to the hashtable, every thread must request a lock on it, this prevents multiple writing from happening. We need to make sure that while a thread is writing a new value to the hashtable, no other threads can come in and do the same thing. This is where you need to use a lock.

The new version of  StringEnum from the Code Associate locks directly on the hashtable. Although this approach is working, I prefer to use an additional variable to lock on. Creating “lock variables” makes your code a bit cleaner and prevent from having two pieces of code blocking on the same object. In the words of John Skeet: “I believe this is a bad idea (locking on a instance), because it means you have less control over your locks. Other code may well end up locking on the same object as you do within your code, which makes it far harder to ensure that you only obtain locks in an appropriate order“.

If you try out the solution, you will see that the old version of StringEnum (CA_old directory) fails while the newer version (CA_new directory) and mine (CA_custom directory) pass the test without throwing exception. Finally, if you look through my code you will see I added a line of code inside every StringEnum  class that forces the thread to sleep for 12 milliseconds. I added this line in order to provoke more quickly a writing/reading error from a thread. And for those how prefer not to download the project, the method looks like the following, where _stringValue is our hastable:

GetStringValueWithSleep

Download the 2008 Visual Studio solution with the test case.

¿Por qué concatenar cadenas es muy, muy mala práctica?

C# No Comments »

Hace unos días Kirill Osenkov, ingeniero que trabaja en el equipo del IDE Microsoft Visual Studio C#, posteó una pregunta de entrevista que se le hizo interesante:

En un string dado de .NET (en Unicode), considera que existen saltos de línea estándares en la forma \r\n (el equivalente de Environment.NewLine).
Escribe un método que inserte espacio entre dos saltos de líneas consecutivos con el fin de separarlos.

Me llamó mucho la atención, en primer lugar, porque en agosto del 2009 había participado en el proceso de entrevistas para trabajar como intern en Redmond. No recibí ninguna oferta pero este año, lo intentaré otra vez :) . Y en segundo lugar, porque desde mis entrevistas quedé muy aficionado a este tipo de preguntas técnicas sobre estructuras de datos o recursión entre otros. Dado que había encontrado el post poco tiempo después de su publicación, tuve tiempo de escribir una de las primeras respuestas. Tiene muchos defectos pero también contiene unos elementos interesantes:

string text = "hello \r\n\r\n\r\n world!";
string textResult = "";
char[] caFromText = text.ToCharArray();
for (int i = 0; i < caFromText.Length; ++i)
{
textResult += caFromText[i];
if ((int)caFromText[i] == CARRIAGE_RETURN)
{
// check if not reaching the end of the array
if (i + 3 < caFromText.Length)
{
if ((int)caFromText[i + 1] == NEW_LINE
&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; (int)caFromText[i + 2] == CARRIAGE_RETURN
&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; (int)caFromText[i + 3] == NEW_LINE)
{
// two consecutive breaks where detected
textResult += "\n ";
// jump to the next break
++i;
}
}
}
}

Mi idea fue transformar la cadena en un arreglo de caracteres. Luego, iterar sobre cada caracter buscando una secuencia consecutiva de saltos de líneas. Para evitar salirse del arreglo, utilicé un centinela que valida si ya estamos llegando al final del arreglo. Cuando se cumple la condición, se concatena un espacio a la cadena ‘textResult’ que nos sirve para almacenar el resultado final.

Rik Hemsley recompiló todas las repuestas que se propusieron en una bonita solución de Visual Studio. Además, agregó una serie de test para comprobar la validez de todas las implementaciones:

HSBenchmakrPlayground

Me dio gusto ver que mi algoritmo sí pasó todas las pruebas mínimas requeridas para agregar un espacio entre dos saltos de líneas consecutivos. Sin embargo, la velocidad de resolución no era nada buena dado que hace uso de una cadena para concatenar el resultado. Sabía que no era la forma correcta de hacerlo, de hecho lo mencioné en mi comentario, pero no me imaginaba lo malo que podría resultar ser la concatenación. Usando el benchmark de Rik Hemsley pude detectar que mi algoritmo lograba parsear un archivo de 2,106,233 caracteres en aproximadamente 107 minutos o 1 hora y 47 minutos!

Para remediar al problema, cambié la cadena por la clase StringBuilder. Las cadenas en .NET framework son inmutables: cuando concatenamos una cadena, cada vez se crea un nuevo objecto de tipo String en memoria con el valor antiguo más el valor a concatenar. El método Append de la clase StringBuilder permite evitar la creación de una cadena a cada concatenación. A continuación, viene mi versión revisada:

using NUnit.Framework;

namespace KirilQuestion.Implementations
{
[TestFixture]
public class JdecuyperRevisited : InsertSpacesFixture
{
private const char CARRIAGE_RETURN = '\r';
private const char NEW_LINE = '\n';

public override string InsertSpaceBetweenCrLfs(string input)
{
var textResult = "";

var caFromText = input.ToCharArray();

for (var i = 0; i < caFromText.Length; ++i)
{
textResult += caFromText[i];

if (caFromText[i] == CARRIAGE_RETURN)
{
// check if not reaching the end of the array

if (i + 3 < caFromText.Length)
{
if (caFromText[i + 1] == NEW_LINE
&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; caFromText[i + 2] == CARRIAGE_RETURN
&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;&amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp;amp; caFromText[i + 3] == NEW_LINE)
{
// two consecutive breaks where detected
textResult += "\n ";

// jump to the next break
++i;
}
}
}
}
return input.Replace("\r\n\r\n", "\r\n \r\n");
}
}
}

Esta última versión de mi código procesó el mismo archivo en 58.5738 milisegundos, más de 10.000 veces más rápido que mi primera versión. Usar la concatenación genera un costo altísimo que más nos vale evitar. Sin embargo, no olviden que no en todas las situaciones se recomienda ocupar un StringBuilder. No usen un StringBuilder cuando las concatenaciones son mínimas ya que seguramente harán un pequeño pedazo de código mucho más complejo de leer además de crear un objeto adicional en memoria. Aunque para pequeñas concatenaciones StringBuilder es más eficiente, nunca lo es de forma significativa.

Si descargan el benchmark, podrán ver que la solución más rápida es la de Jordan Terrell y hace uso de una expresión regular muy potente:

string output = Regex.Replace(input, @"(\r\n)(?=\r\n)", "$1 ");

La expresión regular permite parsear el archivo en menos de 18 milisegundos! Aún 3 veces más rápido que mi última solución. Para entender la expresión regular, vamos a trabajar con un ejemplo un poco más sencillo donde remplacé ‘\r\n’ por ‘_’. Nuestro texto de entrada será:

string input = "hello world __";

Aplicamos primero una expresión regular sencilla:

string outWithoutGroups = Regex.Replace(input, @"__", "_ _");

El resultado se ve bastante bien ya que aparece un espacio entre los dos _:

hello world _ _

Sin embargo, si cambiamos un poco el texto de entrada las cosas se complican:

string input = "hello world______";

La salida es ahora la siguiente:

hello world _ __ __ _

¿Que estará pasando? Después de las palabras “hello world” aparecen 6 carateres que vamos a nombrar 1, 2, 3, 4, 5 y 6 (son los 6 underscores). Cada vez que la expresión realiza un match, i.e. encuentra dos caracteres _ consecutivos, los reemplaza por _ _. El primer match procesa los caracteres 1 y 2. Luego se sigue con el 3 y el 4 y finalmente con el 5 y el 6. El problema es que con esta expresión, no se procesaron los caracteres 3 y 5. Y es por eso que no aparecen espacios entre el 2 y el 3 y entre el 4 y el 5.

Kirill Osenkov realizó una imagen que explica claramente lo que no está procesando nuestra expresión regular:

reemplazar_underscore

Para remediar ese problema, Jordan Terrell utilizó un constructor llamado lookahead assertion que fue introducido en su tiempo por Perl 5. La aserción se representa mediante ‘?=’ y permite hacer un match de un _ seguido de otro, sin embargo el segundo _ no es parte del match y será evaluado nuevamente por su cuenta. Lo cual permite generar la salida correcta:

hello world _ _ _ _ _ _

¿Alguien ha sido confrontado con preguntas de este tipo?

No olvide especificar ImageFormat al guardar una imagen en C#

C# No Comments »

Ya que las imágenes son recursos generalmente pesados, siempre hay que poner mucha atención al manipularlas. Me di cuenta de lo anterior al generar thumbnails a partir de imágenes de una galería web. La primera versión de mi código era la siguiente:

Image imagenFormatoOriginal = Image.FromFile(Directory.GetCurrentDirectory() + "//test.jpg");
Image imagenFormatoThumb = imagenFormatoOriginal.GetThumbnailImage(1000, 1000, null, IntPtr.Zero);
imagenFormatoOriginal.Dispose();
imagenFormatoThumb.Save("test_thumbnail.jpg");

La imagen original pesa 1,002 KB y tiene dimensiones de 4096 por 6144 pixeles. La imagen thumbnail generada pesa 361 KB con dimensiones de 1000 por 1000. La nueva imagen representa un 36.02% del peso de la imagen original. Puede parecer un buen ratio pero en una galería de cientos de imágenes cada byte se vuelve importante tanto para el disco duro como para el ancho de banda. En el siguiente código, especificamos el formato en el cual deseamos crear el thumbnail:

Image imagenFormatoOriginal = Image.FromFile(Directory.GetCurrentDirectory() + "//test.jpg");
Image imagenFormatoThumb = imagenFormatoOriginal.GetThumbnailImage(1000, 1000, null, IntPtr.Zero);
imagenFormatoOriginal.Dispose();
imagenFormatoThumb.Save("test_thumbnail_con_formato.jpg", ImageFormat.Jpeg);

Ahora, la imagen thumbnail generada pesa 29KB y tiene dimensiones de 1000 por 1000 pixeles, lo cual representa un 0,34% del peso de la imagen original ¿Que estará suciediendo? El artículo de MSDN sobre el método ‘Save’ indica que cuando no se especifica ningún codificador, se ocupa por default el codificador del formato de gráficos de red portátiles (PNG/Portable Network Graphics). Creo que sería un mejor diseño obligar el programador a escoger siempre el formato en el cuál desea guardar su imagen o que el método ‘Save’ trate de adivinar el formato de la imagen al guardarla. Si examinamos el header de nuestros dos thumbnails generados corroboramos lo anterior. El thumbnail generado sin formato tiene un header específico del formato PNG:

Imagen en formato PNG

Imagen en formato PNG

En cambio, el header de la segunda imagen presenta las características del formato JPG, mucho más compacto y de menor calidad que PNG:

Imagen en formato JPG

Imagen en formato JPG

WP Theme & Icons by N.Design Studio
Entries RSS Comments RSS Log in