Thursday, February 11, 2010

Force Internet Explore Emulation

Developing a completely flexible web application today can be tired-some,
And Microsoft sure doesnt make it any easier - a working site on IE8 could look bad on IE7, and might not work at all on IE6.

To make it a little bit easier, Microsoft enabled us to use "IE 7 Emulated Mode" on IE8, and luckily they made it possible for us to force IE8 to use Emulation.

Simply add:

<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />

to your header, and IE8 will automatically move to IE7 Emulation mode.

I know I know, it's an ugly workaround, but when you're deadline is yesterday, it might be just what you need...

Wednesday, August 5, 2009

Force Elavation By Code - Windows Vista & 7

If you want to force your application to run in elavated mode in Windows Vista or Windows 7, here's a quick guid on how to do it:

There's a Registry Key called:

HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers


Under this key, there's a value for each applications on your computer configured
either to run in compatability mode (WINXP or other) or as administrator (using elavation).

In order to add your application to this list, you should do the following:
1. Create a new REG_SZ (string) Value named after your full application path, i.e:

C:\Program Files\Your App\App.exe


2. Edit the Value you just created with the following data:

RUNASADMIN


3. If you want to force your application to run not only in elavation, but in XP SP3 compatability mode, update your Value's data to the following:

WINXPSP3 RUNASADMIN


Note: After creating this Registry Value, you must restart your application.

And... That's it!

Friday, August 15, 2008

Cross Processing: #1 Accessing TextBox

So this is the first in a series of posts on accessing cross process UI data.

Note: This posts will correspond to windows-rendeder process windows, and not WPF or java applications that render differently.

Some Background
Buttons, Textboxs, ComboBoxs and the rest are all called "Controls", but they are all actually different forms of "Window"'s.

Every visual (unlike services) process in Windows, is basically a window heirarchy where the root window is the container (with the minimize,maximize and close buttons) and the rest are the actual controls.

The way each control (window) sends information to other controls is through a broadcast mechanism called "Window Messages".

Very much like processes, we could search for a specific window using its unique identifier - handle (like process id), and make less specific search using its name and class.

The demo will be to start the calc, and update and read its textbox.

Prerequisits:
Before we could start codeing, we need some win api declarations:

1. In order to get the handle of a certain window, we'll use FindWindowEx - a windows api declaration:


[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);



2. in order to send data to a window, we need to send it a message:


[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, int wParam, string lParam);


3. Get the buffer of the text:


[DllImport("user32.dll")]
public static extern int GetWindowTextLength(IntPtr hWnd);


4. Get the actual text:

[DllImport("user32.dll")]
public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);



The Code!

Ok, so first we'll start the process:


Process proc = Process.Start(fullProcessPath);

proc.WaitForInputIdle();



Now, we'll use the FindWindowEx api to get the handle to its Edit box (the big textbox):


IntPtr hwnd = FindWindowEx(proc.MainWindowHandle, IntPtr.Zero, "Edit", "");



We have the control's handle, now we could...

1. Change value to "115":


SendMessage(hwnd, 0x000C, 0, "115");



2. Read the value:


int cap;
StringBuilder sb;
cap = Win32.GetWindowTextLength(this.Handle);
sb = new StringBuilder(cap + 1);
Win32.GetWindowText(this.Handle, sb, cap + 1);
return sb.ToString();

Sunday, June 3, 2007

Google Gear Vs. Web Browsers

A few days ago, Google released a beta (of course) version of a new open-source project called Gear.

Gear's main aim is to enabled online applications work offline as well.
Notice I didn't say web-based as the Gear API is open for RIA solutions as well - even more - Adobe's Apollo (Adobe's answer to WPF) project manager said it would have integrated support for the Gear API.

What Is This Gear Anyway?
Well its a very good question, since it's current release is really in its early beta stages and is probably due for some major changes, but its basically a browser plugin (currently supports only FireFox & IE under Window) which exposes a complete framework of utilities to store and retrieve... anything!
Whether it's image or script resources or applicative user-data - everything can be stored (per user of course) and retrieved easily like a hash map or using a simple ansi-sql like language!

This really sounds amazing, but what does this really means?
For the last decade or so, web browsers has become allot more that just an html engines, they now offer local cache, storing user-based data using cookies and saving your forms data.

But then Gear came.

But Why Is Gear Better Than My Existing Browser Solutions?

Because it does everything the browser does, only better.
Here's why:
1. Caching: Although client-side cache is a good thing, its one of the web-developer's worst nightmares - think of updating a script file and not knowing if your clients are using the new version, or the old and buggy one since their browser decided to store it.
Using Gear, you get the power to store resource files by version and retrieve them using a simple sql-like query or key-based!
You then not only don't have to worry if a new version is used or not, but you could also force a selected resource to be cached!

2. Cookies: Not only cookies have a limit on size and content data (cookies have a content security policy), but you don't know if cookies are enabled and if they do, if the client decided to delete them or not.
Using Gear you can save your data per-user using a secure manner, and retrieve no matter what browser your client uses.

There are many other reasons why Gear is good, but I haven't got to Gear's main goal - offline accessibility.

One of the biggest web-based mail client draw-backs is the necessity of being connected to the net.
Think of connection to your gmail or hotmail - for that matter - even while not connected to the net! or even better - to your online Google docs!

Summary
Gear is a set of client-side utilities that enable you to get a bigger handle on how and what data is stored on your client machine without worrying about his\hers browsers settings, allowing you to build a complete offline-accessible web-based solution!

Could this be a knockout to Web\RIA based solutions over the smart-client technologies?

Friday, March 30, 2007

A (Not So) New UI Front-End Alternative

When we're going to start a new project, we're accustomed to the standard 3-tier architecture, and although most of us will probably choose the same frameworks for our data and logic tiers, it's because these frameworks gives us everything we expect them to.

But what about our most important tier, the one that will make people buy our products - the UI tier? it looks like we don't have that kind of luxury of choosing a framework and we'll probably use ASP.Net.

And don't get me wrong - I really like ASP.Net and there are many splendid Ajax tool-kits\frameworks out-there that really are great,
But at the end of the day its basically HTML, and HTML is no fun - its too abstract, requires us to use Scripting languages which are hard to maintain and develop, not Object-Oriented, insecure, platform-dependent (each browser has its own engine) and many other cons.

So after cussing for a couple of days we'll probably use ASP.Net and be happy with it, because there is no other option...

Isn't there?


Adobe Flex Flash Developer
For most of us, Flash still sounds like a kids app for funny videos and games.
But apparently its a fully compliant Object-Oriented language!
So here are 3 facts you didn't know about flash:

1. Cross-Platform: Flash is supported for over 10 platforms amongst them are: Windows, Linux, Mac, Nokia (*), Solaris, Palm OS, BeOS and more.

2. Performance: From results of a benchmark done a few weeks ago, (See Benchmark Here) Flash is faster than Microsoft's new alternative - WPF\E, and on certain circumstances even faster than WPF!

3. IDE: Since mid 2004, Flash has a fully featured IDE based on the open-source Eclipse.

The most amazing thing about Flash is that it's absolutely server-side agnostic.
You could build a fully managed .Net back-end and connect your Flash GUI smoothly to it by WebServices or even directly call to your .Net methods.

Yep that's right using Macromedia's Remoting MX technology you can directly call your .Net methods from the flash code (Here's how)


Conclusion:
Before you start developing you next project, you should check reall good if ASP.Net is really the best way...

Saturday, March 24, 2007

Sternr's Complete Programmer Tutorial

Many people ask me, "sternr, how can one be like you - such a brilliant, funny yet good looking programmer???" ,

Well my friends, I decided to do my duty to man kind, and reveal my 10 steps to become a hardcore programmer!

Sternr's Complete HowTo Tutorial for Becoming a Hardcore Programmer

1. You're not a programmer, you're a Software Engineer.
And a damn good one if I might say.

2. There is no combination of upper-case letters you haven't heard of.
You simple know it by its earlier code name.

3. The Dual Buzzword Principle - Use as many buzzwords as you can.
but beware - there is a small and extincting specie of bold programmers who might ask you to explain what it means.
But even these rare few will not dare to ask twice - and here comes the duality principle: always save a backup buzzword to explain the buzzword.

4. Every design\idea that is not yours has a flaw.
If you cant find it, than it's a security hole - and besides, you would've done it differently...

5. NEVER argue with the Sysadmin - unlike the programmer next door, he really know what he's talking about.

6. Your code is NOT complex and hard to maintain.
It's simply flexible. very flexible.

7. The future is here - advice and talk as much as you can about technologies & products that still have no release date.
You cant be contradicted, yet no hard question can be asked - the design is not final...

8. Install a Linux on at least one of your computers.
You don't have to study, like or use it. but you must have one.
Note: It is recommended to say once a day (don't overdue else you'd be asked questions you cant answer) why you prefer Linux

9. Command Line - Use it as much as you can.
Everyone knows its stupid, but it looks impressive.

10. This is the last, but most important.
In the Hi-Tech industry - and IT especially, people are measured by 2 things and 2 things only: Self Confidence, and Experience.

It is very unfortunate (one might notice that this has nothing to do with how smart or good one is...) but true.

And because of it, it doesn't matter how much or what mistakes you do, its simply how you react to them, its how you react in meetings, and especially under pressure.

So simply stay cool.

Like me ;)

Monday, March 19, 2007

IIS 6.0 & "Connection Dropped" HTTP.sys Error

If you're an IIS (6.0) admin, you're probably quite familiar with the HTTP.sys error log, and even more with the "Connection Dropped" mysterious error.
Charis Ad has a great post explaining everything about this apparently not so dangerous error, here's his explanation.

Thanks Chris!

Thursday, March 15, 2007

Whats Behind W3WP Number Three?

Why?
I mean, they've got different names, different id's maybe even different users, so why on earth does IIS 6.0 makes it so hard to know which w3wp.exe process is running which Application pool?!

Although Microsoft offers us the IISApp.vbs script - which does exactly what I want (and even allows you to do certain actions like pool recycling etc.), this script works only on the current machine and has no support for remote servers.

The quickest - yet dirtiest solution would be to run the script remotely - whether it's by using PSEXEC, or through telnet - it's all the same, but not really recommended, especially not on production...

So, what can we do?

WMI to the Rescue!

After some work, I've found out that each w3wp process hosting an Application pool has some very interesting command-line arguments, I'll discuss these arguments in the future but right now the important thing is - the last argument w3wp gets is - hold your breath - the AppPool name it runs! hooray!

Here's a little code sample on how to implement this using .Net:


using System.Management; // Add reference to System.Management

/* A simple Value Object representing one Application Pool */
public class AppPool()
{
    public int ProcessId;
    public string Name;
    public long UsedMemory;
}

/* Gets remote server's name, returns list of all AppPools */
private List<AppPool> getAppPools(string serverName)
{
    ManagementScope scope;

    /* Change the query to select * if you want more details */
    SelectQuery query = new SelectQuery(
"SELECT ProcessId, CommandLine, WorkingSetSize FROM Win32_Process Where Name = 'w3wp.exe'");

    ManagementObjectSearcher searcher;
    List<AppPool> appPools = new List<AppPool>();

    /* If you do not have sufficient rights, impersonate */
    ConnectionOptions options = new ConnectionOptions();
    options.Username = @"MyDomain\admin";
    options.Password = "pwd";
    options.EnablePrivileges = true;

    scope = new ManagementScope(
        @"\\" + serverName + @"\root\cimv2", options);
    scope.Connect();

    searcher = new ManagementObjectSearcher(scope, query);

    foreach (ManagementObject mob in searcher.Get())
    {
      AppPool appPool = new AppPool();
      PropertyData property = mob.Properties["CommandLine"];

      int pos;

      /* Now we parse the AppPool name from the args */
      appPool.Name = property.Value.ToString();
      pos = appPool.Name.Length - 1;
      appPool.Name = appPool.Name.Substring(0, pos);
      pos = appPool.Name.LastIndexOf("\"") + 1;
      appPool.Name = appPool.Name.Substring(pos);

      /* And find the processId for this AppPool */
      property = mob.Properties["ProcessId"];
      appPool.ProcessId = Convert.ToInt32(property.Value);

      /* General process info, i.e: memory usage */
      property = mob.Properties["WorkingSetSize"];
      appPool.UsedMemory = int.parse(property.Value.ToString());

      /* Convert from Bytes, to MBs */
      appPool.UsedMemory = appPool.UsedMemory / 1048576;

      appPools.Add(appPool);

    }

    return appPools;

}


Although I've written this code in .Net 2.0, except for the Generics, I think it should work on 1.x too...

Monday, March 12, 2007

T From Type Generics #2

Generics are fun. but from the first day I started playing with it, I was intrigued by one main question: how to really make it dynamic.

The hole problem lays in T - how the hell, do I create an instance of a generic type???

To be more clear, I'll give an example:


Lets say I have the following class:


public class GenericChild
{ /* Some Code Here */ }


Now, I want to be able to create GenericChild objects dynamically - at runtime, like the following:


public static void Main()
{
  object child = CreateChild(Type.GetType("System.Collections.ArrayList");


How will you implement the "CreateChild" method?


Type.MakeGenericType
Thanks to Oliver Sturm, I found out, that the Type object has been quite extended,
Take a look at the answer:


public static object CreateChild(Type t)
{
  Type origType = typeof(GenericChild<>);
  Type genType = origType.MakeGenericType(childType);
  return genType.Assembly.CreateInstance(genType.FullName);
}


Ah, the wonders of Generics ;)

Tuesday, February 20, 2007

The Search For The Ultimate Icon

In the last couple of weeks, I've been working on a Windows Application,
And while doing so, I've been exposed to the never ending chase after the perfect toolbar icon or tray image, and I have to say - I don't like it.

Well, my dear WinApp friends, search no more!

Thanks to Serge for enlightening us,it turns out M$ has already solve this annoyance for us (though they didn't bother to let us know...).

If you got to the VS.Net (2005) install dir:
***:\Program Files\Microsoft Visual Studio 8\Common7\VS2005ImageLibrary
You'll find a nice zip file containing every icon, image, and even animation you've ever dreamed of! (no, there is no Angelina Jolie animation there...).

Sunday, January 21, 2007

Generic Vs. Generated Code

Most IT applications encounter the same challenges - whether its how to implement the best user experience or how to make the application as flexible as possible - these question will raise in every enterprise web application.
Than the only question on stand is - how to implement this?

A couple weeks ago I started a new job.
The first few weeks of a new job - to my opinion - are the most effective if you want to open your mind to new\different implementations - after all there is no one answer for any of these questions - each has its pro's and con's.

But I'd like to focus on one very basic difference between many of the existing solutions out there: should my framework be based on generic code that will know to handle a variety of scenarios and systems, or a set of wizards and code generators?

Why Should I Choose Code Generation?
1. Time: Yep, you can lower you eye-brow and think about it - how much lines of code are there in a framework like NHibernate, and how much are there in Wilson's OR Mapper?
Its not that I'm judging Wilson's complexity, on the contrary - although the time it takes to get a stable beta for a complex code generator is less the half the time it takes writing a generic code, in most cases it will support the same amount of scenarios and maybe even have more features (because it can enjoy the advantages of strongly-typed code).

2. Performance: Because of the nature of generic code, it must support a variety of scenarios, objects, context etc. - hence it will parse configuration files, load assemblies, use reflection, and many other performance killers, whereas when working with code generation, the code generated is designed for the specific page\scenario\object and will use no reflection or type casting whatsoever.

3. Debugging: When I first started using NHibernate, it was on one of the early betas (version 0.7 I think...), needles to say it was very unstable, but the most annoying thing was when I got an exception while using it - to start debug it and understand the cause of the bug took me a couple of hours since I needed to understand the "black-box" code.
In code-gen, the code is as simple as it gets which makes reading it a lot easier.

4. Ease Of Use: Drag N' Drop your entities, check the "Lazy-Loading" check-box, and vuala you've got yourself a fully featured DAL. no config file wars, no xml-schema lookups no tutorials to read.
Simply put - you need to no nothing (is it really an advantage?).
The amount time it takes to teach your users how to use a code-gen wizard is usually less the time it takes them to understand the xml structure of the "black-box" config file.

There are several more pro's to code-generation, and yet still they are usually not taken seriously, why?

There are several reasons, but to sum it all to 3 words: S - O - C. Separation Of Concerns.

In its nature, generated code is not stand-alone, it doesn't matter if it's in separate classes, files or even projects (though it might be enough in some cases), it is still strongly-coupled with your code, hence a change in your code will result in re-generational.

But this is the best-case scenario, think of a bug found in production, you have to re-compile the whole application because of a bug in your framework! whereas in "black-box" (generic code), you simply replace the framework assemblies (with care!).

Conclusion:
It's true, code-generation is sexier (I cant believe I say that!!!), but in real world (enterprise) applications, it's simply too risky.

Monday, January 8, 2007

Problems Installing IIS On Windows XP SP2

Hey,
Recently I've reinstalled XPSP2 on my machine, and had hard time installing IIS on it.
After some crawling on the net, I've found this work-around:

first, make a backup for this file:

%windir%\security\database\secedit.sdb

run this on command line:

esentutl /p %windir%\security\database\secedit.sdb

click ok on the message box, then install the IIS and insert the original winxp installation cd when prompted for files.

And vuala!

(Courtesy of Chaim)

Friday, December 15, 2006

JavaScript Properties

One of the most annoying limitations in Javascript - or better say in the java syntax, is that it doesn't support the C#\VB.Net property syntax.
So every time you want to create a property, you must create your own getter & setter like the following:


var _myProp;

getMyProp()
{
    return _myProp;
}
setMyProp(value)
{
    _myProp = value;
}


A couple of days ago I found a neat work-around for this limitation.

First, in the constructor, I'll define a span element which will be the host of our object:


function MyObject(id)
{
    this = document.createElement("span");
    this.id = id;
}


Next, I'll create the MyProp method:


this.MyProperty = function(){ return this._myProperty; }


Notice the behaviour of the MyProperty function is of a getter, now all we need to do is define our setter.

In order to do it, we use the span's onpropertychange event:



this.onpropertychange+=setterProxy;

function setterProxy()
{
    switch (event.propertyName)
    case "otherProperty":
        break;
    case "MyProperty":
        /* Here I can call my setter method */
        eval("setter_" + event.propertyName + "()");
        break;
}


And vuala we've got a getter & a setter just like in C#!

You can download the source-code of this example here

Sunday, December 10, 2006

Flexibility Vs. Complexity

One of the features in ASP.Net 2.0 is dynamic compilation - the ability to execute your asp.net code without the need to compile it first.
Instead ASP.Net has a FileSystemWatcher that check for changes in *.cs files and automatically reloads them.

Although this feature is good in many ways, I'd like to focus this post on a specific drawback - design time.

More Flexible Or Too Messy
The dynamic compilation has the same drawback like .Net 3.0's anonymous types do.
Whilst you do get more flexibility to your code\deployment, I find it hard to believe a good design-time support will be - or I dare say can be available.

Even today when your WebSite application becomes bigger than 50~ web-pages, it is very annoying that your Intellisense starts to act funny because you wrote textBox instead of TextBox in one of your classes.

In my opinion, although the wish to extend and to make the language richer and more flexible is good, it can easily make your code too complex to maintain.
A good example to this tradeoff, is the reason why multiple inheritance is not supported in the .Net Framework.

Wednesday, December 6, 2006

Generics - T constructor

A couple of days ago I found an irritating limitation in .Net 2.0 Generics.

Lets say I want to create some sort of a generic object factory, I'll define the following interface:


namespace Sternr.Tests
{
  public interface IGenericFactory
  {
    public T CreateInstance<T>();
  }
}


Where T is the type of object I want to create.
In .Net 1.x, if I wanted to create a new instance of a specified Type, I needed to use reflection, but in 2.0 you can use the following manner:


T newInstance = new T();


Which is prettier ;)
All you need to do to use this syntax, is declare that T has a default constructor:


public T CreateInstance<T>() where T: new()


For now, everythink looks good, but what happens if I want to make my factory smarter - and I want to support a parameterized constructs?
One would think the following should do the trick:


public T CreateInstance<T>() where T: new(object[] args)


But it turns out this syntax is NOT supported and will result in compilation error!

In order to overcome this limitation I had use my last resort - reflection...

Oh well, lets hope it's been fixed in 3.0...

Tuesday, December 5, 2006

Scriptaculous JScript Library

I hope I wont have a lot more of this kind of posts, but I found yet another cool client-side library and I thought it's worth blog about ;)

Scriptaculous is a cross-browser JavaScript library that enables you to really elevate the richness of your UI.

For example, all I need to do in order to make a certain div (or any other html element for that matter) have a phasing effect, I'll simple add the following line of code to the (client-side) onLoad event:


new Effect.Pulsate('theIdOfMyDivElement',{delay:3})


Or maybe you'd like to add a Switching effect to one element when another is clicked?
Here:


<div onclick="new Effect.SwitchOff('otherDivId')">
Click here for otherDivId to switch off!
</div>


Other features available are drag N drop, alert, stretching animation and many more.

Since Blogger is quite difficult when it comes to running jscript code, here's a link to the Scriptaculous demo page

Although most of the library is for creating UI effects, there are more to it, like an Ajax control kit, and DOM utilities - all of which are achieved with minimum scripting.

Sunday, December 3, 2006

Enhancing A Type Functionality

One of C# 3.0 new features is the extension methods - the ability to extend a specific types functionality.

For example, lets say I want to add the string object the GetFirstChar method, that returns the first char of the current string.
Today what I had to do, is create this static method, and call it like this:


string chr = Utils.GetFirstChar(myStr)


In 3.0, by creating the following method:

public static class Extensions
{
  public static int GetFirstChar(this string s)
  {
     return s.Substring(0,1);
  }
}

And now, I could use the following code on any string in my project:


string chr = myStr.GetFirstChar();


JScript Prototyping

Although this is pretty nice, today I found out you could do the same in JScript using the prototype syntax!
Have a look:


String.prototype.trim = function()
{
return this.replace(/(^\s*)|(\s*$)/g,"");
}


And now I can use:


var desc = document.getElementById("txtDescription").value.trim();


Damn, I'm starting to like this scripting stuff ;)

Thursday, November 30, 2006

A New Coding Standard

This post is a little off topic, but still interesting.
Instead of fighting Blogger every time I want to add some code snippet, a friend (Mushon saved me again ;)) sent me a nice tool called The Syntax Highliter, which is a set of javaScript libraries that automatically color your code!

Although it took me quite some time to make Blogger like my jscript code, but finally they became friends once again ;)

Here's an example:



All done!

Wednesday, November 29, 2006

FW 3.0 Enhancements

The .Net framework 1.1 was basically a big service-pack for 1.0, and 2.0 brought the Generics concept, but mainly focused on enhancing ASP.Net.

.Net 3.0 does not focus on a specific side of the framework, instead its goal is to enhance the flexibility of the language itself.

Lets have a look at some of these enhancements:

Implicit Variables
As minor as these feature might look, other features like LINQ rely heavily on it.
In C# 3.0, there's a new variable type - var (variant).
When a variable is declared as var, it's type will be chosen by the compiler based on the first variables initialization.
For example:


var x = 5; //the compiler will deal x as a simple int.

The only limitation is, that a variable declared as var must have an initializer,
For example, the next line will produce an error:
var x;

Note: Using implicit variables as a norm is NOT good, not because of performance issues (no boxing is made), but the code is less readable and you get minimum to no design-time support.

Anonymous Types
Following the implicitly typed variables, a complementary step is the ability to create an implicit type.
Lets have a look at the following code:


var myself = new { FirstName = "R", LastName="Stern", HasBlog=true};
var other = new { FirstName = "Slash", LastName="The" HasBlog=false };


I defined 2 implicit variables, and instantiate them as a new type that has 2 string properties and a Boolean.
If we look at the IL generated by this code, we'll get:


class __Anonymous1
{
private T1 f1;
private T2 f2;
private T3 f3;

public T1 FirstName { get { return f1 ; } set { f1 = value ; } }
public T2 LastName { get { return f2 ; } set { f2 = value ; } }
public T3 HasBlog { get { return f1 ; } set { f1 = value ; } }
}


Notice the compiler automatically generated a getter and a setter for each property in our type.
Furthermore, since both variables - myself & other has the same initializers, they are considered of the same type!

Lambda Expressions
Lambda expressions allows us to take anonymous methods to the next level.
Instead of writing these methods in the standard "verbose" way, why not simple describe it?
For example:
Instead of:


// get an array of string items in the collection that equal to 'A'
string[] AStrings = col.FindAs(delegate(string str)
{
if (sItem[0] == 'A')
return true;
else
return false
;
});


Consider the following:

string[] AStrings = col.FindAs(Func<string,bool> f = str => sItem=='A');


I'll continue the post tomorrow with some more examples.

WCP (Indigo) First Steps

To be honest I haven't tested it yet, but I thought I'd let you read it too until I post a proper post about it:
WCP Walkthrough