Friday, October 29, 2010

Microsoft Lync 2010 RTM

After 2 years of development we just had RTM (Release To Manufacturing) of Microsoft Lync 2010 (former Microsoft Office Communications Server). We develop voice applications here in Zurich.

Here are the celebration pics from this event:




Tuesday, October 26, 2010

Creating and Extracting a Zip File for Free

I could not find a free zip/unzip program on the web, so I had to create one myself.
Good guys here are at http://dotnetzip.codeplex.com that created a free zip library (Ionic.zip.dll) for us to use.

Using the Ionic library the program code for zipping and unzipping files is straightforward:

using System;
using System.IO;
using System.Text;
using Ionic.Zip;

namespace Zip
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length < 2)
            {
                Usage();
                return;
            }

            if (args[0].StartsWith("z"))
            {
                Pack(args[1]);
            }
            else
            {
                UnPack(args[1]);
            }
        }

        static void Pack(string dir)
        {
            try
            {
                string dirRoot = Path.GetDirectoryName(dir);
                string dirName = Path.GetFileName(dir);
                string result = Path.Combine(dirRoot, dirName + ".zip");

                using (ZipFile zip = new ZipFile())
                {
                    zip.AddDirectory(dir, dirName);
                    zip.Save(result);
                }
                Console.WriteLine("Saved {0} to {1}", dir, result);
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error packing: " + exc.Message);
                return;
            }
        }

        static void UnPack(string zipfile)
        {
            try
            {
                string dirRoot = Path.GetDirectoryName(zipfile);
                string dirName = Path.GetFileNameWithoutExtension(zipfile);
                string result = Path.Combine(dirRoot, dirName + "_extracted");

                using (ZipFile zip1 = ZipFile.Read(zipfile))
                {
                    foreach (ZipEntry e in zip1)
                    {
                        e.Extract(result, ExtractExistingFileAction.OverwriteSilently);
                    }
                }
                Console.WriteLine("Extracted {0} to {1}", zipfile, result);
            }
            catch (Exception exc)
            {
                Console.WriteLine("Error unpacking: " + exc.Message);
                return;
            }
        }

        static void Usage()
        {
            string exe = System.Reflection.Assembly.GetExecutingAssembly().Location;
            Console.WriteLine("Usage: {0} zip|unzip <directory|zip file>", exe);
            Console.WriteLine(" E.g.: {0} zip \"C:\\tmp\"", exe);
            Console.WriteLine(" E.g.: {0} unzip \"C:\\tmp\\myfile.zip\"", exe);

            Console.WriteLine();
            Console.WriteLine("Please press any key.");

            Console.ReadKey();
        }
    }
}


You can download this free zip/unzip program at http://www.nanogmail.com/Zip.zip and the dll from

Instructions:
  • Download Zip.zip and rename it to Zip.exe
  • Download Ionic.Zip.zip and rename it to Ionic.Zip.dll
  • Place Ionic.Zip.dll and Zip.exe to the same directory
  • Usage:
    • Zip.exe zip C:\directoryToZip
    • Zip.exe unzip C:\myzipfile.zip

You can also create and extract Zip files using standard .Net, but it is less straightforward.
Here is how to do that (add a reference to WindowsBase.dll in your project):


using System.IO;
using System.IO.Packaging;

namespace MyZip
{
    public class Zip
    {
        private static int _dataChunk = 1024;

        public static void CreateZipFile(string zipFile, string pathname)
        {
            using (Package zip = Package.Open(zipFile, FileMode.Create))
            {
                AddDirToZip(zip, pathname, "");
            }
        }

        public static void ExtractFromZipFile(string zipFile, string pathname)
        {
            using (Package zip = Package.Open(zipFile, FileMode.Open, FileAccess.Read))
            {
                foreach (PackagePart zipPart in zip.GetParts())
                {
                    Uri uri = zipPart.Uri;

                    string file = pathname + uri.OriginalString;
                    string dirName = Path.GetDirectoryName(file);

                    using (FileStream output = File.Create(file))
                    {
                        Stream input = zipPart.GetStream(FileMode.Open, FileAccess.Read);

                        byte[] buf = new byte[_dataChunk];
                        int bytes;

                        while (0 != (bytes = input.Read(buf, 0, _dataChunk)))
                        {
                            output.Write(buf, 0, bytes);
                        }

                        output.Close();
                    }
                }
            }
        }

        private static void AddDirToZip(Package zip, string pathname, string relDir)
        {
            foreach (string dir in Directory.GetDirectories(pathname))
            {
                string newRelDirName = relDir + Path.GetFileName(dir) + "\\";
                AddDirToZip(zip, dir, newRelDirName);
            }

            foreach (string file in Directory.GetFiles(pathname))
            {
                AddFileToZip(zip, file, relDir);
            }
        }

        private static void AddFileToZip(Package zip, string file, string relDir)
        {
            string filename = Path.GetFileName(file);
            string relPath = relDir + filename;
            Uri uri = PackUriHelper.CreatePartUri(new Uri(relPath, UriKind.Relative));
            PackagePart zipPart = zip.CreatePart(uri, System.Net.Mime.MediaTypeNames.Text.Plain);

            using (FileStream input = new FileStream(file,
                FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                Stream zipStream = zipPart.GetStream();

                byte[] buf = new byte[_dataChunk];
                int bytes;

                while (0 != (bytes = input.Read(buf, 0, _dataChunk)))
                {
                    zipStream.Write(buf, 0, bytes);
                }
            }
        }
    }
}

Tuesday, October 12, 2010

Using .Net Profiler with Visual Studio

Using a profiler is indispensable for any non-trivial project. It helps avoiding any guessing on what can take the longest in the program. Let's see how we can use it with Visual Studio. Consider this method of converting a class to an XML string in C#:


internal static string GetString(string msg)
{
    byte[] bytes = null;


    atype aType = new atype();

    aType.a = msg;
    using (MemoryStream bodyStream = new MemoryStream(256))
    {
        XmlSerializer serializer = new XmlSerializer(typeof(atype));
        serializer.Serialize(bodyStream, aType);
        bytes = bodyStream.GetBuffer();
    }


    string retVal = Encoding.UTF8.GetString(bytes);
    return retVal;
}

It turns out that the code above, which is called over and over, sometimes takes a lot of time.
How can we fix it? What is the statement that takes most of the time?
The class atype is a very simple one, converted to a C# file from an XSD definition file by .Net Framework:

[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd""3.5.30729.1")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(TypeName="a-type", Namespace="http://www.w3.org/2001/10")]
[System.Xml.Serialization.XmlRootAttribute("a",
Namespace =
"http://www.w3.org/2001/10",
IsNullable =
false)]
public class atype
{
    private string aField;    [System.Xml.Serialization.XmlAttributeAttribute(Form=System.Xml.Schema.XmlSchemaForm.Qualified, Namespace="http://www.w3.org/XML/1998/namespace")]
    public string a
    {
        get
        {
            return this.aField;
        }
        set
        {
            this.aField = value;
        }
    }
}

Let's use the profiler to figure out what is going on.
In Visual Studio (probably you need at least a professional one) go to Analyze -> Launch Performance Wizard. There are two options, select the most complete one, Instrumentation.
You will get an extra window called “Performance Explorer”.
Click on the “Launch with Profiler” button there.

Here are the results you get after running the original code:

Functions With Most Individual Work
NameTime (msec)%
System.Xml.Serialization.XmlSerializer..ctor(class System.Type)
783.2489.36
System.Xml.Serialization.XmlSerializer.Serialize(class System.IO.Stream,object)
68.927.86
profiler.Program.Main(string[])
8.400.96
profiler.Program.GetString(string)
4.430.50
System.Text.Encoding.GetString(uint8[])
3.520.40

So we can see right away that the answer is the XmlSerializer constructor.
(now we can even say that it kind of makes sense, considering all reflection operations going on there).
Once we identify the problem, the solution is clear: create a static XmlSerializer once and just reuse it!
After one line change - moving serializer declaration from inside the method outside and making it static - calling this function multiple times performs about 10 times faster!