Contents tagged with .NET 2.0
-
[.NET 2.0] Playing Around with BuildProvider and CodeDom
This is old news for some of you, but I've never looked at the ASP.NET buildprovider functionality in more detail until tonight, and it is pretty cool. The buildprovider can generate/build code from certain file types you drop into an ASP.NET project and I'm sure you're familiar with .xsd files and how VS.NET generates classes from those. The cool thing is that you can write your own buildprovider and generate code yourself.
If you think this sounds like fun, here's a few links for you to get you started:
- Fritz Onion's "Jaw Dropping Experience": http://pluralsight.com/blogs/fritz/archive/2004/09/06/2188.aspx
- Kirk Allen's "Web Services Contract First" blog post: http://blogs.msdn.com/kaevans/archive/2005/09/02/460231.aspx
- Daniel Cazzulino's article on code generation: http://msdn.microsoft.com/xml/default.aspx?pull=/library/en-us/dnxmlnet/html/xsdcodegen.asp
What you need to know though, is that if you need to do something more elaborate, the CodeDom stuff isn't a walk in the park. Also, the buildprovider only works for ASP.NET projects, which is sad news, but Scott Guthrie explained it in an old blog post of his:
In the beginning of the Whidbey project there was a plan to enable broad declarative support for file-types as compiler inputs (for example: XAML could have been processed this way). Unfortunately due to time/resources the compiler teams had to scale back their support for this -- and only web projects still contain them. I'm hoping we'll see broader support for them in all project types with future releases.
Buildproviders should also work in Web Application Projects, but I couldn't get it to run... Have to look at that again some other day. I saw Scott Guthrie mention this in some blog post, but I cannot find it now. UPDATE: I got a mail from Scott about this:
Unfortunately build providers don’t work directly with web application projects (they still work for the running app – but the assemblies they create aren’t linked to by the web application project assembly, so you can’t reference the types directly.
You can, however, use the VS feature called “single file generators” that enable you to generate .vb/.cs files from declarative types, and then include this within your project assembly.
Pity... guess I have to look at single file generators then if I want to follow up on this one. Or just run an external code generator manually. No time for this now anyway, too much work to do...
-
[.NET 2.0] On Battery or Not
I'm thinking of writing a small utility to manage which of my apps gets started at startup of Windows, depending on if my laptop is running on batteries or not. Normally, when I boot it up on batteries, I don't want to start things such as my blog reader and a few other things.
The thing is it's very simple to detect from .NET if you are running on batteries or not. The SystemInformation type gives you all that and more:
using System;
using System.Windows.Forms;
namespace BatteryConsole
{
class Program
{
static void Main(string[] args)
{
PowerStatus ps = SystemInformation.PowerStatus;
if(ps.PowerLineStatus == PowerLineStatus.Online)
Console.Write("Your power cable is connected, and ");
else
Console.Write("You are running on batteries, and ");
Console.WriteLine("your battery level is on {0}", (ps.BatteryLifePercent * 100) + "%");
}
}
}
I'll get back if I ever get that small program written.
-
[.NET 2.0][Unit Testing] Good Tutorial on System.Transactions (and Unit Testing)
On my random blog reading and Googling around System.Transactions and Unit Testing, I ran into a series of short but great articles by Stuart Celarier which actually covers both topics. Stuart teaches the reader about System.Transaction by using unit tests in a very educational (and entertaining) way.
He uses NUnit in his articles, but nothing will stop you from using the test mechanism built into VS.NET if you got that Team Edition version. Just use the [TestMethod] attribute instead of [Test] and all sample code in the articles will compile and test well (eventually :)
Stuart also make use of anonymous methods for testing events that I recently blogged about.
System.Transactions is good stuff, I wonder if it could be useful to manage "compensating transactions" when dealing with multiple web service calls within a transaction?
-
[.NET 2.0][Unit Testing] Using Anonymous Methods when Testing Events
-
[.NET 2.0] Detecting Idle Time with Mouse and Keyboard Hooks
I thought I could share some piece of code I wrote a couple of years ago to detect if a user is idle or not. I used it on a chat client I developed because we were not allowed to use Messenger at the site. So the way to do it is to set up a coupld of low-level Windows hooks to detect mouse and keyboard activity. Obviously this involves a couple of DLL Import statements and you have to be careful to UnHook everything when the application exits as we're dealing with unmanaged code here. That's why I implemented the IDispose pattern for it.
This code is actually a piece of cake to implement if you use the ClientIdleHandler class (code below). First a look at the sample Windows Form which is made up of a lable indicating if the user is idle or active, and a timer set to 1 second. Each time the timer fires, it checks the bActive value in the ClientIdleHandler to see if the user has been active since the last check. I also added a progress bar on it (0 to 10) to give a visual indication on the idle seconds count.
Note: This code has not been tested in production systems and if you decide to use it, do that at your own risk. This code has been running pretty fine for the last 2 years, but on .NET 1.1. I don't know how well it behaves on .NET 2.0 even though it seems to work well. Also note that this code is not optimized in anyway and you may want to implement the static bActive variable different, perhaps raise events from the ClientIdleHandler class instead of using a timer like I do. Anyway, you have been warned :)
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace MouseAndKbdHookSample
{
public partial class Form1 : Form
{
private ClientIdleHandler clientIdleHandler = null;
private int iIdleCount = 0; //keeps track of how many seconds the user has been idle
private const int IDLE_THRESHOLD = 10; //how many seconds should pass before the app goes into idle mode
public Form1()
{
InitializeComponent();
//start client idle hook
clientIdleHandler = new ClientIdleHandler();
clientIdleHandler.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
if (ClientIdleHandler.bActive) //indicates user is active
{
//zero the idle counters
ClientIdleHandler.bActive = false;
iIdleCount = 0;
//change user status
if (IdleLabel.Text == "IDLE")
IdleLabel.Text = "ACTIVE";
}
else //user was idle the last second
{
//check if threshold was reached
if (iIdleCount >= IDLE_THRESHOLD)
{
//change to IDLE and stop counting seconds
if (IdleLabel.Text == "ACTIVE")
IdleLabel.Text = "IDLE";
}
else //increase secs counter
iIdleCount++;
}
//some visual goo added
progressBar1.Value = iIdleCount;
}
}
}I added some code into the Dispose() method of the form, to help close the hooks, like this:
//Dispose of our client idle handler
if (clientIdleHandler != null)
clientIdleHandler.Close();Then there is this ClientIdleHandler class which does it all. I added enough comments in there I hope to explain what it does. If you want to read more on these hooks and how to use them from .NET there is always Google out there and a few KB articles on MSDN which helped me out. Like this one for example. Some people may recognize parts of the code in this class from a bunch of code sample that can be found on the Internet, still this kind of functionality is still asked for by people in forums.
ClientIdleHandler.cs
using System;
using System.Runtime.InteropServices;
namespace MouseAndKbdHookSample
{
/// <summary>
/// Write something here sometime.../// </summary>
public class ClientIdleHandler : IDisposable
{
//idle counter
public static bool bActive = false;
// hook active or not
static int hHookKbd = 0;
static int hHookMouse = 0;
// the Hook delegate
public delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
//Declare MouseHookProcedure as HookProc type.
public event HookProc MouseHookProcedure;
//Declare KbdHookProcedure as HookProc type.
public event HookProc KbdHookProcedure;
//Import for SetWindowsHookEx function.
//Use this function to install thread-specific hook.
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn,
IntPtr hInstance, int threadId);
//Import for UnhookWindowsHookEx.
//Call this function to uninstall the hook.
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
//Import for CallNextHookEx
//Use this function to pass the hook information to next hook procedure in chain.
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode,
IntPtr wParam, IntPtr lParam);
//Added all the hook types here just for reference
public enum HookType : int
{
WH_JOURNALRECORD = 0,
WH_JOURNALPLAYBACK = 1,
WH_KEYBOARD = 2,
WH_GETMESSAGE = 3,
WH_CALLWNDPROC = 4,
WH_CBT = 5,
WH_SYSMSGFILTER = 6,
WH_MOUSE = 7,
WH_HARDWARE = 8,
WH_DEBUG = 9,
WH_SHELL = 10,
WH_FOREGROUNDIDLE = 11,
WH_CALLWNDPROCRET = 12,
WH_KEYBOARD_LL = 13,
WH_MOUSE_LL = 14
}
static public int MouseHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
//user is active, at least with the mouse
bActive = true;
//just return the next hook
return CallNextHookEx(hHookMouse, nCode, wParam, lParam);
}
static public int KbdHookProc(int nCode, IntPtr wParam, IntPtr lParam)
{
//user is active, at least with the mouse
bActive = true;
//just return the next hook
return CallNextHookEx(hHookKbd, nCode, wParam, lParam);
}
public void Start()
{
if (hHookMouse == 0)
{
// Create an instance of HookProc.
MouseHookProcedure = new HookProc(MouseHookProc);
// Create an instance of HookProc.
KbdHookProcedure = new HookProc(KbdHookProc);
//register a global hook
hHookMouse = SetWindowsHookEx((int)HookType.WH_MOUSE_LL,
MouseHookProcedure,
(System.IntPtr)Marshal.GetHINSTANCE(
System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]),
0);
//If SetWindowsHookEx fails.
if (hHookMouse == 0)
{
Close();
throw new ApplicationException("SetWindowsHookEx() failed");
}
}
if (hHookKbd == 0)
{
//register a global hook
hHookKbd = SetWindowsHookEx((int)HookType.WH_KEYBOARD_LL,
KbdHookProcedure,
(System.IntPtr)Marshal.GetHINSTANCE(
System.Reflection.Assembly.GetExecutingAssembly().GetModules()[0]),
0);
//If SetWindowsHookEx fails.
if (hHookKbd == 0)
{Close();
throw new ApplicationException("SetWindowsHookEx() failed");
}
}
}
public void Close()
{
if (hHookMouse != 0)
{
bool ret = UnhookWindowsHookEx(hHookMouse);
//If UnhookWindowsHookEx fails.
if (ret == false)
{
throw new ApplicationException("UnhookWindowsHookEx() failed");
}
hHookMouse = 0;
}
if (hHookKbd != 0)
{
bool ret = UnhookWindowsHookEx(hHookKbd);
//If UnhookWindowsHookEx fails.
if (ret == false)
{
throw new ApplicationException("UnhookWindowsHookEx() failed");
}
hHookKbd = 0;
}
}
public ClientIdleHandler()
{
//
// TODO: Add constructor logic here
//
}
#region IDisposable Members
public void Dispose()
{
if (hHookMouse != 0 || hHookKbd != 0)
Close();
}
#endregion
}
}That's it folks! I hope it helps someone.
-
WinFX Renamed to .NET Framework 3.0
Picked this up from Soma's blog:
...we have decided to rename WinFX to the .NET Framework 3.0. .NET Framework 3.0 aptly identifies the technology for exactly what it is – the next version of our developer framework.
What a pack of good stuff developers will get in that release indeed. The CLR will still be version 2.0 though. Jazon Sander posted some details around questions that followed directly after that announcement, like these:
1. What version of the compilers are being used? .NET FX 3.0 is built on .NET FX 2.0 including the CLR and BCL. This means you will be using the 2.0 C# and VB compilers from the redist when using .NET FX 3.0.
2. Will .NET FX 3.0 contain LINQ support? No. LINQ support is in the Orcas product which is shipping after .NET FX 3.0 (which ships in Vista).
I think I'll have to figure out a new tag taxonomy for my blog posts :)
-
[.NET 2.0] Anonymous Methods
My mate Eric blogs about how useful Anonymous Methods could be when calling on multiple asynchronous methods. Check it out.
-
[.NET 2.0] Testing Generics, Collections and Yield Return
I've not looked too much at the yield return statement in c# 2.0 yet, but if you learn how to use it I'm sure it will become something you use "every day" when programming. Whenever you need to do some conditional iterations on a collection, array or list, yield may be a nice solution to go for. A few, silly and not perfect, snippets which helped me understand how to use yield return:
using System;
using System.Collections;
using System.Collections.Generic;
public class Program
{
static void Main()
{
// Build up a few arrays and a list to work with
string[] names = { "Johan", "Per", "Thomas", "Lina", "Juan", "Jan-Erik", "Mats" };
int[] values = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
Console.WriteLine("Get the names which contains an 'a':");
// Iterate on all names which contains letter 'a'
foreach (string name in EnumerableUtils<string>.GetNamesContainingLetter(names, 'a'))
{
Console.Write("{0} ", name);
}
Console.WriteLine();
Console.WriteLine();
//iterate through first half of this collection
Console.WriteLine("First half of the name-array:");
foreach (string name in EnumerableUtils<string>.GetFirstHalfFromList(names))
{
Console.Write("{0} ", name);
}
Console.WriteLine();
Console.WriteLine();
//iterate through first half of another collection
Console.WriteLine("First half of the value-array:");
foreach (int value in EnumerableUtils<int>.GetFirstHalfFromList(values))
{
Console.Write("{0} ", value);
}
Console.WriteLine();
Console.WriteLine();
//iterate through first half of a List
Console.WriteLine("First half of the value-list:");
foreach (int value in EnumerableUtils<int>.GetFirstHalfFromList(list))
{
Console.Write("{0} ", value);
}
Console.WriteLine();
}
}
public class EnumerableUtils<T>
{
public static IEnumerable GetNamesContainingLetter(string[] names, char letter)
{
foreach (string name in names)
{
if (name.ToLower().Contains(letter.ToString().ToLower()))
yield return name;
}
}
public static IEnumerable<T> GetFirstHalfFromList(List<T> arr)
{
for (int i = 0; i < arr.Count / 2; i++)
yield return arr[i];
}
public static IEnumerable<T> GetFirstHalfFromList(T[] arr)
{
for (int i = 0; i < arr.Length / 2; i++)
yield return arr[i];
}
} -
[.NET 2.0] Quick Way of Closing VisualStudio Files
If you end up having a zillion files opened in the VisualStudio 2005 IDE and want to close a few of them, just click with the MIDDLE mouse button on their tabs where you see the filename. Quick and easy.
-
[.NET 2.0] Visual Studio 2005 Web Application Project V1.0 Released
From the Visual Studio 2005 Web Application Project webby:
Today we released the V1.0 release of the VS 2005 Web Application Project option. You can learn about it here, and download it here.
You should then check out the tutorials on this site to learn more about it and how to use it. You might also want to keep an eye on my blog -- where I'll be posting updates about it regularly.
This forum is the best place to ask questions or get get answers about the VS 2005 Web Application Project option.