Monday, October 30, 2006

How cool is that

Heineken is refreshing its supply chain to ensure its beer doesn't reach parts it shouldn't.

Heineken is to trial a tracking system which will tell it exactly where its beer shipments are, even in the middle of the Atlantic. The brewer has deployed the solution to track ten containers full of beer travelling from the UK and the Netherlands to its distribution centre in the US. The project, which it calls "The Beer Living Lab", uses triangulation techniques of both satellites and cellular base stations to locate exactly where the cargo is. The SOA-based architecture will also allow the creation of distributed data sources, rather than Heineken having to run a large central database.

Tuesday, October 03, 2006

Dynamically calling an unmanaged dll from .NET (C#)

I like to keep collecting small snippets of code in my blog, which i know will be useful later on.
Below is the code snippet for "Dynamically calling an unmanaged dll from .NET (C#)" from Jonathans blog on MSDN blogs:

To start and to refresh our memories, let's create a very basic C++ dll that does very little..... your code should resemble the following (check out my previous post for more info on this):

Header file

extern "C" __declspec(dllexport) int MultiplyByTen(int numberToMultiply);

Source code file

#include "DynamicDLLToCall.h"

int MultiplyByTen(int numberToMultiply)
{
int returnValue = numberToMultiply * 10;
return returnValue;
}

As you can probably infer from the function name, an int is passed into this function and it will return the number passed in multiplied by ten. Told you it would be simple.

Now comes the more interesting part, actually calling this dll dynamically from your C# source code. There are two Win32 functions that are going to help us do this:

1) LoadLibrary - returns a handle to the dll in question
2) GetProcAddress - obtain the address of an exported function within the previously loaded dll

The rest is rather simple. We use LoadLibrary and GetProcAddress to get the address of the function within the dll we want to call, and then we use the GetDelegateForFunctionPointer static method within the Marshal class to assign this address to a C# delegate that we define. Take a look at the following C# code:


static class NativeMethods
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);

[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
}

class Program
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate int MultiplyByTen(int numberToMultiply);

static void Main(string[] args)
{
IntPtr pDll = NativeMethods.LoadLibrary(@"PathToYourDll.DLL");
//oh dear, error handling here
//if (pDll == IntPtr.Zero)

IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "MultiplyByTen");
//oh dear, error handling here
//if(pAddressOfFunctionToCall == IntPtr.Zero)

MultiplyByTen multiplyByTen = (MultiplyByTen)Marshal.GetDelegateForFunctionPointer(
pAddressOfFunctionToCall,
typeof(MultiplyByTen));

int theResult = multiplyByTen(10);
Console.WriteLine(theResult);
}
}

The only item worthy of note is the UnmanagedFunctionPointer attribute, which was introduced to version 2.0 of the .NET framework,

Monday, October 02, 2006

Using Settings in C#

The .NET Framework 2.0 allows to create and access values that are persisted between application execution sessions. These values are called settings. We can use settings by accessing the Properties namespace.

There are two types of settings:
Application Settings
User Settings


Settings have four properties:

Name: The Name property of settings is the name that is used to access the value of the setting at run time.
Type: The Type of the setting is the .NET Framework type that the setting represents. A setting can be of any type. For example, a setting that holds a user preference of color would be a System.Color type.
Scope: The Scope property represents how a setting can be accessed at run time. There are two possible values for the Scope property: Application and User. These will be discussed more in this section.
Value: The Value property represents the value returned when the setting is accessed. The value will be of the type represented by the Type property.

Creating a New Setting at Design Time
You can create a new setting at design time by using the Settings designer. The Settings designer is a familiar grid-style interface that allows you to create new settings and specify properties for those settings. You must specify Name, Type, Scope, and Value for each new setting. Once a setting is created, it can be assessed in code using the mechanisms described later in this article.

To Create a New Setting at Design Time

In Solution Explorer, expand the Properties node of your project.
In Solution Explorer, double-click the .settings file in which you want to add a new setting. The default name for this file is Settings.settings.
In the Settings designer, set the Name, Type, Scope, and Value for your setting. Each row represents a single setting.

Changing the Value of an Existing Setting at Design Time
You can also use the Settings designer to change the value of a pre-existing setting at design time, as described in the following steps:

To Change the Value of an Existing Setting at Design Time

In Solution Explorer, expand the Properties node of your project.
In Solution Explorer, double-click the .settings file in which you want to add a new setting. The default name for this file is Settings.settings.
In the Settings designer, find the setting you want to change and type the new value in the Value column.

Changing the Value of a Setting Between Application Sessions
At times, you might want to change the value of a setting between application sessions after the application has been compiled and deployed. For example, you might want to change a connection string to point to the correct database location. Since design-time tools are not available after the application has been compiled and deployed, you must change the setting value manually in the file.

To Change the Value of a Setting Between Application Sessions


Using Microsoft Notepad or some other text or XML editor, open the .exe.config file associated with your application.
Locate the entry for the setting you want to change. It should look similar to the following example:

This is the setting value


Type a new value for your setting and save the file.
Using Settings at Run Time
Settings are available to the application through code at run time. You can access the value of settings with application scope on a read-only basis, and you can read and write the values of user-scope settings. Settings are available in C# through the Properties namespace.

Reading Settings at Run Time
You can read both application-scope and user-scope settings at run time with the Properties namespace. The Properties namespace exposes all of the default settings for the project by using the Properties.Settings.Default object. When writing code that uses settings, all settings appear in IntelliSense and are strongly typed. Thus, if you have a setting that is of type System.Drawing.Color, for example, you can use it without having to cast it first, as shown in the following example:

this.BackColor = Properties.Settings.Default.myColor;

Saving User Settings at Run Time

Application-scope settings are read only, and can only be changed at design time or by altering the .exe.config file in between application sessions. User-scope settings, however, can be written at run time, just as you would change any property value. The new value persists for the duration of the application session. You can persist changes to user settings between application sessions by calling the Settings.Save method. These settings are saved in the User.config file.

To Write and Persist User Settings at Run Time
Access the user setting and assign it a new value, as shown in the following example:
Properties.Settings.Default.myColor = Color.AliceBlue;

If you want to persist changes to user settings between application sessions, call the Save method, as shown in the following code:
Properties.Settings.Default.Save();