Tuesday, November 6, 2007

Detect the presence of network connection

A simple way to detect the presence of network connection in a device (managed code):

Wednesday, October 24, 2007

Log4net and .Net Compact Framework 1.0

Log4net, part of the Apache Logging Services project, can be a very helpful tool to log statements to different output targets. One of the features of log4net is the support for multiple frameworks. This post is just an extract from the Apache site that highlights the major differences of the compact version of log4net.

Microsoft .NET Compact Framework 1.0

* Assembly attributes
The .NET Compact Framework 1.0 does not support retrieving assembly level attributes, therefore all log4net configuration attributes were removed from the .NET Compact Framework 1.0 version of log4net.

For Smart-device applications, the log4net system can be configured by passing the location of the log4net configuration file to the log4net.Config.XmlConfigurator.Configure(FileInfo) method in the entry point of the application.

For example:

// Uncomment the next line to enable log4net internal debugging
// log4net.Util.LogLog.InternalDebugging = true;

// This will instruct log4net to look for a configuration file
// called config.log4net in the root directory of the device
log4net.Config.XmlConfigurator.Configure(new FileInfo(@"\config.log4net"));

// This will shutdown the log4net system
log4net.LogManager.Shutdown();


* Notification events
The .NET Compact Framework 1.0 does not support notification events during the application shutdown, therefore log4net cannot automatically hook the application shutdown notification.

Applications will need to programmatically shutdown the log4net system during the application's shutdown using the log4net.LogManager.Shutdown() method in order to prevent losing logging events. See the code above for an example.

* FileSystemWatcher
The .NET Compact Framework 1.0 does not support the System.IO.FileSystemWatcher class. As a result, the XmlConfiguratorAttribute.Watch property and the XmlConfigurator.ConfigureAndWatch methods are not available. Watching changes to the log4net configuration file is not supported on the .NET Compact Framework 1.0.

* UserName
The .NET Compact Framework 1.0 does not support the System.Security.Principal.WindowsIdentity class. This is used to capture the current thread's user identity. Therefore the LoggingEvent.UserName property will return the value "NOT AVAILABLE".

* Identity
The .NET Compact Framework 1.0 does not support the System.Security.Principal.IPrincipal interface. This is used to capture the current thread's user identity. Therefore the LoggingEvent.Identity property will return the value "NOT AVAILABLE".

* Environment variables
The .NET Compact Framework 1.0 does not support retrieving environment variables, therefore it's not possible to substitute environment variables in parameter values when using the .NET Compact Framework 1.0 version of log4net.

* Serialization
The .NET Compact Framework 1.0 does not support serialization, therefore none of the log4net classes in the .NET Compact Framework 1.0 version are serializable.

* LoggingEvent.Domain
The .NET Compact Framework 1.0 does not support AppDomain functionality. The friendly name for the current AppDomain is stored in the LoggingEvent.Domain property and is accessed using the %a pattern of the PatternLayout. On the .NET Compact Framework 1.0 this value is generated by taking the file name for the application's primary module.

Click here to visit the page directly.

Friday, September 28, 2007

Use of BeginUpdate() and EndUpdate() when populating ListView/TreeView

Often a listview control in C# needs to be populated with large amount of data (bulky operations, for example, adding 1000 items). For every item added in the Listview, the control will redraw itself, thus greatly reduce the overall performance.

However, using the two methods BeginUpdate() and EndUpdate() while performing these bulk operations gives significant advantage. A call to BeginUpdate() can be made before adding/deleting/clearing items. This will stop any paint messages being sent or processed. Once the operation is done, the EndUpdate() can then be called.


I have logged the time taken of the above code (i.e. adding 1000 items in a ListView for each button click) with and without the BeginUpdate/EndUpdate method calls using a test application.


The use BeginUpdate() and EndUpdate populates the control with a constant duration and much better performance. Amazing, isn't it?

Thursday, September 20, 2007

Write C# code for both full .NET Framework and .NET Compact Framework

Introduction
C# is fully supported on both the full .NET Framework and .NET Compact Framework and there are many times when a piece of code could have been used on both the "full framework" and "compact framework. A simple example would be the Business Logic as this would normally be the same in an enterprise project, whether the solution would be deployed on any of these platforms. I have attempted to write a simple application that addresses this issue, and I am sure there exist other ways to do this - google.com is a faithful friend :).

The Visual Studio Solution: FrameworkApps
There are three projects in the solution, and they are:

1. BusinessLogic, a class library project, that implements the business logic;
2. DesktopApp, a desktop application on the full .net framework platform;
3. DeviceApp, a device application on the .net compact framework platform.

The BusinessLogic.cs file is used by both the desktop and device application. Thus, any source files hould be added as links to the projects, to avoid duplicate source files.

Here is a snapshot of the project structure:



Conditional compilation
Conditional branching of the code at compile time is used to determine the code to be compiled during the compilation process. To achieve this, go to the desktop project properties and under the Build tab add a new "Conditional compilation symbol", say FULL_FRAMEWORK.



Implementation
Project: BusinessLogic
Source file: BusinessLogic.cs



Project: DesktopApp
Source file: Form.cs



Project: DeviceApp
Source file: Program.cs



Output
Set DesktopApp as the startup project and run the application:



Set DeviceApp as the startup project and run the application:



Hope it helps.

Monday, September 10, 2007

Automatic generation of XML Documentation in C# with GhostDoc

Writing XML comments while coding in C# can be a tedious task at times. By installing GhostDoc, a free Visual Studio add-in, you can automate this process and get some additional minutes to concentrate on the code :-)

What does GhostDoc do?
GhostDoc simply gives you a quick means of adding some comments to your classes/methods while you are using the editor to code in C#, by guessing a suitable (and meaningful) comments and thus, automates the process.

Note: GhostDoc assumes that the code follows Microsoft's Design Guidelines for Class Library Developers.

GhostDoc also includes options that allow you to modify existing rules and add additional rules that determine what kind of comments should be generated. Sounds exciting, isn't it?

What doesn't GhostDoc do?
GhostDoc doesn't do miracles...

GhostDoc is not a tool for creating the complete documentation for a given source file in one go. It can only document one member at a time, and you always have to check and, if necessary, correct the automated comments in order to meet match your preferred documentation.

Installation
Download it from http://www.roland-weigelt.de/ghostdoc/

Usage
While coding in the Visual Studio editor, right click on the class name, method, etc and select "Document this".


Give it a try!

Thursday, September 6, 2007

Millisecond component on .NET Compact Framework

One of the differences between full .NET Framework and .NET Compact Framework relates to the Time Intervals. The value returned from System.DateTime.Now is specific only to seconds, not milliseconds. Thus, the milliseconds component of the DateTime, usually expressed between 0 and 999 (in the full framework) will always be 0 on a compact framework platform.

Recommendation

Microsoft recommends the use of the TickCount property available in the Environment class in order to get a more precise time span measurement. This property returns the amount of time in milliseconds that has passed since the last time the computer was started.

http://msdn2.microsoft.com/en-us/library/system.environment.tickcount(vs.80).aspx

Hope it helps.

Monday, September 3, 2007

Optimal size of column headers in listview

When using a ListView in C# and the View property is set to View.Details, you probably want to set the width of the columns in the listview to an optimal size, without any … in the columns.

Problem
If the column text strings does not fit the column width (set at design time), three dots (...) will be displayed at run time, as shown below.



Aim
Display the text fully in the column, and get rid of the ...

Solutions??

For one moment, you may think of finding the length of the longest string in the column and assign it to the width of the column header. But wait, the length would be in terms of number of characters, whereas the width of the column should be in pixels. So, this will not work, unless you use a utility function to convert the length of the text (taking into consideration the font being used) and calculate it in terms of pixel. Yes it is possible :-) but you won't see it in this post!

Correct Solution
At runtime, set the Width of the ColumnHeader to:

a) -1 to adjust the width of the longest item in the column (without taking into consideration the column heading).

hdrCountry.Width = -1;
hdrName.Width = -1;



Now, the text in the columns is displayed correctly, but not the heading of the first column.

b) -2 to autosize width of the column, taking into consideration the column heading.


hdrCountry.Width = -2;
hdrName.Width = -2;



Now, it works fine. Hope it helps.

Monday, August 27, 2007

Drawing a filled rectangle on a windows form

This is quite straight-forward. Override the OnPaint() method with the following code:



And it's done. A filled rectangle will be painted at the top of the form.

The code is in the overridden OnPaint() method so that each time the form is resized/obscurred by another form, the content will be re-painted automatically. Also, it is a good practice to call the Dispose methods of objects that consume system resources heavily (e.g. Brush and Graphics objects).

Thursday, August 2, 2007

Cradle a device emulator and access the internet

Pre-requisites:
Visual Studio 2005 is installed.
Microsoft ActiveSync 4.0 or later is installed.
An internet connection is available.

Often a device emulator attempts to connect to the internet via the pc and the following message is encountered: Cannot Connect - Unable to connect: You have no modem entries created, and no network card present.

Here is a simple walkthrough, with some tips, describing how an emulator can be launched from Visual Studio, cradle it via ActiveSync and access a web page on the internet (obviously, provided that the PC is connected to the net).


Step 1: Launch an emulator (say Pocket PC 2003 SE Emulator)

a) Start Visual Studio 2005.

b) Go to the Device Emulator Manager (Tools -> Device Emulator Manager)
A list of available emulators will be displayed in the Device Emulator Manager window.



c) To start the emulator, right click PC 2003 SE Emulator and select Connect.
The Emulator will start.



Step 2: Attempt to browse a web page via Internet Explorer

a) Launch Internet Explorer (Start -> Internet Explorer) from the Device Emulator and your web page url, say enter www.google.com.

The error message will be displayed: Cannot Connect - Unable to connect: You have no modem entries created, and no network card present.



Step 3: Cradle the emulator

The emulator must be cradled (as it would have been the case for a physical device) and connect it to the PC via ActiveSync.

a) To cradle the emulator, go to the Device Emulator Manager in Visual Studio (Tools -> Device Emulator Manager).



b) Right click on the connected emulator, and select Cradle.
The emulator will now be cradled and connected to ActiveSync.



Step 4: Access the web page (repeat step 3)
The Internet Explorer on the emulator will successfully browse to the web page.


Great, isn't it?

Sunday, July 22, 2007

Skip 'blue' welcome screen on Windows XP

If you are using Windows Xp and want to get rid of the blue "Welcome" screen that shows up at startup (prompting you to select the correct user account and enter the password, if any), then this post can be useful :-) One reason for turning off this feature is that you can turn on your PC, and come back after some minutes and you are right on the desktop (ready for use). However, please bear in mind that although you are the sole user of the system, it is not recommended to do so as it simply means you are disabling the basic security feature that the operating system provides. So, be careful!

Pre-requisite:
You have currently logged on windows as Administrator and have admin rights.

Steps
1. Click Start and then select Run,
2. In the Run window, type control userpasswords2, and then click OK button,


A User Accounts windows pops up.

3. Clear the "Users must enter a user name and password to use this computer" check box, and then click Apply.


You will be requested for the username and password of the account you wish to automatically logon as for following reoots of your system.

4. In the Automatically Log On window, type the required information and click OK to close the window.
5. Finally click OK to close the User Accounts window.

At any later stage, you can activate this security feature by following the same steps but recheck the box, at step 3.

Friday, July 13, 2007

Setting transparent color to control's BackColor property

Using C# with .Net Framework 2.0, an attempt to assign a color from the System.Drawing.Color struct to the BackColor property of a window’s control, say a System.Windows.Forms.TextBox, will compile and run successfully.

Snippet 1:
textBox1.BackColor = Color.Cyan;

However, a problem arises when any transparent color (e.g. #00FEF2D4) is assigned to the BackColor property. Upon execution, a runtime exception will be thrown (see below).

Snippet 2:
textBox1.BackColor = ColorTranslator.FromHtml("#00FEF2D4");


On msdn, the following explanation is given:
The BackColor property does not support transparent colors unless the SupportsTransparentBackColor value of System.Windows.Forms.ControlStyles is set to true.

Using the control’s SetStyle() method, this SupportsTransparentBackColor value can be changed. The problem now is that SetStyle() is declared as a protected method and thus, only the control’s class or any child class can call this method.


A quick solution
A possible solution is to create a class inheriting from the control’s class. For example, a TransparentTextBox class can inherit from the System.Windows.Forms.TextBox. Now, the protected SetStyle() method is accessible and the SupportsTransparentBackColor value can be set to true. The ideal place to call the SetStyle() method will be in the constructor of this new class after the InitializeComponent() method calls.



It’s done. Now, as an instance of TransparentTextBox can be created and any transparent color can be set.

Snippet 3:
transparentTextBox1.BackColor = ColorTranslator.FromHtml("#00FEF2D4");

One major concern: do we really want to subclass all controls that probably will need a transparent color? Think...

Hello World

Hello World! Welcome to my new blog - ASHVIN"S TECHNICAL BLOG.

I started a personal blog Ashvin Gunga last year. Then, the idea to have another blog where I can share fwd emails popped in my mind. So, I created another one - FWDs - early this year. Weeks back I thought why not a technical blog - a blog where I can share anything I want related with technology, computing and programming. Now, it's up. I am writing my first post!

Another post that I wrote on my personal blog and talks about the start of this new blog: Ashvin's Technical Blog