Monday, December 03, 2007

Cruise Control.Net cannot find NUnit

I am setting up a continuous integration server for a project that I am working on. I had an interesting problem, my nant script was building without a problem, but when I ran it under cc.net, it failed. It turns out that NUnit was registered only under my user account, whereas the cc.net service was running under the system account and didn't have knowledge of some environment variables. The fix was go to the services and right click on the cc.net service, change to log on as option to the user that has access to those environment variables, then restart the service ... simple enough

Friday, October 26, 2007

HttpModule

Something that I didn't know even exists, not that I see myself using it ever, but still one of those nice things to know:here

Monday, October 08, 2007

Web Startups

One of the best articles I have read recently:
http://www.paulgraham.com/webstartups.html

Sunday, October 07, 2007

Reflection.Emit

OK, I was interested in generating code at runtime and compiling it. Not that I really need it, I was just curious how the whole thing works.
Here is a good article on MSDN that gives a pretty decent example.
And while the concept looks pretty cool, it doesn't look like(and I sure am glad for that) that I will have a need to use this anytime soon. Maybe if I was in the business of code generation and/or compiler business I would find a good use for it, but for now I think it just is rather complicated to find a good use for it.

Reflection

OK, for this example, I would need two projects, one is a c# console application and the other one is a c# DLL project.
The DLL will be called TestLateBinding and the Console App will be called Reflection.
Here are the classes that each one has:
DLL:
using System;
using System.Collections.Generic;
using System.Text;

namespace TestLateBinding
{
class TestClass
{
private void OnlyMethod()
{
Console.WriteLine("Printing from within OnlyMethod\n");
}
}
}

And the console application has Program.cs and TestDataType.

Here are the contents of TestDataType:

using System;
using System.Collections.Generic;
using System.Text;

namespace Reflection
{
public class TestDataType
{

public void print()
{
Console.WriteLine("Printing shit\n");
}

}

}

Here are the contents of Program.cs:

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;

namespace Reflection
{
class Program
{
static void Main(string[] args)
{
TestDataType testObject = new TestDataType();
Type objectType = testObject.GetType();

ConstructorInfo[] info = objectType.GetConstructors();
MethodInfo[] methods = objectType.GetMethods();

// get all the constructors
Console.WriteLine("Constructors:");
foreach (ConstructorInfo cf in info)
{
Console.WriteLine(cf);
}

Console.WriteLine();
// get all the methods
Console.WriteLine("Methods:");
foreach (MethodInfo mf in methods)
{
Console.WriteLine(mf);
}

MethodInfo info2 = objectType.GetMethod("print");
Console.WriteLine("Calling print:\n");
object[] parms = new object[1];
parms[0] = "d";
info2.Invoke(testObject, null);


Console.WriteLine("Testing Late Binding:\n");
Assembly a = Assembly.Load("TestLateBinding");
Console.WriteLine("Types in TestLateBinding assembly:\n");
foreach (Type t in a.GetTypes())
{
Console.WriteLine(t.Name);
if (t.Name.Equals("TestClass"))
{
MethodInfo info5 = t.GetMethod("OnlyMethod", BindingFlags.NonPublic | BindingFlags.Instance);

Object o = Activator.CreateInstance(t);
info5.Invoke(o, null);
}
}
Console.ReadLine();
}
}
}

Now in order for us to continue, you will have to build and then copy the TestLateBinding.dll from the TestLateBinding Debug Folder into the Debug folder of the console app, so we can access the members from the dll during runtime, without using compile time knowledge of the code in the library, in essence, without doing a reference to the library.

OK, so now to the code, in order for us to use reflection, we need the
using System.Reflection; reference.
So in these two lines:
TestDataType testObject = new TestDataType();
Type objectType = testObject.GetType();
I declare a new object of type TestDataType and then I use the objects, GetType method to assign it to the object objectType of type Type.
I know this is a silly example, but you can see how it would be helpful, if you were able to access methods, constructors and other information at runtime, so this is what I am trying to show here.
The next two lines get all constructors and all methods from the object using reflection:

ConstructorInfo[] info = objectType.GetConstructors();
MethodInfo[] methods = objectType.GetMethods();

I then print them out to the console. And I am also getting the method information for a particular method, in this case, print:

MethodInfo info2 = objectType.GetMethod("print");

In this case, the method does not accept any parameters, so I am just calling it:

info2.Invoke(testObject, null); However, if it required parameters, I could have done it so:
object[] parms = new object[1];
parms[0] = "d";
info2.Invoke(testObject, parms);
Note the above is actually quite silly, but it addresses the point that I am trying to make.

Next we can call an external assembly by using the Load method from the Assembly class:

Assembly a = Assembly.Load("TestLateBinding");

where "TestLateBinding" is the name of the assembly(our dll)

Then I am getting all types in the assembly and calling a private method from within the class:

foreach (Type t in a.GetTypes())
{
Console.WriteLine(t.Name);
if (t.Name.Equals("TestClass"))
{
MethodInfo info5 = t.GetMethod("OnlyMethod", BindingFlags.NonPublic | BindingFlags.Instance);

Object o = Activator.CreateInstance(t);
info5.Invoke(o, null);
}
}
Note the use of BindingFlags.NonPublic | BindingFlags.Instance, without those flags, the private method will not be reflected, I don;t know why, don't ask me.
If the method is public, you will not need to pass any flags.

I hope this helped

Developer Tools

http://www.windevpowertools.com/ToolList/Tag/Chapter%2013

Friday, October 05, 2007

SAMBA setup

yum install samba system-config-samba samba-client samba-common samba-swat smbldap-tools

SAMBA config file:

# This is the main Samba configuration file. You should read the
# smb.conf(5) manual page in order to understand the options listed
# here. Samba has a huge number of configurable options (perhaps too
# many!) most of which are not shown in this example
#
# For a step to step guide on installing, configuring and using samba,
# read the Samba-HOWTO-Collection. This may be obtained from:
# http://www.samba.org/samba/docs/Samba-HOWTO-Collection.pdf
#
# Many working examples of smb.conf files can be found in the
# Samba-Guide which is generated daily and can be downloaded from:
# http://www.samba.org/samba/docs/Samba-Guide.pdf
#
# Any line which starts with a ; (semi-colon) or a # (hash)
# is a comment and is ignored. In this example we will use a #
# for commentry and a ; for parts of the config file that you
# may wish to enable
#
# NOTE: Whenever you modify this file you should run the command "testparm"
# to check that you have not made any basic syntactic errors.
#
#======================= Global Settings =====================================
[global]

# workgroup = NT-Domain-Name or Workgroup-Name, eg: MIDEARTH
workgroup = SAFE

# server string is the equivalent of the NT Description field
server string = DigiData Digital SAFE

# Security mode. Defines in which mode Samba will operate. Possible
# values are share, user, server, domain and ads. Most people will want
# user level security. See the Samba-HOWTO-Collection for details.
security = share

# This option is important for security. It allows you to restrict
# connections to machines which are on your local network. The
# following example restricts access to two C class networks and
# the "loopback" interface. For more examples of the syntax see
# the smb.conf man page
; hosts allow = 192.168.1. 192.168.2. 127.

# Uncomment this if you want a guest account, you must add this to /etc/passwd
# otherwise the user "nobody" is used
; guest account = pcguest

# this tells Samba to use a separate log file for each machine
# that connects
log file = /var/log/samba/%m.log

# Put a capping on the size of the log files (in Kb).
max log size = 50

# Use password server option only with security = server
# The argument list may include:
# password server = My_PDC_Name [My_BDC_Name] [My_Next_BDC_Name]
# or to auto-locate the domain controller/s
# password server = *
; password server =

# Use the realm option only with security = ads
# Specifies the Active Directory realm the host is part of
; realm = MY_REALM

# Backend to store user information in. New installations should
# use either tdbsam or ldapsam. smbpasswd is available for backwards
# compatibility. tdbsam requires no further configuration.
; passdb backend = tdbsam

# Using the following line enables you to customise your configuration
# on a per machine basis. The %m gets replaced with the netbios name
# of the machine that is connecting.
# Note: Consider carefully the location in the configuration file of
# this line. The included file is read at that point.
; include = /usr/local/samba/lib/smb.conf.%m

# Configure Samba to use multiple interfaces
# If you have multiple network interfaces then you must list them
# here. See the man page for details.
; interfaces = 192.168.12.2/24 192.168.13.2/24

# Browser Control Options:
# set local master to no if you don't want Samba to become a master
# browser on your network. Otherwise the normal election rules apply
; local master = no

# OS Level determines the precedence of this server in master browser
# elections. The default value should be reasonable
; os level = 33

# Domain Master specifies Samba to be the Domain Master Browser. This
# allows Samba to collate browse lists between subnets. Don't use this
# if you already have a Windows NT domain controller doing this job
; domain master = yes

# Preferred Master causes Samba to force a local browser election on startup
# and gives it a slightly higher chance of winning the election
; preferred master = yes

# Enable this if you want Samba to be a domain logon server for
# Windows95 workstations.
; domain logons = yes

# if you enable domain logons then you may want a per-machine or
# per user logon script
# run a specific logon batch file per workstation (machine)
; logon script = %m.bat
# run a specific logon batch file per username
; logon script = %U.bat

# Where to store roving profiles (only for Win95 and WinNT)
# %L substitutes for this servers netbios name, %U is username
# You must uncomment the [Profiles] share below
; logon path = \\%L\Profiles\%U

# Windows Internet Name Serving Support Section:
# WINS Support - Tells the NMBD component of Samba to enable it's WINS Server
; wins support = yes

# WINS Server - Tells the NMBD components of Samba to be a WINS Client
# Note: Samba can be either a WINS Server, or a WINS Client, but NOT both
; wins server = w.x.y.z

# WINS Proxy - Tells Samba to answer name resolution queries on
# behalf of a non WINS capable client, for this to work there must be
# at least one WINS Server on the network. The default is NO.
; wins proxy = yes

# DNS Proxy - tells Samba whether or not to try to resolve NetBIOS names
# via DNS nslookups. The default is NO.
dns proxy = no

# These scripts are used on a domain controller or stand-alone
# machine to add or delete corresponding unix accounts
; add user script = /usr/sbin/useradd %u
; add group script = /usr/sbin/groupadd %g
; add machine script = /usr/sbin/adduser -n -g machines -c Machine -d /dev/null -s /bin/false %u
; delete user script = /usr/sbin/userdel %u
; delete user from group script = /usr/sbin/deluser %u %g
; delete group script = /usr/sbin/groupdel %g


#============================ Share Definitions ==============================
[homes]
comment = Home Directories
browseable = no
writable = yes

# Un-comment the following and create the netlogon directory for Domain Logons
; [netlogon]
; comment = Network Logon Service
; path = /usr/local/samba/lib/netlogon
; guest ok = yes
; writable = no
; share modes = no


# Un-comment the following to provide a specific roving profile share
# the default is to use the user's home directory
;[Profiles]
; path = /usr/local/samba/profiles
; browseable = no
; guest ok = yes

# This one is useful for people to share files
;[tmp]
; comment = Temporary file space
; path = /tmp
; read only = no
; public = yes

# A publicly accessible directory, but read only, except for people in
# the "staff" group
;[public]
; comment = Public Stuff
; path = /home/samba
; public = yes
; writable = yes
; printable = no
; write list = @staff

# Other examples.
#
# A private directory, usable only by fred. Note that fred requires write
# access to the directory.
;[fredsdir]
; comment = Fred's Service
; path = /usr/somewhere/private
; valid users = fred
; public = no
; writable = yes
; printable = no

# a service which has a different directory for each machine that connects
# this allows you to tailor configurations to incoming machines. You could
# also use the %U option to tailor it by user name.
# The %m gets replaced with the machine name that is connecting.
;[pchome]
; comment = PC Directories
; path = /usr/pc/%m
; public = no
; writable = yes

[public]
comment = Your Sync Zone
path = /safe/sync
public = yes
only guest = yes
writable = yes

[www]
comment = Web Root
path = /var/www/html
public = yes
writable = yes
create mask = 0775

# The following two entries demonstrate how to share a directory so that two
# users can place files there that will be owned by the specific users. In this
# setup, the directory should be writable by both users and should have the
# sticky bit set on it to prevent abuse. Obviously this could be extended to
# as many users as required.
;[myshare]
; comment = Mary's and Fred's stuff
; path = /usr/somewhere/shared
; valid users = mary fred
; public = no
; writable = yes
; printable = no
; create mask = 0765



make sure Linux SE allows samba to write:
setsebool -P smbd_disable_trans 1

also make sure that file system permissions allow write access

Also make sure that we have the firewall allowing samba :
run /usr/sbin/system-config-security-level-tui to open up the port for swat (901)

Other tips:
restaring samba:
/etc/init.d/smb restart
Also, it is a good idea to check for open ports in /etc/services:
netbios-ns 137/tcp # NETBIOS Name Service
netbios-ns 137/udp
netbios-dgm 138/tcp # NETBIOS Datagram Service
netbios-dgm 138/udp
netbios-ssn 139/tcp # NETBIOS session service
netbios-ssn 139/udp

and 445 add the lines if they are missing

Also, we need to add users to samba(these need to also be available as linux users)
smbpasswd -a
Now, you should be able to access the share (make sure you login under the correct name in windows)

Things SQL

http://mashable.com/2007/10/03/sql-toolbox/

Thursday, October 04, 2007

Command to start SVN as service on windows

sc create svnserve binpath= "\"C:\Program Files\Subversion\bin\svnserve.exe\" --service -r \"C:\projects\svn"" displayname= "Subversion Server" depend= Tcpip start= auto

Subversion Global Ignore Pattern

I always forget this, so I am putting it here to have a record of it;

*/bin */obj *.bak *.*scc *.user *.suo *.webinfo bin
obj *.dll *.pdb*.exe

Wednesday, September 26, 2007

Client Callbacks in ASP.NET 2.0

OK, I was looking for a way to call code behind from javascript and a ASP.NET 2.0 Web Page. I know, I know... I am a little behind on the whole AJAX thing, but I am trying to catch up quickly. Believe it or not, I am also just now learning javascript. It is interesting because I have been programming for over 5-6 years now and I have been messing with computers and web design since roughly 1998 and all this time, I never learned javascript. You can see how amusing I was finding all the comments all over the internet that javascript is very easy to learn, especially compared to real programming languages. Anywho, I naturally wanted to learn how to call my C# code from java script and readthis awesome article on the code project.
I find it much better than this one from MSDN

I am going to paste the article here, for the sake of me finding it later when I search for it, in case the original web page moves.

Introduction
Client Call back is an interesting feature of ASP.NET which allows call of server code from Client side Java Script through XmlHTTP so called AJAX in this article I will discuss client callback first and lets will compare its benefits with the AJAX.



Using AJAX in ASP.NET 1.1 is quite tedious task first you need to copy the AJAX dll into the bin folder than register it as an HttpHandler in Web.Config, things not finished here because for every page which your planning to use AJAX needs to be register as well by calling AJAXUtility.RegisterForAJAXType (this.GetType ()) and then comes the writing of actual client and server side code.

In ASP.NET 2.0 Runtime takes this responsibility of registering http handler, page types etc and simplified the process of client script callbacks so in this article I will discuss the details of it.

ASP.NET introduce the new interface named ICallBackEventHandler, page needs to implement this interface in order to support client call backs. It has two methods

* RaiseCallbackEvent: Processes a callback event that targets a control, this method is the execution point when server code is call from client script,
* GetCallbackResult: Returns the results of a callback event that targets a control, the result is usually returned by RaiseCallBackEvent and stored in some class member.

Client Call Backs in Action
Lets take a look at very basic example of Client Callbacks in which clicking of client side button triggers server code which returns a simple text message for display in the textbox at client side

Implementing ICallbackEventHandler



   1:  public partial class _Default :

   2:   

   3:  System.Web.UI.Page, ICallbackEventHandler  

   4:   

   5:  {

   6:   

   7:      string callbackResult;

   8:   

   9:      protected void Page_Load(object sender, EventArgs e)

  10:   

  11:      {

  12:   

  13:          // will discuss this later

  14:   

  15:      }

  16:   

  17:   

  18:   

  19:      public void RaiseCallbackEvent(string eventArgument)

  20:   

  21:      {

  22:   

  23:          // perform some real operation

  24:   

  25:          callbackResult = "DotNET Rocks!";

  26:   

  27:      }

  28:   

  29:    

  30:   

  31:      public string GetCallbackResult()

  32:   

  33:      {

  34:   

  35:          return callbackResult;

  36:   

  37:      }

  38:   

  39:  }



The above code is quite simple RaiseCallbackEvent performs some operation and store result in callbackresult variable which is returned by GetCallbackResult method. Now the next step is to have some JavaScript code which till trigger this callback.



   1:  <script type="text/javascript">

   2:   

   3:      function GetMessageFromServer()

   4:   

   5:      {

   6:   

   7:          UseCallBack();

   8:   

   9:      }

  10:   

  11:     

  12:   

  13:      function JSCallback(TextBox1, context)

  14:   

  15:      {

  16:   

  17:          // when callback finishes execution this method will called

  18:   

  19:          document.forms[0].TextBox1.value = TextBox1;

  20:   

  21:      }

  22:   

  23:  </script>



GetMessageFromServer will trigger the server code using UseCallback method this is dynamic method generated from the code behind more on this later. JSCallback is the client method which will call when server callback completes its execution

So what I did here is just copy the server message in the textbox.



Click of Following html button will invoke the method



   1:  <input type="button" id="Button1" runat="server" value="Get Message" onclick="GetMessageFromServer()"/>



Now comes the final and most important step of using client callbacks this step is actually responsible for emitting the java script which will call the Framework method so make actual XmlHttp, normally this code fragment comes in Page_Load event i.e.



   1:  protected void Page_Load(object sender, EventArgs e)

   2:   

   3:  {

   4:   

   5:      // get reference of call back method named JSCallback

   6:   

   7:      string cbref = Page.ClientScript.GetCallbackEventReference(this, "arg", "JSCallback", "context");

   8:   

   9:   

  10:   

  11:      // Generate JS method trigger callback

  12:   

  13:      string cbScr = string.Format("function UseCallBack(arg, context) {{ {0}; }} ", cbref);

  14:   

  15:   

  16:   

  17:      Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "UseCallBack", cbScr, true);

  18:   

  19:  }

  20:   

  21:   

  22:   

  23:  The above C# code generates the following Java script at run time

  24:   

  25:  function UseCallBack(arg, context)

  26:   

  27:  {

  28:   

  29:      WebForm_DoCallback('__Page',arg,JSCallback,context,null,false);

  30:   

  31:  }



This is actually the calls the XmlHttp behind the scene which will ultimately result callback of server code. So that’s it after server code finishes its execution Framework will call the specified Java script method to notify the completion of callback in this case which is function JSCallback(TextBox1, context).


Internals of Client Callbacks

You might be wondering where XmlHttp object is and how framework calls the server callback behind the scene, well of you look at the generated html for the page you will see an interesting script declaration i.e.



   1:  <script src="/&lt;AppName>/WebResource.axd?d=v…&amp;t=63…0" type="text/javascript"></script>



If you open the above URL in browser you will see the complete definition of library functions and objects responsible for server calls and client notifications.



Another interesting thing in the previous code was ClientScript property of page class this property represents the instance of ClientScriptManager class which contains all the concerns of client side scripting and contain lots of methods useful in client side scripting. GetCallbackEventReference is one of the methods which returns reference to a client-side function that, when invoked, initiates a client call back to a server-side event.



Page Cycle in Client Callback Scripts

One of the interesting and unique feature of client callback script is that when calling server callback the aspx page loads into memory and executes normal page cycle events such as Page_Init, Page_Load etc. this is where client callback runs away from AJAX because in AJAX aspx page is not loaded in memory so you cannot access viewstate, page controls but this is not the case in client callbacks.



However in client callbacks partial page cycle executes and events such as Pre_Render, Render doesn’t fire and it’s logical enough because we don’t want the complete page refresh. Following diagrams will describe the page life cycles in both scenarios

To add to the above, he talks about passing parameters to the callback and how you do it, but is not very clear. You can pass only one parameter to the server and it is only a script data type. That means that you could concatenate the parameters in a comma delimited string and just parse in the code behind. Pretty cool I would say...

Friday, September 21, 2007

Data Layer testing

Data layer testing has been an issue for me for quite some time. All tests need to be atomic, that is a fundamental rule when it comes to testing and is especially important and difficult to achieve in the database testing. Some things that come to mind are Identity fields. Every time you insert a record, the database gets changed, even if you delete the record manually at the end of the test. Also cleaning up manually a distributed database could be quite hectic, same applies when you need to insert a lot of data to efficiently test your functionality (consider a tree-like structure that is stored in SQL). The best way to solve all of the above mentioned problems and still ensure atomicity is transactions. Here is more on the topic:
COM+ 1.5 Transactions
The article uses Enterprise Services.
One waring though, the tests will randomly fail if your testing code has a transaction that is supposed to fail (Exceptions, boundary cases, faulty input ... etc) When you say Transaction.Rollback() which one is the one that gets rolled back?
I have spent numerous hours trying to figure out randomly failing unit tests.
If you have had code that randomly fails and passes under the same conditions, you know very well this is not a very pleasant situation.

So keeping all that in mind, the article is pretty good.

Sunday, August 19, 2007

Saturday, August 18, 2007

Black Metal

I have been listening to black metal for over 11 years now and I am still amazed by the richness of the genre. Sadly, there are very few new bands(if any) worth mentioning.
But to me black metal is still that hidden treasure that very few people tend to enjoy.
It is a safe haven from hip hop, pop, country, chalga and all the shit that surrounds us lately. I don't think there will ever be anything replacing the sound of Dimmu Borgir, Dissection, Burzum, Emperor, Mayhem, Immortal, Darkthrone, Old Sieben Burgen. Also other extreme bands like Amorphis (Up to Elegy), Dragonlord, newer Nordafrost. It is too sad that kids nowadays are too much into shitty crap like the junk that surrounds us. Damn I feel old and I am only 25. I remember when I used to roam the streets with soldier boots, black clothes and chains around my waist listening to enthroned or enslaved, or the latest dimmu. Those were sweet times. I wonder if things will ever be the same. Black metal has never been big in the US, but it's getting weaker even in Europe; how sad. I remember the days when there were true metalheads, willing to kill and die to protect the name of their favourite band. Oh how sad the wold has become. I can count the true metalheads that I have met in my life on the fingers of one of my hands. One of them is Mexican, one American and one Bulgarian and that is not counting me.
May the god of war bless us all,

one old and sad metalhead.

Friday, August 17, 2007

Date Parse Methods

DateTime.Parse() and SqlDateTime.Parse() methods are really cool and easy ways to convert a string with datetime format to a DateTime datatype. I wish I knew this earlier, no more manual parsing for me. :-)

Thursday, August 16, 2007

NUnit and App.config files

I was having problems getting NUnit to recognize and use the correct config files for the projects that I was running.
There were several reasons why I was getting runtime errors. Here is a list of them:

1) NUnit is looking for a config file with the same name as the assembly. - renamed the config to {assemblyname}.config
2) VS 2005 is supposed to copy over the App.config to bin/Debug(Release) at compile time and rename it to {assemblyname}.config, mine was failing to do that for some reason. - manual copy worked. Postbuild event should work too.
3) Nunit's project name has to be the same as the assembly name i.e. Project1.nunit won't cut it; it has to be named {assemblyname}.nunit- rename the project name.

After all of the above criteria are met, NUnit should be able to run tests on projects that have config files. I think this problem comes up only with dlls.

Wednesday, August 15, 2007

Using external config files for enterprise library configuration

http://blogs.msdn.com/tomholl/archive/2006/04/02/entlib2externalconfig.aspx

Tuesday, August 14, 2007

Testing Private methods w Nunit

Sometimes we run into the problem of testing private methods that are not visible from a Nunit assembly. One way that could be accomplished, without breaking the data encapsulation is to make the method in questions internal and add the following two lines to your code:


using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("PutYourTestAssemblyNameHere")]

now it will work

Friday, August 03, 2007

Enterprise Library Assemblies are Strongly Named

Alright how does that affect you? Well... in a very simple way, look at these two configuration files that are taken from Enterprise Library 2.0.0.0 and 3.1.0.0

2.0.0.0:

<text>
<configuration>
<configsections>
<section name="securityCryptographyConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Configuration.CryptographySettings, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null">
<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null">
</section>
<securitycryptographyconfiguration defaulthashinstance="PasswordHasher">
<hashproviders>
<add algorithmtype="System.Security.Cryptography.SHA1Managed, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" saltenabled="true" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" name="PasswordHasher">
</add>
</hashproviders>
<enterpriselibrary.configurationsource selectedsource="System Configuration Source">
<sources>
<add name="System Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SystemConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null">
<add name="userStore" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=2.0.0.0, Culture=neutral, PublicKeyToken=null" filepath="..\..\UserStore.config">
</add>
</add>
</sources>
</enterpriselibrary.configurationsource></securitycryptographyconfiguration></section></configsections></configuration>

3.1.0.0:


<configuration>
<configsections>
<section name="securityCryptographyConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.Configuration.CryptographySettings, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<section name="enterpriseLibrary.ConfigurationSource" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ConfigurationSourceSection, Microsoft.Practices.EnterpriseLibrary.Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
</section>
<securitycryptographyconfiguration defaulthashinstance="PasswordHasher">
<hashproviders>
<add algorithmtype="System.Security.Cryptography.SHA1Managed, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" saltenabled="true" type="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.HashAlgorithmProvider, Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" name="PasswordHasher">
</add>
</hashproviders>
<enterpriselibrary.configurationsource selectedsource="System Configuration Source">
<sources>
<add name="System Configuration Source" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.SystemConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<add name="userStore" type="Microsoft.Practices.EnterpriseLibrary.Common.Configuration.FileConfigurationSource, Microsoft.Practices.EnterpriseLibrary.Common, Version=3.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" filepath="..\..\UserStore.config">
</add>
</add>
</sources>
</enterpriselibrary.configurationsource></securitycryptographyconfiguration></section></configsections></configuration>

Do you see the difference? Yes, the config files are referring to different version of the Enterprise Library and also the 3.1.1.0 version has a public key token.

The reason for that is because the first config file is taken from the Enterprise Library hands on lab and has no public token, because it's supposed to easily work on any machine; however it is still looking for version 2.0.0.0. So whenever you try to build the solution from the hands on labs, you would get some weird exception and usually when you catch the inner exception, you would be able to see the actual problem. In my case, Visual Studio was unable to load Microsoft.Practices.EnterpriseLibrary.Common, but for enterprise library 2.0.0.0. I don't have that animal installed on my machine, so I was getting the error.

It won't even help if you try to open the App.config file with the Enterprise Library Configuration Tool, as it will try to open it with the old version of the ent. Lib assemblies bleh...
The only solution is to get the token and version from another config file and manually replace each entry.

Voila problem solved...

Indenting Partial Classes in VS

I am not going to go over something that is explained pretty well somewhere else. Nevertheless, I would like to flag the issue here. From experience I know that you don't always put the Dependent Upon tag where you would think of, but with trial and error anyone could find the right place.
Read the posted link for more info.

Enterprise Library Performance counters

I decided to get back to blogging, not so much because I am thinking that people will actually read my junk, but more so because I caught myself quickly forgetting things that I have done and need to relearn how to do them again.
My first post will be about using performance counters with Microsoft Enterprise Library 3.1 and Windows Vista. In order for you(or me) to be able to follow the example I will post here, you will have to have Enterprise Library 3.0 installed. You can download it here

After installing, make sure that you run the install instrumentation bat file with administrator privileges. You can do so by going to start->all programs->Microsoft patterns and practices->Enterprise Library then right click on Install Instrumentation and select Run as Administrator.



Now you are ready to use performance counters with your application.

Next step is to actually write your performance counter. I used Chris Burrows' .Net blog post as a basis for accomplishing this, but ran into a few problems that I feel should be documented. The code I will post here is identical to the one on his post, but I will add a few additional comments.

So let's start by creating a new Visual Studio Console Application project and naming it SamplePerformanceCounter.

Add a class to your solution called SimplestPerformanceClass and paste the following code in it:

using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Common.Instrumentation;
using System.Diagnostics;


namespace SamplePerformanceCounter
{
[HasInstallableResources]
[PerformanceCountersDefinition(PerformanceCategory, "SampleInstrumentationCounterHelp")]
public class SimplestPerformanceClass
{
private const string PerformanceCategory = "Simplest Performance Category";

[PerformanceCounter("Operations Started/sec", "OperationStartedHelpResource", PerformanceCounterType.RateOfCountsPerSecond32)]

private EnterpriseLibraryPerformanceCounter _operationStarted = new EnterpriseLibraryPerformanceCounter(PerformanceCategory, "Operations Started/sec");

public void OperationStarted()
{
_operationStarted.Increment();

}

}
}


Also add a partial class called ProjectInstaller.cs with the following code:

using System.ComponentModel;
using System.Configuration.Install;
using System.Management.Instrumentation;
using Microsoft.Practices.EnterpriseLibrary.Common.Instrumentation;
using System;
using System.Management;

namespace SamplePerformanceCounter
{
///

/// Let the system know that the InstallUtil.exe tool will be run against this assembly
///

[RunInstaller(true)]
public partial class ProjectInstaller :System.Management.Instrumentation.DefaultManagementProjectInstaller
{
///
/// Represents the installer for the instrumentation events. Not intended for direct use.
///


public ProjectInstaller()
{
Installers.Add(new ReflectionInstaller());
}
}



}



Here is one place that personally got me here, namely this line:
public partial class ProjectInstaller :System.Management.Instrumentation.DefaultManagementProjectInstaller

I had the System.Management.Instrumentation, System.Configuration.Install and Microsoft.Enterprise.Practices.EnterpriseLibrary.Common assemblies referenced in my project, and I thought everything should work fine. However Visual Studio was finding only System.Management.Instrumentation.DefaultManagementInstaller, so when I was trying to install my assembly using installutils, things didn't work right. It turns out that I had to reference System.Management as well, despite the fact that that class resides in System.Management.Instrumentation.
After getting that done, I added the following code to Program.cs:

using System;
using System.Collections.Generic;
using System.Text;

namespace SamplePerformanceCounter
{
class Program
{
static void Main(string[] args)
{
SimplestPerformanceClass performance = new SimplestPerformanceClass();

for (int i = 0; i < 1000000; i++)
{
performance.OperationStarted();
}
}
}
}


and compiled my solution.

Now is a good time to ensure that all the enterprise library default performance counters are added to perfmon. you can do so by calling the performance and reliability tool from Administrative tools, or just typing perfmon in Start->Run.

After doing that, you will see this:



You can click on the performance monitor under the monitoring tools folder and select the green cross at the top of the window and you should be presented the "Add Counters" screen. If you scroll the list, you should be able to see Enterprise Library counters, provided you installed instrumentation correctly. If you don't see anything ent. lib. related stuff that means you need to go back and figure out what went wrong with the install. Most likely you had permission problems and will have to run the script again with admin privileges.
So now that we have our solution complete and we have ensured that the ent. lib. instrumentation stuff is installed correctly, we will have to install our process counters with installutil.
Start the visual studio command prompt that you can find under Visual Studio 2005-> command tools. Make sure that you start it with admin privileges and navigate to your default project directory, then navigate to your bin/Debug folder and execute
installutil SamplePerformanceCounter.exe.
Now when you go back to the add counters screen in perfmon, you should see Simplest Performance Category as an option


Go ahead and open up the category by clicking the little triangular thingy to the right of it and select the text that will show up. It's something like Operations/sec. Then click on add to bring it to the right side of the split screen and select OK. If you are unable to see it under your graph, you will have to add a Thread.Sleep method in order to have instance of the application running, while you add the category. Once you have it added to your monitor, you can go back and remove the Thread.Sleep call. You should be able to see something similar after you have done all that:



I definitely think that Microsoft could have done a better job addressing performance counters in the enterprise library considering how little is the documentation on the web. I also think that Microsoft could do a much better job at documenting the enterprise library, considering that the enterprise library hands on labs are not detailed enough, the documentation on MSDN is virtually non-existent and a developer has to rely solely on the community out there for help.
After all this is not a few month old project, but some years now.

Happy programming.

P.S. Almost forgot, You will have to add an App.config file to your solution that has instrumentation specified in it. Here is how you can do that:

Open the Enterprise Library Configuration tool by going to All Programs->Microsoft Patterns and Practices-> Ent. Lib. -> Enterprise Library Configuration tool.




Right Click on the blue cubes that say Ent. Lib. Configuration-> Add new application.

Now Right click on the Application Configuration Icon and add new Instrumentation block. Now select true for Performance counters enabled and save the newly created config file as App.config inside your project directory. Now all you have to do is go back to your project and add existing file, pointing to the newly created App.config and you are set.