I stumbled upon a small and very useful utility. It helps to read parameters for a console application in a developer-friendly way. The tools’ name is NDesk.Options, it is free and available from the official NuGet package storage, thus CI friendly.
I am writing a small console app that monitors performance of another process. Console app takes in some parameters, and being agile about it, I know which parameters I definitely need, such as process name and, perhaps, where to store performance data. Still, later I may need to add/amend/remove something. So parameters shall not be rigidly typed in. This is exactly what you can do with NDesk.Options.
Having said that, let’s take a quick look at the code of a wrapping class called, well, Parameters.
public class Parameters
{
public string ProcessName { get; set; }
public string LogName { get; set; }
public double Interval { get; set; }
public bool PrintHelp { get; set; }
public OptionSet Options { get; set; }
public Parameters()
{
string tmp = ConfigurationManager.AppSettings["defaultLog"];
string format = ConfigurationManager.AppSettings["fileNameDateFormat"];
string date = DateTime.Now.ToString(format);
LogName = String.Format(tmp, date);
Options = RegisterSupported();
}
private OptionSet RegisterSupported()
{
var p = new OptionSet
{
{
"process=|p=", "Name of the process to be monitored",
option => ProcessName = option
},
{
"log=|l=", "Path to log file. Default: log_[DateTime].txt",
option =>
{
if (!String.IsNullOrEmpty(option))
{
LogName = option;
}
}
},
{"h|?|help", option => PrintHelp = option != null},
};
return p;
}
}
As you can see this class has got Properties that are assigned from the input. In the class constructor I registered default parameters. The usage of the class is really straightforward
internal class Program
{
private static void Main(string[] args)
{
//create new default parameters
var parameters = new Parameters();
//parsing the input
try
{
parameters.Options.Parse(args);
}
catch (OptionException ex)
{
Helpers.PrintException(ex);
return;
}
//if needed print help and exit
if (parameters.PrintHelp)
{
Helpers.PrintHelp(parameters.Options);
return;
}
// Do stuff here
}
}
See how easy it is to print help or error
public class Helpers
{
public static void PrintHelp(OptionSet p)
{
Console.WriteLine("--Process performance monitor--");
Console.WriteLine("Application logs performance parameters of another process");
Console.WriteLine();
Console.WriteLine("Options:");
p.WriteOptionDescriptions(Console.Out);
}
public static void PrintException(Exception ex)
{
Console.WriteLine("Boom! Error occurred");
Console.WriteLine(ex.Message);
Console.WriteLine("Try `--help' for more information.");
}
}
And this is actually what is produced by calling help.

Overall impression NDesk.Options rocks, manual implementation will take far more time to implement this simpe functionality.
If you enjoyed this post, make sure you subscribe to my RSS feed!
36ea4598-6892-4eae-843f-288ce49d73f5|0|.0
I have been recently debugging an application with a leaking problem. The application itself is a set of math engine dlls (coated by a console app for debugging) that can perform optimization tasks. Theoretically, a number of parameters goes in, boils, steams and finally result is returned. All is good until I discovered that after several runs the application crashes. Soon enough it became apparent that optimization itself is not releasing memory and after consuming several gigs, it just dies.
First thought, there is some IDisposable type not collected in a some kind of a loop (which was quite likely). So I started ANTS Memory Profiler. The following screenshots shed much light on what was really happening. Let's start with the bytes in all managed heaps:

Blue: reserved free bytes, green - used bytes. There are 8 memory snapshots with the the first taken after a few seconds of app life and the last one taken after about around 5 minutes. Pretty much all manageable memory is under 4 megs all the time. No increasing in the large object heap:

Still the memory goes crazy:

It appears that the problem is with private bytes, which is unmanaged code. Here is what ANTS shows:

Due to the fact that managed code is interoperating with unmanaged, it appears .NET tries to run finalazers (by calling Dispose). However, there is a flaw in the unmanaged code and the call is not returned. This creates a block in the finalazer thread. And because there is only one thread for running finalazers, which is blocked, the memory is never released, nor any other finalazer can process afterwards.
A great tool to detect unmanaged memory leak is Debug Diagnostic Tool. It can show where and how much the app leaks. After analysing memory dump I found the method that leaks. I didn't have source codes of the library thus method names are not fully shown + I removed information that can identify the vendor.
Function details
Function ***!***::CConstants::operator=+454e1f
Allocation type Heap allocation(s)
Heap handle 0x035f0000
Allocation Count 4505839 allocation(s)
Allocation Size 147.00 MBytes
Leak Probability 94%
Moreover DebugDiag shows the callstack:
Call stack sample 1
Address 0x1345c008
Allocation Time 00:05:15 since tracking started
Allocation Size 96 Bytes
Function Source Destination
***!*******::CConstants::operator=+454e1f
***!*******::CConstants::operator=+454e1f
***!*******::C***::Simulate+26d
***!*******::Internal::***Exception_ErrorDescriptionByID+4fa 0xD4FB8155
***!*******::CStatistics::operator=+4c
***!*******::COptIIS::operator=+f6
0x37CC474
clr!IJWNOADThunkJumpTarget+17 0x931EA0
***!Ordinal17+f00
<Unloaded_***.dll>+c064
<Unloaded_***.dll>+c332
<Unloaded_***.dll>+c51f
<Unloaded_***.dll>+3458
***!*******::CConstants::operator=+5967b
***!*******::CConstants::operator=+598ce
ntdll!ZwQueryInformationProcess+c
***!*******::CConstants::operator=+454e1f
***!*******::CConstants::operator=+454e1f
***!*******::CConstants::operator=+454e1f
***!*******::CConstants::operator=+454e1f
<Unloaded_***.dll>+3d0c3
<Unloaded_***.dll>+3d0d9
<Unloaded_***.dll>+3e00e
<Unloaded_***.dll>+1389
<Unloaded_***.dll>+267d
***!*******::CStatistics::operator=+4c
0x37C574D
0x37FA917
clr!CallDescrWorker+33
clr!CallDescrWorkerWithHandler+8e clr!CallDescrWorker
clr!MethodDesc::CallDescr+194 clr!CallDescrWorkerWithHandler
clr!MethodDesc::CallTargetWorker+21 clr!MethodDesc::CallDescr
clr!MethodDescCallSite::Call+1c clr!MethodDesc::CallTargetWorker
clr!MethodDesc::GetSigFromMetadata+21
clr!operator delete[]+41
clr!operator delete[]+41
clr!AppDomain::SetFriendlyName+16c clr!operator delete[]
clr!CrstBase::AcquirePreempLock+33
clr!CrstBase::AcquirePreempLock+33
clr!EEStartupHelper+9a3
clr!EEStartupHelper+9a3
clr!EEStartup+52 clr!EEStartupHelper
mscoreei!_CorExeMain+38
mscoree!ShellShim__CorExeMain+99
mscoree!_CorExeMain_Exported+8 mscoree!ShellShim__CorExeMain
kernel32!BaseProcessStart+23
So the leak is found and software vendors were notified, hopefully the leak will be fixed soon.
If you enjoyed this post, make sure you subscribe to my RSS feed!
5569f71b-eec2-4b49-9466-082aafec4a06|0|.0
NuGet package manager is a free open source package management system that allows developers to add, remove and update references to 3rd party libraries in .NET projects. It also can update .config files to reflect changes in references. One usually needs to be connected to the internet, as NuGet is linked to Microsoft online centralized package storage. A package is a set of data and metadata files that are needed for 3rd party library or tool integration.
NuGet uses Powershell console and Microsoft Visual Studio 2010 (Powershell needs to be installed separately, here is the link).
Okay, that’s basic theory. Let’s start doing some work! As a sample, I will be adding references to a CHB.Container, which is a small Inversion of Control project that I am using within my solution. The base IoC container I will be using is Castle Windsor. This is due to a number of reasons that go beyond the topic of this post. So, theoretically, without NuGet I will be doing the following steps:
- Download the latest version of Castle Windsor from sourceforge
- Unzip the files
- Do the security checks
- Find libraries that target proper .NET
- Copy files to some resource folder in the solution
- In the CHB.Container project add references to Castle.Core.dll and Castle.Windsor.dll from location defined in step 5
Seems to be easy, erm? Let’s see how I can make a shortcut.
To kick off with NuGet I go to Tools > Extension Manager in MS VS 2010. Then, I search for NuGet in the online gallery, download and install it. After the VS restart, I can begin useing the package manager.
So far so good. Now, let's add references to CHB.Container. I will perform these steps:
- Open Package Manager Console from View -> Other Windows
- Select CHB.Container as a default project
- Type install-package Castle.Windsor in the console window
Hint: IntelliSense can be used with TAB key. Try pressing TAB after install-package and see the whole list of available packages.
The output will look something like this:
PM > Install-Package Castle.Windsor
'Castle.Core (= 2.5.2)' not installed.
Attempting to retrieve dependency from source...
Done
Successfully installed 'Castle.Core 2.5.2'
Successfully installed 'Castle.Windsor 2.5.2'
Successfully added 'Castle.Core 2.5.2' to CHB.Container
Successfully added 'Castle.Windsor 2.5.2' to CHB.Container
All the needed references were added and the project is ready to rock!
Hint: to uninstall the package use uninstall-package command.
Lastly, a few considerations:
- Screencasts can be found in the Getting Started section on the official website.
- NuGet downloads the whole package, whereas just a few files are used. In my sample solution I am using NHibernate, FluentNHibernate, log4net and Castle Windsor and the total package folder weight climbs just a few inches above 61 MB, which is, of course, a lot to be sent to a repository.
- It is a new project, do expect to catch some small bugs here and there
Summary
NuGet is a package management system that simplifies developer’s life. Even though it has some drawbacks, it really saves much time. Use it!
If you enjoyed this post, make sure you subscribe to my RSS feed!
1e8cb564-4387-4e71-8138-eba0dc28cb75|0|.0