Monday, December 1, 2008

MCTS: .Net Framework 2.0 Windows Application achieved!

Good evening everyone.

Today is indeed a special day for me, as I am going to have my first ever certification. I took the 70-526 Microsoft .NET Framework 2.0 – Windows-Based Client Development examination in the morning at the CTI Prometric Centre and I have passed with a score of 980 out of 1000.

I also completed the 70-536 Microsoft .NET Framework – Application Development Foundation examination last October (with a score of 947 out of 1000), so I am now a Microsoft Certified Technology Specialist: .NET Framework 2.0 Windows Applications.

Read more about the MCTS: .Net Framework 2.0 Windows Application here.

There are actually about 15,469 professionals worldwide with this certification, and working as a .NET developer for more than 2 years and spending a couple of months preparing for these two examinations, I am finally going to be one of them. Objective met!!!

Tuesday, November 25, 2008

Manually enable remote connections in SQL Server 2005

The default configuration of the SQL Server 2005 doesn't allow remote connections. Hence, the error message "An error has occurred while establishing a connection to the server. When connecting to SQL Server 2005, this failure may be caused by the fact that under the default settings SQL Server does not allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)" when creating a new SQL Server database or connecting to an existing database in Visual Studio 2005 (VS2005).


To manually enable remote connections on the SQL Server,

1. Open the SQL Server Surface Area Configuration through Start menu.


2. Next, select Surface Area Configuration for Services and Connections.

3. On the left panel, expand the SQL Server instance -> Database Engine -> Remote Connections. Then, on the right panel, select Local and remote connections - Using TCP/IP only.


4. Also, make sure that the SQL Server Browser service is running.


5. Finally, restart the SQL Server instance. This can be done in the Services list under Administrative Tools in Control Panel.

Friday, November 21, 2008

Build setup project and msi file using command-line

Command build the VS2005 deployment (or setup) project and create the msi file:

"C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exe" SOLUTIONNAME.sln /Build "Release" /project SETUPPROJECTNAME.vdproj /projectconfig "Release"

Friday, November 14, 2008

ArgumentException Column does not belong to table

When using ADO.Net, I got the following error:

Column does not belong to table . A simple fix will be to check if the column exists before accessing the column in the table. This can be done as follows:

if (row.Table.Columns.Contains(ColumnName))

{

// proceed here

}

Monday, October 27, 2008

Code Snippets: Monitor class for thread-safety

Code Snippets is an interesting in-built feature of Visual Studio 2005. Code snippets are normally used in the Code Editor by first typing a shortcut (short name or alias), and then pressing TAB key. The code snippet shortcut/alias will then expand into a programming construct. This can make writing program code quicker, easier and more reliable.

To use the code snippets, use any of the follwing ways:

1. Right click in Code Editor and select the Insert Code Snippet menu command,
2. Activate the code snippet list by typing CTRL + K followed by X.


The Code Snippets Manager, found under the Tools menu, allows us to manage code snippets (add/remove) that will be available to insert into the code. It can also be accessted by CTRL K, followed by B.


The code snippets are stored as XML in .snippet files, and any user-defined snippet can be easily imported through the Code Snippets Manager and used during coding.

As a example, I will write a code snippet in order to use the Monitor.Enter and Monitor.Exit methods for thread-safe code (as we already have the 'lock' code snippet in VS2005) as shown below:

try
{
    System.Threading.Monitor.Enter(obj);
 
    // do some work here
}
finally
{
    System.Threading.Monitor.Exit(obj);
}

>>> Create the code snippet and store it as monitor.xml

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
  <CodeSnippet Format="1.0.0">
    <Header>
      <Title>monitor</Title>
      <Shortcut>monitor</Shortcut>
      <Description>Code snippet to use Monitor class for thread-safety</Description>
      <Author>Ashvin Gunga</Author>
      <SnippetTypes>
        <SnippetType>Expansion</SnippetType>
      </SnippetTypes>
    </Header>
    <Snippet>
      <Declarations>
        <Literal>
          <ID>expression</ID>
          <ToolTip>Expression to evaluate</ToolTip>
          <Default>AnObject</Default>
        </Literal>
      </Declarations>
      <Code Language="csharp">
        <![CDATA[
          try
          {
          System.Threading.Monitor.Enter($expression$);
          //TODO: Enter your code here
          $selected$ $end$
          }
          finally
          {
          System.Threading.Monitor.Exit($expression$);
          }]]>
      </Code>
    </Snippet>
  </CodeSnippet>
</CodeSnippets>

>>> Use the Code Snippets Manager and import the monitor.snippet file under My Code Snippets


>>> Now, in the code, type monitor and press TAB. The monitor shortcut is expanded to:

try
{
    System.Threading.Monitor.Enter(AnObject);
 
    //TODO: Enter your code here
}
finally
{
    System.Threading.Monitor.Exit(AnObject);
}

Downloads
Visual Studio 2005 Code Snippets can be downloaded here.

Saturday, October 25, 2008

Load data from XML file into Crystal Reports

In this post, I will demonstrate how we can display data found in an XML file in a Crystal Report in C# using .NET Framework. It is easier to understand the whole thing when there is no need to write code for database (such as Oracle, Access or SQL) access or adapter or connection objects.

Pre-requisite: Crystal Reports installed on the machine, along with Visual Studio 2005.

1. The first thing is to create a new Windows Application (here I've named it XmlToCrystalReports) in VS2005.

2. I will add an Employees.xml file to the project, under a DATA folder. The xml file will contain data about employees.

Right click on the Windows Application in the Solution Explorer. Select Add -> Add New Item. Choose XML File in the Add New Item form, name it Employees.xml and select Add..


3. Populate the xml file with test data.
<?xml version="1.0" encoding="utf-8" ?>
<Employees>
  <Employee>
    <Id>1</Id>
    <Name>John</Name>
    <Position>Team Leader</Position>
    <Experience>6</Experience>
  </Employee>
  <Employee>
    <Id>2</Id>
    <Name>Frank</Name>
    <Position>Analyst Programmer</Position>
    <Experience>3</Experience>
  </Employee>
  <Employee>
    <Id>3</Id>
    <Name>Michael</Name>
    <Position>Senior Analyst Programmer</Position>
    <Experience>5</Experience>
  </Employee>
  <Employee>
    <Id>4</Id>
    <Name>Thomas</Name>
    <Position>Senior Analyst Programmer</Position>
    <Experience>4</Experience>
  </Employee>
  <Employee>
    <Id>5</Id>
    <Name>Alan</Name>
    <Position>Trainee Analyst Programmer</Position>
    <Experience>0.5</Experience>
  </Employee>
</Employees>

4. Next, I will add a Crystal Report to the project.

Right click on the Windows Application in the Solution Explorer. Select Add - Add New Item.


Choose Crystal Report, name it EmployeesReport.rpt, and select Add.


The Crystal Reports Gallery pops up. I will leave the default options and select OK.


The Standard Report Creation Wizard is shown, along with a list of available data sources. Under Project Data -> .NET Objects, double click on XmlToCrystalReports.MainForm.


The ADO.NET form is shown. Browse and select the Employees.xml file created earlier and choose Finish.


And we are back in the Standard Report Creation Wizard. The Employee table is now shown under the Available Data Sources tree. Select the Employee table, move it to the right under the Selected Tables tree and choose Next.


Now, we will need to select the appropriate fields to be displayed in the crystal report. So, move all the fields under the Fields to Display tree on the right and select Finish.


The EmployeesReport.rpt is added to the project and shown in the designer, with a pre-defined layout.


5. Format the crystal report to meet your needs (example, change font size, add title in header)


6. The Solution Explorer will now be as follows:


7. Now to view the report when the application runs, we will need to add a Crystal Report Viewer to the main form. The Crystal Report Viewer component is available in the Toolbox under Crystal Reports.



We can hide the Group Tree found on the left by setting the DisplayGroupTree to false in the Properties Window.


8. The last step is during form load, we will need to (1) load the XML file into a dataset, (2) create an EmployeesReport instance and set the data source to the dataset created, and (3) set the ReportSource of the crystal viewer to the instance of the EmployeesReport.

private void Form1_Load(object sender, EventArgs e)
{
    DataSet dsEmployees = new DataSet();
    dsEmployees.ReadXml(@"DATA\Employees.xml");
 
    EmployeesReport report = new EmployeesReport();
 
    report.SetDataSource(dsEmployees);
    crystalReportViewer1.ReportSource = report;
 
}

9. Run the application, and (if everything is ok) the Crystal Reports Viewer will display the employee displays found the the xml file.

Friday, October 24, 2008

Dotfuscate

Introduction
The Microsoft .NET compiler converts the C# source code into Microsoft Intermediate Language (MSIL). However, with the use of a good decompiler tool and a few mouse clicks, any person can revert this .NET compiled code to its original C# source code. Hence, we need to protect the source code, including the 'trade secrets and logic' from attackers, especially when distributing the libraries/executables to third parties. A viable solution is the use of an Obfuscation Tool such as the .NET Dotfuscator (or simply, Dotfuscator).

The definition of 'obfuscate' is 'to confuse' or 'to make obscure or unclear', and that's exactly what an obfuscator tool will do. The Obfuscator will apply behavior preserving transformations on the code so that the functionality is preserved but the readability or understandability of the code is drastically reduced. The aim is to confuse observers while giving a consistent behavior to the Runtime Environment.

Main strategies of an obsfuscator
Compaction
The entire application is analysed and unused members are identified and removed from the obfuscated assembly. This is called the Compaction process. The unused members include unused classes, methods, instance variables and design time metadata, just to name a few. For example, a common library may offer a lot of functionalities but only a few are used in the application. So, these unused methods can be safely removed. Compacted programs also tend to load faster and run using less memory.

Overload Induction
The obfuscator renames all program identifiers to small, meaningless names. The Overload Induction mechanism works by identifying colliding set of methods across inheritance hierarchies and renaming such sets according to some enumeration (e.g. the alphabet). This method determines all opportunities for name reuse and hence, you may find more than 30% of ALL methods renamed to a single letter 'a'. Another advantage is the final program size of the obfuscated code is reduced by approximately 10% as there is heavy reuse of identify names.

String Encryption
Another interesting feature is the implementation of the runtime decrypted string encryption. An encryption algorithm is applied to all string literals and constants so as to make reverse-engineering even harder. This is very useful to hide hardcoded SQL strings, usernames and passwords that may be found in the code. Also, a decryption algorithm is inserted in the obfuscated code and later called at runtime to get back the original string literals.

Control Flow obfuscation
Control Flow obfuscation is yet another strong form of code protection. Here the flow of the program is changed so that the link between the original code and the obfuscated code breaks. It also ensures that no bug is introduced. For example, a for loop statement may be transformed into a while loop, a switch statement may be converted to a nested if statement and go to statements and labels may be introduced, just to name a few. This in turn transform the neat logic and flows in the original source code into a 'spaghetti-like' code to confuse the readers and any reverse engineering tool.

Assembly Linking
Multiple input assemblies are also combined into one or more output assemblies.



PreEmptive Solutions Dotfuscator flavors
There are currently two different version of the Dotfuscator: Professional Edition and Community Edition. The Community Edition is an entry level obfuscator and is included in Visual Studio 2005 Pro. The Professional Edition provides superior protection to foil decompilation, size reduction to conserve memory and improve load times, incremental obfuscation to release patches, watermarking to track pirates and so on and so forth.

Simple Dotfuscator Demonstration
1. Create your project in VS2005. Here, I shall use a simple application that print numbers 1 to 100.
using System;
using System.Collections.Generic;
using System.Text;
 
namespace DotfuscateDemo
{
    class Program
    {
        private double unUsedDouble;
 
        /// <summary>
        /// Gets or sets the un used double.
        /// </summary>
        /// <value>The un used double.</value>
        public double UnUsedDouble
        {
            get { return unUsedDouble; }
            set { unUsedDouble = value; }
        }
 
        /// <summary>
        /// Main method
        /// </summary>
        /// <param name="args"></param>
        public static void Main(string[] args)
        {
            Print1ToN(100);
            Console.ReadLine();
        }
 
        /// <summary>
        /// Print1s to N.
        /// </summary>
        /// <param name="nValue">The n value.</param>
        private static void Print1ToN(int nValue)
        {
            for (int i = 1; i <= nValue; i++)
            {
                Console.WriteLine(i);
            }
        }
    }
}


2. Build your project to get the assemblies that needs to be dotfuscated.

3. In Visual Studio 2005, open the Dotfuscator Community Edition found under Tools menu.


4. On the 'Select Project Type' screen, select the 'Create New Project' option.


5. Now we are ready to dotfuscate the project asssembly.

Select the Input tab on the Dotfuscator main window.

Select the option 'Browse and add assemblies to list' (this is an open folder icon) and add the project assembly.


6. There are other features available in the different tabs on the window and many of them may also be disable if you using the Community Edition. To keep this example simple, I will go directly to the dotfuscation process.

7. Now its time to save the project using Save Project under File menu. The solution is saved as an xml file.

8. The final step is to kick off the obfuscation process. This is done by selecting the Build Project option (play icon).

9. Once the build is completed, a Build Statistics is shown giving summary details of the obfuscated code changes.


10. You can now find the dotfuscated assemblies in a folder named Dotfuscated at the location where you saved the project xml file.

Before obfuscation...
After obfuscation...
Worth noting facts about Dotfuscator
A command line interface is available and thus, makes it suitable for integration into scripting environments or automated build processes.

ASP.NET code behind assemblies can be obfuscated using the Dotfuscator.

Dotfuscator will solely work on the compiled .NET assemblies and the original source code is never affected.

Dotfuscator is not a profiler (a very common misconception!!!).

Dotfuscator supports the Microsoft .NET Compact Framework.

And finally ...
Last but not least, it is important to know that obfuscation (or even encryption) is not 100% protected and secure. The only aim is to make the reverse engineering process extremely time consuming and painful so that it's not worth the effort and hence, stopping any potential attacker.

References
Microsoft .NET Support Team Blog
Preemptive Solutions
The Dotfuscator Solution

Thursday, October 23, 2008

Hide ListView border in .NET Compact Framework

To disable (or hide) the border of a ListView control in .NET Compact Framework,

1. Declare the following PInvoke methods...

#region PInvoke Declarations

const int GWL_STYLE = -16;

const int WS_BORDER = 0x00800000;

const int SWP_NOSIZE = 0x1;

const int SWP_NOMOVE = 0x2;

const int SWP_FRAMECHANGED = 0x20;

 

[DllImport("coredll.dll")]

private static extern int GetWindowLong(IntPtr hWnd, int nIndex);

 

[DllImport("coredll.dll")]

private extern static void SetWindowLong(IntPtr hwnd, int nIndex, int dwNewLong);

 

[DllImport("coredll.dll")]

private static extern bool SetWindowPos(IntPtr hwnd, IntPtr hWndInsertAfter,

   int x, int y, int cx, int cy, int uflags);

#endregion



2. Write a ShowListViewBorder method...

/// <summary>

/// Shows the list view border.

/// </summary>

/// <param name="handle">The handle.</param>

/// <param name="showBorder">if set to <c>true</c> [show border].</param>

private void ShowListViewBorder(IntPtr handle, bool showBorder)

{

   int style = GetWindowLong(handle, GWL_STYLE);

   if (showBorder)

   {

        style |= WS_BORDER;

   }

   else

   {

        style &= ~WS_BORDER;

   }

   SetWindowLong(handle, GWL_STYLE, style);

   SetWindowPos(handle, IntPtr.Zero, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);

}



3. Call the ShowListViewBorder...

ShowListViewBorder(window.lvwDetails.Handle, false);

Sunday, October 5, 2008

'Beautify' C# source code in VS2005

Many times I have been asked whether it is possible to 'beautify' the C# source code in Visual Studio 2005. The answer is yes, we can.

In VS2005, the Format Document command found in the Edit -> Advanced Menu is available. The keyboard shortcut is:

Ctrl-k, Ctrl-d

(i.e. press ctrl, k and d keys simultaneously)

Before Format Document command...
public class Divider
{
public static double Divide(int divident, int divisor)
{
try{return divident / divisor;}
catch (Exception ex){
throw ex;
}
}
 
public static void Main() { try
{Divider.Divide(30, 0);}
catch (Exception ex)
{Debug.WriteLine(ex.StackTrace);
}
}
}

After Format Document command...
public class Divider
{
    public static double Divide(int divident, int divisor)
    {
        try { return divident / divisor; }
        catch (Exception ex)
        {
            throw ex;
        }
    }
 
    public static void Main()
    {
        try
        { Divider.Divide(30, 0); }
        catch (Exception ex)
        {
            Debug.WriteLine(ex.StackTrace);
        }
    }
}


Tip: Another way to achieve the same result is to first find the last closing bracket in the source and then delete it, and finally re-type it.

You can also check out the other interesting features available on the Edit -> Advanced menu:


Sunday, September 28, 2008

Null-coalescing operator in .NET Framework

The post Declaring variables as nullable in c# describes how nullable value types can be declared used in C#.

.NET Framework also provides the ?? operator, called the null-coalescing operator, and its primary use is to define a default value for a nullable value types as well as reference types. It returns the left-hand operand if it is not null; otherwise it returns the right operand.

As an example, if the following code is run, the intValue will be 1, since nullInt is null.

Nullable<int> nullInt = null;

int intValue = nullInt ?? 1;

Thursday, September 25, 2008

Walkthrough EQATEC Tracer

1: Create application in .NET

I have written a simple test application, TestEqatecTracer, to play with the new tool EQATEC .NET Tracer (which I mentioned in the previous post). In the TestEqatecTracer application,

- names are populated in a list structure,
- list is then sorted using the List.Sort() ,
- finally, the list is sorted by the last character using SortByLastCharacter Comparer class.


using System;

using System.Collections.Generic;

using System.Text;

 

namespace TestEqatecTracer

{

   public class SortByLastCharacter : IComparer<string>

   {

        #region IComparer<string> Members

 

        public int Compare(string x, string y)

        {

            if (string.IsNullOrEmpty(x) || string.IsNullOrEmpty(y))

               return 0;

            else

               return x[x.Length - 1].CompareTo(y[y.Length - 1]);

        }

 

        #endregion

   }

 

   public class Program

   {

        static void Main(string[] args)

        {

            List<string> names = new List<string>();

            names.Add("John");

            names.Add("Frank");

            names.Add("Andy");

            names.Add("Brain");

 

            Console.WriteLine("Initial names: ");

            PrintNames(names);

            Console.WriteLine();

 

            Console.WriteLine("Names sorted: ");

            names.Sort();

            PrintNames(names);

            Console.WriteLine();

 

            Console.WriteLine("Names sorted by last character: ");

            names.Sort(new SortByLastCharacter());

            PrintNames(names);

            Console.WriteLine();

 

            Console.ReadLine();

        }

 

        private static void PrintNames(List<string> names)

        {

            if (names != null)

            {

               foreach (string name in names)

                    Console.WriteLine(name);

            }

        }

   }

}



2. Instrumentation Process

Now open the EQATEC Tracer tool. In the Instrumentor tab, browse and locate the assemblies of the application. The drag and drop feature can also be used.

The list of all assemblies in the selected folder will be shown in the Assembly List.

Select the assemblies that will be analysed in the list shown, and start the instrumentation process by selecting the "Instrument currently selected assemblies" button and a modified version of the assemblies will be then generated. The instrumentation process injects trace statements in the assemblies.




3. Select methods to trace

Click the flash icon to launch the modified application. The application view will then change to the Viewer tab.

After connecting to the application, the Control tree is populated with the classes and methods of the assemblies. Select ones that needs to be traced by checking the boxes.

The LocalHost represents the local machine. If the application is a device application, then the IP address of the device should be entered.



4. View trace results

Now connect to the application using the "Play" button.

And the trace will be shown in the Trace Viewer.



25/09/2008 15:51:18 (1) enter Program.Main ( String[], )
25/09/2008 15:51:18 (1) enter+leave Program.PrintNames ( List`1[System.String], )
25/09/2008 15:51:18 (1) enter+leave Program.PrintNames ( List`1[System.String], )
25/09/2008 15:51:18 (1) enter+leave SortByLastCharacter..ctor ()
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Andy", "Brain", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "John", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Andy", "John", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "John", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "John", "Andy", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( -11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "John", "Frank", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 3, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "John", "John", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "John", "John", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "Andy", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( -11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "Andy", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( -11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "Brain", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "Andy", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( -11, )
25/09/2008 15:51:18 (1) enter SortByLastCharacter.Compare ( "Brain", "Brain", )
25/09/2008 15:51:18 (1) leave SortByLastCharacter.Compare ( 0, )
25/09/2008 15:51:18 (1) enter+leave Program.PrintNames ( List`1[System.String], )

EQATEC Tracer

Another free developer tool has been released yesterday - the EQUATEC Tracer.

Here's the email extract from the EQATEC development team:

We're happy to announce the release of yet another development tool, the EQATEC Tracer.

In summary, the tracer will show how your .NET code is executed live. It's great for debugging and no source code changes are needed: just point the tracer to your app, run the modified code, and start watching the trace output. It's that simple.

The tracer is useful for all .NET developers, but especially for those doing embedded development in .NET Compact Framework: it allows you to enable in-target-debugging during development or at customer sites - a situation where a traditional debugger isn't an option. Letting the tracer add trace-instructions to all methods and turn them on/off at runtime can easily save many, many days of work, so you can spend your time on the fun and interesting parts instead of adding endless trace-messages.

Some functional highlights include:

- Add trace to any .NET apps - no source code changes needed
- Enable tracing at runtime for all method calls, parameters, exceptions etc
- Works with both .NET Compact Framework and the full .NET Framework
- Very low overhead when tracing is turned off
- View trace output from PC or device remotely over network connection
- On the fly enabling and disabling of trace instructions
- Trace each thread in a separate window


The EQATEC Tracer can be downloaded here under BSD license terms.

Tuesday, September 23, 2008

CommaDelimitedStringCollection class in .NET Framework

One simple but yet very interesting and useful class in .NET Framework that allows the creation of comma separated string from a list of string items is the CommaDelimitedStringCollection. This class is found in the System.Configuration namespace. So, we can stop reinventing the wheel each time we need such a collection, and instead, make use of this ready-made class.

Sample code...

CommaDelimitedStringCollection sites = new CommaDelimitedStringCollection();

sites.Add("www.yahoo.com");

sites.Add("www.google.com");

sites.AddRange(new string[] { "moiashvin-tech.blogspot.com", "www.lexpress.mu" });

Console.WriteLine(sites.ToString());


Output...
www.yahoo.com,www.google.com,moiashvin-tech.blogspot.com,www.lexpress.mu

Sunday, September 21, 2008

100% code coverage - good but not preeminent

I was configuring TestDriven.NET on my machine, and the idea of writing a few lines about code coverage popped in my mind. There have been continuous debates and discussions about this particular topic in the past years and thousands of words have already been written by experts in the field. Everyone can have a different opinion about testing, and more importantly code coverage (as this is what the post is all about), and so do I.

We, programmers (irrespective of the programming language that we use), have one common goal in our respective objectives - to write good quality code. And by good quality code, I mean code that implements correctly the desired functionality, is in line with industry (or corporate) standards while following the appropriate coding guidelines, uses constraint resources of the environment and infrastructures in an optimal way and is easily maintainable, just to mention a few. Last but not least, another feature of the good quality code is also 'bug free' code.

The testing phase in a software development life cycle ensures that the code is well-tested using an appropriate strategy. Different types of tests, such as unit tests, integration tests and system tests, just to name a few, are conducted. Once the tests are completed, code coverage reports are usually produced.

"Testing never proves the absence of faults, it only shows their presence." - Edsger Dijkstra

What is code coverage? Code coverage tells us how much of our code have we tested. It gives helpful information about the part of the code that has been exercised, and hence, a complete new perspective to the testing paradigms. However, the toughest task is to be able to correctly interpret the code coverage results (or say, reports). And that's where development teams and programmers often make their first mistake.

Many professionals in the software development field believe that a 100% code coverage means that the application is bug free. Hold on. Take a moment and give this a second thought. Are you indeed such a believer?

According to me, 100% code coverage is good but not preeminent. Not preeminent? Yes, I believe there is nothing extraordinary with a 100% code coverage. Does the 100% coverage guarantee that all the tests have been done in the right way? Does it guarantee that the selected test cases and test data are indeed correct? Does it guarantee that we haven't missed any corner case? What about a missing functionality in the code, will the 100% coverage identify it? The answers are a big NO. This is neither the Test Driven Development nor the code coverage fault. It's a failing of the way the results are interpreted. The focus should be more on the test strategies, scenarios and data rather than on the code coverage.

Let me give a very basic example. I have a static Divide() method in the Divider class that accepts a dividend and divisor and returns the quotient.

using System;
using System.Collections.Generic;
using System.Text;
 
namespace CodeCoverageTests
{
    public class Divider
    {
        public static double Divide(int divident, int divisor)
        {
            return dividend / divisor;
        }
    }
}


I will use the DividerTest class to test this Divide() method using the NUnit tool.

using System;
using System.Collections.Generic;
using System.Text;
using NUnit.Framework;
 
namespace CodeCoverageTests
{
    [TestFixture]
    public class DividerTest
    {
        [Test]
        public void TestDivide()
        {
            Assert.AreEqual(10.0, Divider.Divide(30, 3), "Incorrect division.");
        }
    }
}

When run, the test is passed successfully.


And more importantly, the code coverage shows a 100% figure.


With this figure, it gives the impression that this is really a good piece of work, with tests passed succesfully, and above all, a code coverage of 100%.

Ladies and Gentlemen: Don't be fooled by the coverage report. That's how Andrew Glover expressed himself in his article “In pursuit of code quality: Don’t be fooled by the coverage report”.

Call the method Divide() with 0 as the divisor and the program will throw a DivisionByZero exception. This is just a simple example to show how wrong one can be when assuming that a piece of code with 100% code coverage is bug free.

Code coverage is a very good indicator of how various sections of the code were tested. It is here to work as a complement, not the primarily indicator, for the overall code quality picture.

Thursday, September 18, 2008

Netbeans free DVD distribution program suspended indefinitely

Extract of the email from Netbeans Webmaster...

I regret to inform you that the DVD distribution program has been suspended indefinitely as we evaluate options to simplify the distribution of NetBeans software.

Since August 30th, 2005, NetBeans.org has shipped more than 225,000 CDs & DVDs to developers around the world through this initiative! During this period, NetBeans has experienced explosive growth as a download, media kit, and a community. To stay ahead of this encouraging trend we are looking into ways to effectively satisfy increasing demand for NetBeans software worldwide. Please bear with us.

In the interim, we are offering the same great contents of NetBeans IDE 6.1 ML DVD Starter Kit as an ISO image that you are free to download and burn. Alternatively, visit our download page for installer bundles as lightweight as 18MB. In the near future we also hope to offer our downloads via mirrors and bittorrent ...

Monday, September 15, 2008

Logon failed for user MACHINENAME/ASPNET

Some weeks back, everything was working fine with the login MYCOMPUTER/ASPNET on the SQL Express Server.

I formatted my machine recently and during 're-installation' of the operating system, I used a MACHINENAME instead of the default MYCOMPUTER.

Then, I run the aspnet_regiis command and it seems to me that the user MACHINENAME/ASPNET has been created and is also being used as login onto the database.

The client application throws the following exception:

System.Data.SqlClient.SqlException: Cannot open database "XXXDATABASEXXX.MDF" requested by the login. The login failed.
Login failed for user 'MACHINENAME\ASPNET'.
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
... ... ... ...
... ... ... ...

The database should now be configured to recognise this new MACHINENAME/ASPNET user.

I tried to replace the MYCOMPUTER/ASPNET user with MACHINENAME/ASPNET user in the database properties but can't find the MACHINENAME/ASPNET user in the available list of users. Any reason for that???

Anyways, instead of losing precious time finding the right way, the following SQL statement will create the user on the database and allow successful login. Just you have to make sure that the appropriate permissions are set once the user has been created.

USE [XXXDATABASEXXX.MDF]
CREATE USER [MACHINENAME\ASPNET] FOR LOGIN [MACHINENAME\ASPNET]
GO

Don't forget to change XXXDATABASEXXX and MACHINENAME to the appropriate names on your machine...

Friday, September 12, 2008

Predicates: List.Find() method

When it comes to searching an element in a list in C#, it seems easier to write a for loop, and iterate over the elements until the desired element is found. In other words, a linear or sequential search.

As an example, a LocationVO has two members: Code and Description.
public class LocationVO
{
    private string code;
 
    /// <summary>
    /// Gets or sets the code.
    /// </summary>
    /// <value>The code.</value>
    public string Code
    {
        get { return code; }
        set { code = value; }
    }
 
    private string description;
 
    /// <summary>
    /// Gets or sets the description.
    /// </summary>
    /// <value>The description.</value>
    public string Description
    {
        get { return description; }
        set { description = value; }
    }
}

The list declaration would be as follows:
List<LocationVO> locations = new List<LocationVO>();

And the linear search would be:
/// <summary>
/// Finds the business location.
/// </summary>
/// <param name="code">The code.</param>
/// <returns></returns>
public LocationVO FindLocation(string code)
{
    if (locations != null)
    {
        for (int i = 0; i < locations.Count; i++)
        {
            if (locations[i].Code = code)
                return locations[i];
        }
    }
    return null;
}

Predicates
An more elegant way is to use the List.Find() method. This method uses a predicate that defines the search criteria. If an element has to be searched by using another criteria (e.g. using the description property rather than the code one), it would be better to write another predicate rather than duplicating the linear search algorithm in the source code.
/// <summary>
/// Finds the location using predicate.
/// </summary>
/// <param name="code">The code.</param>
/// <returns></returns>
public LocationVO FindLocationUsingPredicate(string code)
{
    LocationVO vo = locations.Find(delegate(LocationVO curr)
    {
        return curr.Code == code;
    });
 
    return vo;
}

The List.FindAll() method is yet another interesting method that returns all instances matching the search criteria.