November 27, 2007

MMC Snapin creation

MMC Snapin Creation

There are 2 main versions of MMC available on Windows, MMC 2.0 (Windows 2000 and XP) and MMC 3.0 (Windows Server 2003). I'll mainly explain how to develop a Snap-in with MMC 3.0.

You can upgrade MMC 2.0 to MMC 3.0 using this install supplied by Microsoft

MMC 2.0 snapin:
Download the Platform SDK, Windows® Server 2003 R2 Platform SDK Web Install, from http://www.microsoft.com/downloads/details.aspx?FamilyID=0baf2b35-c656-4969-ace8-e4c0c0716adb&DisplayLang=en

Build an example from the Platform SDK install:
C:\Program Files\Microsoft Platform SDK\Samples\SysMgmt\MMC\mmc2.0\simple>nmake

MMC 3.0 snapin:

How to Develop and MMC 3.0 Snap-in (msdn)

How to create a Snap-in using MMC 3.0 (msdn)

MMC Snap-ins for MMC 3.0 can be developed with the Windows SDK, for information on the snapin classes see msdn Management Console
There is also an opensource .NET library at http://sourceforge.net/projects/mmclibrary

The MMC 3.0 application installation is at http://www.microsoft.com/downloads/details.aspx?FamilyID=61fc1c66-06f2-463c-82a2-cf20902ffae0&DisplayLang=en

Here's an example of how to build a simple Snapin

To develop MMC 3.0 snapins you'll need the microsoft.managementconsole.dll library. This library can be gotten by installing the MMC 3.0, found at http://www.microsoft.com/downloads/details.aspx?FamilyID=61fc1c66-06f2-463c-82a2-cf20902ffae0&DisplayLang=en
Add this library as a reference to your Snapin project and you'll have access to it's functionality.
.

You can also install the Windows Server 2003 R2 Service pack. Some example code is available on the web.

You Snapin is a Class Library project. It's main Class should implement the Microsoft.ManagementConsole.SnapInInstaller interface and override these 3 methods

public override void Install(IDictionary stateSaver);
public override void Rollback(IDictionary savedState);
public override void Uninstall(IDictionary savedState);

MMC 3.0 - A managed code 'task manager' MMC 3.0 snap-in

Installation
The procedure to install the MMC Snapin in MMC 2.0 and MMC 3.0 is different, see below for further details:

MMC 2.0 snapin:


Register the snapin with MMC:
C:\Program Files\Microsoft Platform SDK\Samples\SysMgmt\MMC\mmc2.0\simple\WIN2000_DEBUG>regsvr32 Simple.dll

MMC 3.0 Snapin
This snapin was build with MMC 3.0 as ManagementConsoleSnapin.dll

The resultant DLL, C:\MySnapinProject\bin\Debug\ManagementConsoleSnapin.dll, can be installed as a snapin to MMC 3.0 as follows: >C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\installutil.exe C:\MySnapinProject\bin\Debug\ManagementConsoleSnapin.dll

and uninstalled using:
>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\installutil.exe /u
C:\MySnapinProject\bin\Debug\ManagementConsoleSnapin.dll

After installation the snapin appears in the MMC Snapin list as "My Management Console". Add the snapin to MMC and select OK. The Snapin is now ready for use.

MMC Snapin Debugging
The easiest way to debug the MMC while installing the Snapin is to set the Project Properties of your snapin project, in the project properties Debug tab select 'Start External Program' and enter 'C:\WINDOWS\system32\mmc.exe' in the field. Now when you hit F5 the MMC app will launch, you now 'Add\Remove Snapin' from the MMC's File menu.


October 15, 2007

Handling SoapExceptions

SoapExceptions are thrown from WebServices when a problem occurs. The SoapException will occur whenever any type of Exception occurs in the WebServices code
e.g. if an IOException occurs it will bubble up to the caller as a SoapException, unlike other Exceptions the origninal Exception is not easily extracted, for instance by using the InnerException property.

Because of this you must handle the SoapException in the sender and the caller. Yuo must stuf your Originals details into a new instance of a SoapException and then throw it. The original Exception's details are contained in the Details property of the SoapException but you still have to do some work to extract it.
Also remember that WebServices return XML, the SoapException is also returned as XML, so our extraction code will need to know how to identify the inner exception and how to extract it from the correct XML Element.

One thing you may wish to do with the SoapException is extract the original Exceptions details. Here's how to achieve this:
First you must catch the SoapException
try
{
}
catch(System.Web.Services.Protocol.SoapException se)
{
//Somehow extract the details from the SoapException, I'll explain how to do this now
}

In here you must extract the SoapExceptions details. This is not as easy as a normal Exception, really to get the details you have to know the format in which they were entered. So you should throw the SoapException with the Details you want from within the WebService yourself.

You do this by stuffing entries into the Details property of the SoapException before throwing it.
using System;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

using System.Xml.Serialization;
using System.Xml;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class SoapExceptionSupplier : System.Web.Services.WebService
{
public SoapExceptionSupplier () {

//Uncomment the following line if using designed components
//InitializeComponent();
}

[WebMethod]
public string HelloWorld()
{

try
{
throw new System.IO.IOException("An IOException has been thrown");
}

catch(Exception e)
{
// Build the detail element of the SOAP fault.
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
System.Xml.XmlNode node = doc.CreateNode(XmlNodeType.Element, SoapException.DetailElementName.Name, SoapException.DetailElementName.Namespace);

// Build specific details for the SoapException.
// Add first child of detail XML element.
System.Xml.XmlNode message = doc.CreateNode(XmlNodeType.Element, "Message", "http://tempuri.org/");
message.InnerText = e.GetType().ToString();
// Append the two child elements to the detail node.
node.AppendChild(message);

// Build specific details for the SoapException.

// Add first child of detail XML element.
System.Xml.XmlNode details = doc.CreateNode(XmlNodeType.Element, "Details", "http://tempuri.org/");
details.InnerText = e.Message;
// Append the two child elements to the detail node.
node.AppendChild(details);
SoapException se = new SoapException("Fault occurred", SoapException.ClientFaultCode, Context.Request.Url.AbsoluteUri, node);
throw se;

}
return null;
}

}


The code above is a WebMethod, I've thrown a System.IO.IOException, this is caught and a SoapException is thrown instead, the reason for this is that I am actually embedding Details in the SoapException before it's thrown, if I simply threw the
System.IO.IOException it would be wrapped in a SoapException by the WebService and I would find it very difficult to get any information from it on the Callers side.

In the Catch I construct a XML Document and create a XMLNode, this mode is populated with Details of the Exception thrown, I then pass the XMLNode into the SoapException and throw it.
Now on the Callers side I know what to expect and can check the SoapException for these details using the SoapExceptions Details property.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;

using System.Windows.Forms;
using System.Xml;

public partial class _Default : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
localhost.SoapExceptionSupplier soapExSupplier = new localhost.SoapExceptionSupplier();
try
{
//Call the WebMethod I listed earlier
soapExSupplier.HelloWorld();

}
catch (System.Web.Services.Protocols.SoapException soapEx)
{
XmlDocument doc = new XmlDocument();

//First the Error message (Exception type)
MessageBox.Show("Error Message : " + soapEx.Message);

//Now the Detail, more detail on the exception.
doc.LoadXml(soapEx.Detail.OuterXml);
XmlElement root = doc.DocumentElement;
string result =string.Empty;

foreach (XmlElement child in root.ChildNodes)
{
result += child.InnerText;
}

MessageBox.Show("Error Detail : " + result);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}

Here I catch the SoapException just thrown by the WebMethod. I construct a XMLDocument from the SoapExceptions Detail properties OuterXML. I extract each XmlElement from this XmlDocument, this will contain the contents I stuffed into the SoapException in the WebService.
Done.

September 24, 2007

SilverLight

SilverLight is a Microsoft API for delivering dynamic media content to your web application

http://www.microsoft.com/silverlight/

August 16, 2007

DynamicMethod, IL Code, CreateDelegate

In a previous post, dotNET - Under the Hood, IL Assembly, I briefly described how to write some IL Code to an Assembly, but what if at a later occasion you'll want to invoke these methods from the dll.
This could be achieved by loading the assembly in an AppDomain and then invoking the methods within ????
Or you could use what are known as DynamicMethods to invoke the methods.

DynamicMethod is a class that also resides in the System.Reflection.Emit namespace. Why would you want to use DynamicMethod? it's useful when you want to load methods into memory or write methods in memory and invoke later.
We can write IL code in memory in the exact same was as we wrote IL code earlier using the MethodBuilder.

In my experience DynamicMethod is a bit tricky to get right especially when you try to invoke your Dynamic method. The problem I found was with the constructor parameters, what do they mean;
There are 6 constructor overloads in all;
half of these are associated with an class instance i.e. you supply a Type as one of the constructor parameters, the significance of this is that it gives you access to reference private data within the type.
The other half of the constructor overloads are associated with the Module i.e. the dll and not a type, the significance of this is that it does not give you access to private types data.
from msdn:
DynamicMethod (String, Type, Type[], Module) Creates a dynamic method that is global to a module, specifying the method name, return type, parameter types, and module.
DynamicMethod (String, Type, Type[], Type) Creates a dynamic method, specifying the method name, return type, parameter types, and the type with which the dynamic method is logically associated.

There's also another caveat which is a boolean option to skip the JIT checking. This means some verification of the parameter types which is usually done by the JIT is skipped.
DynamicMethod (String, Type, Type[], Module, Boolean) Creates a dynamic method that is global to a module, specifying the method name, return type, parameter types, module, and whether just-in-time (JIT) visibility checks should be skipped for members of all types in the module.
DynamicMethod (String, Type, Type[], Type, Boolean) Creates a dynamic method, specifying the method name, return type, parameter types, the type with which the dynamic method is logically associated, and whether just-in-time (JIT) visibility checks should be skipped for members of other types in the module.

And there's one more caveat, CallingConvention,......

DynamicMethod dynamicMethod = new DynamicMethod(

"MyMethod"),
typeof(object),
new Type[] { typeof(object[]), typeof(object[]) },
typeof(MyClass));

The instance of DynamicMethod results in a method with the following signature
MyClass
{
object MyMethod(object[], object[])
{
}
}
You now have to insert your own IL code is the methods like Emit, again see my other post, dotNET - Under the Hood, IL Assembly, you write the IL code in the same manner.

Now you want to Invoke the method you've just created. This can be done in 2 ways, one call Invoke on your instance i.e.
dynamicMethod.Invoke();
or create a Delegate and then call Invoke on that delegate. The advantage of this over the first option is that you supply the correct parameters here and then just call Invoke on it later, the first option requires you to call Invoke here and now.
I'll explain the second option here:
DynamicMethod.CreateDelegate is a method used to invoke a piece of IL code. It creates a Delegate as the name suggests. The Delegate must have the identical signature to the DynamicMethod instance which is calling CreateDelegate.

public delegate object CompiledMethod(object[] arguments);

//As the delegate above defines, our DynamicMethod must return an object, and take an array of objects as parameters, it's also tied to the type "Example".
dynamicMethod = new DynamicMethod(
"",
typeof(object),
new Type[] { typeof(Example), typeof(object) },
typeof(Example)
);

// Get a FieldInfo for the private field 'id'.
FieldInfo dynamicMethodFid = typeof(Example).GetField(
"id",
BindingFlags.NonPublic | BindingFlags.Instance
);

ILGenerator dynamicMethodIlg = d.dynamicMethod.GetILGenerator();

dynamicMethodIlg.Emit(OpCodes.Ldarg_0);
dynamicMethodIlg.Emit(OpCodes.Ldfld, dynamicMethodFid);
dynamicMethodIlg.Emit(OpCodes.Ldarg_0);
dynamicMethodIlg.Emit(OpCodes.Ldarg_1);
dynamicMethodIlg.Emit(OpCodes.Stfld, dynamicMethodFid);
dynamicMethodIlg.Emit(OpCodes.Ret);

CompiledMethod result = (CompiledMethod)d.dynamicMethod.CreateDelegate(typeof(CompiledMethod), d.ex);

The CreateDelegate has 2 constructor overloads, one which takes and instance of an object as the second parameter (Instance) and another which does not (Static).
The difference being at invokation time, if you created your delegate using the instance method you do not have to supply the instance at invokation time.
If you created your delegate using the Static method you must supply the instance at invokation time e.g.

Instance
public delegate int UseLikeInstance(int newID);//delegate declaration,i.e. when your invoking the delegate you must supply a value only, no instance.
UseLikeInstance uli = (UseLikeInstance) d.changeID.CreateDelegate(typeof(UseLikeInstance, d.ex));//instantiation, instance required

uli(1492); //Invokation, no instance

Static
public delegate int UseLikeStatic(Example ex, int newID);//delegate declaration,i.e. when your invoking the delegate you must supply an Instance and a value.
UseLikeStatic uls = (UseLikeStatic) d.changeID.CreateDelegate(typeof(UseLikeStatic));//instantiation, NO instance required
uls(d.ex, 1492); //Invokation, instance required

The following I'm not too sure about!

The resultant delegate looks the same, it has a Method and a Target. The Method is the DynamicMethod you've just created and the Target is the instance you provided. When the Delegate is invoked if the IL code within the DynamicMethod requires an instance of an object in order to run then it looks in the Target. If at invokation time this Target is null or is of the wrong type an Exception will be thrown.
The Target is created when you use the CreateDelegate, at this time the instance must exist, you can later set this same instance to null before invokation of the delegate, this must mean that a copy of the instance is added to the Target at runtime and the original can be done away with.

The Target object (instance) is a point of confusion for me! when is it required and when is it not? It's when the DynamicMethod's IL uses instances that are already on the stack, this is a achieved with
Idlem.ref
this gets a reference to an object which resides on the stack.
This is where the Target comes it, it is the instance that gets used.
Then this instance is used for something such as a call to another external method.



The above is not yet complete

August 14, 2007

Enumerator(s)

You've all used the foreach loop in .NET to get the values in a container. The foreach actually uses that objects Enumerator.
In order to allow the use of the foreach on an object the class must implement the IEnumerable.GetEnumerator method which also means you have to implement the IEnumerable interface. Within the GetEnumerator override you need to return an instance of IEnumerator, so you need to create a class that implements the IEnumerator interface. see the code.

This is useful if you class contains a member variable which is an or even a container. Let's say it's an array. When an instance of your class is create the array is also instantiated. But you don't want the array to be visible but you do want clients to be able to use a foreach on your class instance, this can be achieved by implementing the IEnumerable interface and overriding the GetEnumerator method.


using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace Enumerator
{


public class Person
{
public Person(string fName, string lName)
{
this.firstName = fName;
this.lastName = lName;
}

public string firstName;
public string lastName;
}
public class People : IEnumerable
{
private Person[] _people;
public People(Person[] pArray)
{
_people = new Person[pArray.Length];

for (int i = 0; i < position =" -1;" _people =" list;" position =" -1;" peoplearray =" new" peoplelist =" new">


System.Collections.IEnumerable

Yield

This is a keyword in .NET, it's placed before the return value where your implementation of IEnumerable.
When you use yield your actually replacing the requirement for an Enumerator, Yield acts as the Enumerator. So if your iterating through your own type (a class made by yourself) you's usually have to create an implemetation of the IEnumerator interface to tell the foreach for example how to move to the next item in the list i.e. MoveNext(). Now you can use the Yield keyword instead which saves you work.

The Yield actually returns a value from the collection and then goes back to the loop and gets the next value in the loop, remembering the context.

The Yield keyword can be used in your IEnumerable implementations GetEnumerator() method or in the foreach itself.
This can be done in the IEnumerable's GetEnumerator() method
e.g.
public IEnumerator GetEnumerator()
{
for(int i=0;i<_people.length;i++)>
yield return _people[i];
}
instead of
public IEnumerator GetEnumerator(){
return new PeopleEnum(_people);
}
which uses an implementation of IEnumerator, which in turn returns the array of _people, to return the enumerator

If you want to return an Enumerable list from a method i.e. you want to return a list of object which you can iterate through from a method you'll need to use the yield keyword.

The keyword yield is required when returning an IEnumerable object from a method like so


public static IEnumerable DoSomething()
{
int counter = 10;
int result = 1;
while (result <>

August 13, 2007

Security in Assemblies

Code Security is all about allowing and preventing code from running.

The .NET Security Model works by the assemblies each having their own Evidence embedded in the Assembly by the Assembly writer.
When the CLR loads the assembly it then reads and applies this Evidence to a Security model and this in turn returns Permissions, depending on what Permissions are returned will determine is the assembly is permitted to execute or not.
So it's Evidence in (on the assembly) -> Code Groups -> Permissions.

Code Access Security (CAS) is the the mechanism used by .NET to manage all of this. It's function is to process assemblies and determine the runtime permissions they should have, e.g. should they code within a certain assembly be allowed to run or not.

All assemblies have Evidence. As the CLR is loading the assembly it looks at this Evidence and processes it using the current machines .NET Code Group. Depending on where the assembly is being loaded from, the Evidence it has, the Code Group configuration on the current machine; will determine the Permissions that assembly gets.

Evidence: Evidence takes into account the assemblies strong name, publisher. There are 2 types of evidence Host Evidence and Assembly Evidence. Host Evidence is all about where the code is being loaded from, internet, local machine these are identified by URI, Site and Zones (Zones are for non internet)

Code Group: You can group permissions for assemblies i.e. all assemblies that have Internet permissions can do such and such. These are setup on the machine, when the CLR is processing the assemblies Evidence it tries to match the output with a Code Group.

Permissions: FullTrust, Internet. Have special meaning to the CLR, these restrict the access of code to resources, resources such as printers, applications etc.


August 08, 2007

dotNET - Under the Hood, IL Assembly, MSIL, ILGenerator, MethodBuilder

IL (Intermediate Language) is also referred to as MSIL (Microsoft Intermediate Language) or even ILAsm which is the same thing. IL is the code which your source code (C#, VB.NET etc) is compiled into. When you EXE or DLL is run these IL code is converted to a machine language particular to the present machine i.e. if the current machine being used to run the application is a Windows 2000 machine the IL will be converted into Windows instructions before running on the x86 processor (processor architecture used for Windows machines).

When you're developing with .NET languages with a Development tool such as Visual Studio 2005 the compiler you use will generate the correct/valid IL for you, but what if you want to create your own IL for some reason! One reason could be that you've developed your own Language and would like it to run on .NET, in this case you'll need to write out some sort of Assembly, be it EXE or DLL, with IL code. To do this you can use some Classes available in .NET API, these classes reside within the
System.Reflection.Emit namespace. I'll explain how this is achieved later.

There are also some tools which are used to compile and decompile the IL code, ILASM (all caps means this is the compiler and not the language ILAsm) is the IL compiler and ILDASM is the IL Decompiler (allows the reverse of compilation, you can create .NET language source code from an IL assembly).

An IL assembly contains 2 things, Metadata and Managed Code. Metadata is information which describes the structures and methods within the assembly. The Managed Code is the actual IL code, it is stored in the assembly in Binary form, managed means that the Runtime controls it.

The assembly has 2 main components, the metadata and the code. At runtime the assembly is loaded, the metadata is read first to find the descriptions of the structures and methods, the JIT compiles the IL code in the assembly into machine code using the metadata. When a method is required the machine code for that method is executed (incidentally this is what differentiates this from an Interpreter).

PE and COFF are additional data embedded in the assembly to describe an EXE, we'll not worry about them here.

Contents of the Assembly:
The assembly contains one or more Modules. An Assembly may or may not have multiple modules but it must have at least one i.e. the Prime Module. The Prime Module contains a
Metadata section which describes the contents of the Assembly, An Assembly Identity section and maybe some actual IL code. The Assembly may also contain additional Modules which each have their own Metadata and IL Code sections.


Boxed/Boxing and UnBoxed/UnBoxing:
You'll see these two terms appearing whenever you deal with IL, for you C++ developers you may have heard of the term before. It's related to Reference types and Value types, reference types are objects on the Heap to which a variable points, value types are not on the Heap and the variable contains the value in it's own memory location. This can be seen in the IL code. Reference types are more expensive, in terms of processor and memory, than Value types.

Boxing is the conversion of a value type to a reference type at compile time i.e. the value is contained in a variables memory location, for some reason (such as passing the value by reference, maybe as a method parameter) you want to convert your value type to a reference type. This means that a bit copy is made of the value type and instance of a Class is created with that copied value.

UnBoxing in the conversion of reference type to value type at compile time i.e. in your source code a variable points to a memory address on the Heap, you new-up an Object, when you compile the object is Boxed meaning the IL code is written for that Object, the memory required is allocated in IL code.
Int32 unBoxed = 20;//Unboxed
Object boxed = unBoxed;//Boxed
Int32 unBoxedBoxed = (Int32)boxed;

Here's the IL code generated for the C# source code above
.entrypoint
// Code size 19 (0x13)
.maxstack 1
.locals init ([0] int32 unBoxed,
[1] object boxed,
[2] int32 unBoxedBoxed)
IL_0000: nop
IL_0001: ldc.i4.s 20
IL_0003: stloc.0
IL_0004: ldloc.0
IL_0005: box [mscorlib]System.Int32
IL_000a: stloc.1
IL_000b: ldloc.1
IL_000c: unbox.any [mscorlib]System.Int32
IL_0011: stloc.2
IL_0012: ret
Here's a great article on Boxing from msdn magazine.


When playing around with IL code and reflection you may want to invoke a method within an assembly. If you are writing the assembly you may want to write it using IL code, to do this you would use the MethodInfo class found in the System.Reflection.Emit namespace. Once you'd created your methodinfo you can write IL code directly to that method and then save all to a dll later using the ILGenerator class, this ILGenerator can be thought of as the writer of the IL code and a reference to this is gotten from the MethodInfo instance you've just created
// create a dynamic assembly and module
AssemblyName assemblyName = new AssemblyName();
assemblyName.Name = "HelloWorld";
AssemblyBuilder assemblyBuilder = Thread.GetDomain().DefineDynamicAssembly(
assemblyName, AssemblyBuilderAccess.RunAndSave);

ModuleBuilder module;
module = assemblyBuilder.DefineDynamicModule("HelloWorld.dll");

// create a new type to hold our Main method
TypeBuilder typeBuilder = module.DefineType(
typeof(Example).Name,
TypeAttributes.Public TypeAttributes.Class);




// create the Main(string[] args) method
MethodBuilder methodbuilder = typeBuilder.DefineMethod(
DynamicMethod.GetCurrentMethod().Name,
DynamicMethod.GetCurrentMethod().Attributes,
DynamicMethod.GetCurrentMethod().CallingConvention,
changeID.ReturnType,
new Type[] { typeof(Example), typeof(int) });

Type t = changeID.DeclaringType;
// generate the IL for the Main method
ILGenerator ilGenerator = methodbuilder.GetILGenerator();


// Push the current value of the id field onto the
// evaluation stack. It's an instance field, so load the
// instance of Example before accessing the field.
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldfld, fid);

// Load the instance of Example again, load the new value
// of id, and store the new field value.
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldarg_1);
ilGenerator.Emit(OpCodes.Stfld, fid);


// The original value of the id field is now the only
// thing on the stack, so return from the call.
ilGenerator.Emit(OpCodes.Ret);

// bake it
Type helloWorldType = typeBuilder.CreateType();
assemblyBuilder.Save("HelloWorld.dll");


A useful reference for deeper understanding of how .NET works under the hood is the Microsoft opensource .NET project "Shared Source Common Language Infrastructure" codenamed "Rotor", it's an opensource version of .NET and can be used for discovering more about .NET code, there's also a book and it's available from googledocs, see my bookmarks.

June 12, 2007

Design Patterns - Visitor Pattern

The Visitor Pattern is a solution for a problem where you have many Objects, each Object is similar but you wish to extract information (such as a print statement) on each Object in a different way.
E.g. You have a collection of Objects, each of your objects has different member variables and you want some way to call print this info. One way to do it would be to cycle through each object and Call some common method on each such as Print(), this ties the Object tightly to the printing or whatever you are doing, we want to loosly couple the printing or whatever to the object itself, to unbind the Printing from the actual Object we introduce 2 interfaces. The Visitor and the Visitable.
The Visitor interface has a Visit(object) method (this is what would print the details).
The Visitable interface has an Accept method, this takes the Visiting object as a parameter.
The Object we want to print implements the Visitable interface, this has a callback to the implementor of the Visitor Interface, this callback is required because it is actually the implementor of the Visitor that does the printing.
The implementor of the Visitor has a visit(Object) method for each Object type, this removes the need for Use/Case statements for each Object type.

using System;
using System.Collections.Generic;
using System.Text;

namespace VisitorPattern
{
interface Visitor
{
void visit(Car car);
void visit(Bus bus);
}

interface Visitable
{
void accept(Visitor visitor);
}

class Car : Visitable
{
public void accept(Visitor visitor)
{
visitor.visit(this);
}
}

class Bus : Visitable
{
public void accept(Visitor visitor)
{
visitor.visit(this);
}
}

class PrintVisitor : Visitor
{
public void visit(Car car)
{
Console.WriteLine("Visiting car");
}
public void visit(Bus bus)
{
Console.WriteLine("Visiting bus");
}
}

public class VisitorDemo
{
static public void main(String[] args)
{
Visitable[] objects = { new Car(), new Bus() };
Visitor visitor = new PrintVisitor();
foreach (Visitable visited in objects)
{
visited.accept(visitor);
}
}
}
}

May 08, 2007

Installer (MSI) - Windows Installer general information

Aaron Stebner's Blog

Common problems I've found while playing around with the creation of Windows installers is that if you break the uninstaller functionality it's very difficult to uninstall at all.
There are a couple of ways to attempt to repair, this
1. Force overwrite of the installer with a known good installer and then uninstall.
msiexec.exe /fvecmus
2. Repair the installer with a known good installer (Control Panel->Add/Remove Programs, locate you Applications installer and select "Click here for support Information", then select Repair from the resultant dialog, now point to a new location of a good installer)
Then Remove.
3. Use a tool name MsiZip.exe, it's available with the
MS Windows SDK, it cleans up the registry (the SDK installation takes quite a while).
4. A
Windows Installer Cleanup Utility.

The windows installer keeps a list in the OS of files installed by the installer, if you cannot uninstall because windows thinks one of these files is being used then try option 1 above.

April 17, 2007

BootStrapper BootStrapping

Bootstrapping is the creation of a wrapper installer around already existing installars or files.
It's useful if you have multiple installation files that you'll like the user to install in on step.

The Bootstrapper itself is a .exe installer file, it also may have .SED file which contains details of the contents of the .exe.

There are a few applications out there to generate a bootstrapper, the most simple I've seen is the an app called IEXpress.
IExpress
Is actually installed on windows (System32/iexpress.exe).
This creates an installer, you tell it what files you wish it to include in the installation.
I've only played with this so far and it appears to me that the isntaller can only install upto 2 setup.exes. You can include as many files as you like, but the files cannot have the same name, because of this you will probably need to rename your setup.exes to something else because you cannot have 2 files with the same name.
After you've included all the files you wish to run the next step asks you which files you wish to run, at this stage it looks like you can only specify upto 2 .exe installer files (there maybe a way around this, by editing the .sed file afterwards).
Also the final step I recommend telling the bootstrapper to use full files paths, this seems to ensure it works.

Visual Studio
In Visual Studio the BootStrapper is read in as an XML file. Visual Studio has a set BootStrapper XML file which it reads, below I will describe how to use this default bootstrapper and then I will describe how to create your own.
Using the BootStrapper in Visual Studio
Visual Studio also has a Bootstrapper, it's actually the Launch Conditions Editor in the Setup Project. The prerequisites are what your looking for, you'll see .NET is there by default.

By right clicking the Setup Project and bringing up the Properties dialog you'll a prerequisites button, this launches another dialog which lists the prerequisites, only the default ones are there.

There is a snag with this however you can to add your own you'll need to create your own BootStrapper XML file
Create your own BootStrapper file
There are 2 ways to create the XML file
1. Write the XML file yourself and copy to the correct location:
you'll need to follow the instructions in the .zip found in the BootStrapper SDK
2. You can use an Community UI (BMG) to write the bootstrapper for you (note the web installer doesn't work funnily enough, the msi does, the program can then be found at C:\Program Files\Microsoft\Bootstrapper Manifest Generator\BMG.exe).
It allows you to add .msi files, .exe files and apply conditions for them. It also installs the bootstrapper xml file for you after, this makes it available in Visual Studios Setup Project Prerequisite dialog that I mentioned earlier.
Here's a complete description of how to install you Custom Prerequisite.
Use the Visual Studio 2005 Bootstrapper to Kick-Start Your Installation - This article is the complete version and is not msdn, Also describe Custom bootstrapping.
Adding Custom Prerequisites.

MSBuild GenerateBootStrapper Task
After you've created your Visual Studio BootStrapper you can use it with MSBuild with the GenerateBootstrapper Task.
This MSBuild task allows you to include your custom prerequisite in any Visual Studio Project.
So if you wish to create a Bootstrapper for your installer using MSBuild it's the same thing as Adding Prerequisites to your Setup Project using the Project->Properties->Prerequisite dialog.
You'll still need to have your prerequisites created and installed beforehand.
Here's and example of a project to create a BootStrapper using 2 Prerequisites:


<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectGuid>{7447AF9B-33E3-41AE-9D88-833704524543}</ProjectGuid>
</PropertyGroup>
<ItemGroup>
<Content Include="MyOriginalInstaller.msi">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
<Target Name="Bootstrapper">
<GenerateBootstrapper
ApplicationFile="MyOriginalInstaller.msi"
ApplicationName="MyInstallerName"
BootstrapperItems="@(BootstrapperFile)"
ComponentsLocation="Relative" Culture="en" FallbackCulture="en-IE" CopyComponents="True"
Validate="False"
OutputPath="$(OutputPath)"
Path="C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bootstrapper" />
</Target>
<ItemGroup>
<BootstrapperFile Include="Microsoft.Net.Framework.2.0">
<ProductName>.NET Framework 2.0</ProductName>
</BootstrapperFile>
<BootstrapperFile Include="ProjectAggregator2">
<ProductName>ProjectAggregator2.msi</ProductName>
</BootstrapperFile>
</ItemGroup>
</Project>


We're creating a BootStrapper called MyInstaller.msi.
We're setting our main Installer (the one whose Gui appears) to be "MyOriginalInstaller.msi".
We include this same main installer "MyOriginalInstaller.msi" in the current project, it appears that it must be found in the current project in order for this to work.
We include to pre-requisites which get installed beforehand, their ProductName must be identical to the folder name that appears in their installation location
C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages
e.g.
C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\BootStrapper\Packages\ProjectAggregator2.msi\

ClickOnce FAQs (installsite.org)

April 16, 2007

dotNET Custom Attributes

Attributes those snippets of code you see in .NET classes in square brackets at the top of Class or Method, one of the most common examples is [WebMethod] to indicate that the current method is a WebMethod.
The Attribute is in fact a class that inherits from System.Attribute. The Attribute is read in at Runtime, Reflection takes care of this. Attributes are useful for flagging types, conditions when and when not to use certain methods like the WebMethod.

April 04, 2007

WiX - Windows Installer XML

Latest Release ('Rosario' November CTP msdn) now has Visual Studio Integration.
WiX Tutorial (tramontana).
WiX documentation (sourceforge).
WiX and Visual Studio (msdn forum).
WiX integration in Visual Studio using Votive (Votive blog).
WiX integration (msdn).
WiX Forum.
Building setup packages for Visual Studio project templates and starter kits (Aaron Stebner's WebBlog)
WiX Tallow tool

WiX is a methodology to write installers.
WiX has a compiler/linker (candle/light) which may give the installer writer some validation before deployment.
The contents of the end installer (.msi) are edited using an XML file.
I haven't found WiX to be advantageous over the ordinary Visual Studio Setup Project.
Visual Studios SDK has a project template (from Votive) for creating WiX installers. This project template gives you the skeletol wix file to start and the build commands are built into the project, all you've to do is create new GUIDs ,these guids are only for the installer, they've nothing to do with your applications GUIDs, the WiX compiler, candle.exe, will complain if you fail to change one anyway.
The addition of items to install is done be editing the WiX xml file! if you choose to use it with Visual Studio , the Votive version (present Wix 2) then you'll get Intellisence, that with the Candle compiler are very useful but editing xml files is very tedious.
You'll also note that this version does not support integrated Visual Sourcesafe in Visual Studio, I found this a disadvantage. However WiX 3 (presently in developer status) does have this but lacks other vital components at present, such as it does not support the gui components you require for user input in the installer. In WiX 2 these are provided by the SDK in the wixui.dll.

All in all I don't think WiX is up to scratch just yet but WiX 3 does look promising.

There's a tool now called Tallow which included in the WiX SDK, apparently it's a command line tool that allows you to create a WiX installer be passing in you file locations and registry settings on the command line.

WiX pre-processor table (these items can be added to your WiX file, they are replaced at compile time).

Preprocessor VariableExample Variable UseExample Variable Value
var.<Project>.ConfigurationName$(var.MyApp.ConfigurationName)Debug.NET
var.<Project>.ProjectDir$(var.MyApp.ProjectDir)C:\code\msdn\MyApp
var.<Project>.ProjectDosFileName$(var.MyApp.ProjectDosFileName)MYAPP.CSP
var.<Project>.ProjectExt$(var.MyApp.ProjectExt).csproj
var.<Project>.ProjectFileName$(var.MyApp.ProjectFileName)MyApp.csproj
var.<Project>.ProjectName$(var.MyApp.ProjectName)MyApp
var.<Project>.ProjectPath$(var.MyApp.ProjectPath)C:\code\msdn\MyApp\MyApp.csproj
var.<Project>.TargetDir$(var.MyApp.TargetDir)C:\code\msdn\MyApp\obj\Debug
var.<Project>.TargetDosFileName$(var.MyApp.TargetDosFileName)MYAPP.EXE
var.<Project>.TargetExt$(var.MyApp.TargetExt).exe
var.<Project>.TargetFileName$(var.MyApp.TargetFileName)MyApp.exe
var.<Project>.TargetName$(var.MyApp.TargetName)MyApp
var.<Project>.TargetPath$(var.MyApp.TargetPath)C:\code\msdn\MyApp\obj\Debug\MyApp.exe
var.SolutionDir$(var.SolutionDir)C:\code\msdn\MySetup
var.SolutionDosFileName$(var.SolutionDosFileName)MYSETUP.SLN
var.SolutionExt$(var.SolutionExt).sln
var.SolutionFileName$(var.SolutionFileName)MySetup.sln
var.SolutionName$(var.SolutionName)MySetup
var.SolutionPath$(var.SolutionPath)C:\code\msdn\MySetup\MySetup.sln

January 30, 2007

Visual Studio Extensibility

http://feeds.delicious.com/rss/learnerplates/extensibility

Extending the Visual Studio IDE means adding custom functionality to the IDE, this could be custom TextEditors, Add Ins to the Tools menu, Writing to the Output Console, basically anything that will require you to add or write to any component in the Visual Studio IDE.

Extending the Visual Studio IDE is not for the faint hearted. It is implemented with a Visual Studio Extensibility SDK downloadable from link 1 below. It's implemented using COM interfaces (not very nice).
There are 5 points of contact for Extensibility issues
1. MSDN Visual Studio SDK homepage.
2. MSDN documentation.
3. MSDN Extensibility Forum.
4. Dr. Ex's Weblog.
5. MZ-Tools.
There are also webcasts available from msdn.

I recommend watching some of the webcasts especially the Managed Package Framework as the explain briefly how some of the Class Attributes work with RegPkg.exe and how important the GUIDs are.

GUIDs
The GUIDs are static and each control and component in the VS environment should have one, if they have a static GUID it means that Visual Studio will persist that same object for all instance of Visual Studio, this means that if you create your own Control, say a Form, if you do not give it a static GUID a new Form object will be created each time it's launch from VS, if you give it a GUID then that same Form object will be used each time, the result of this is that if you change the size or something of that Form object then the next time the Form is shown it will pertain that size set.


Visual Studio Features
Some more detailed features of Visual Studio Extensibility are:
Language Services - Create your own language with Visual Studio TextEditor highlighting and intellisence etc, msdn.
Aaron Martin's Webblog - Managed Language Tools in Visual Studio SDK.

VSPackages - VSPackages allow your application to consume services provided by VSSDK. Your VSPackage implementation must implement the Package base class, this requires implementation of various Interface methods.
To create your own Project type i.e. your own project name type appears in the open dialog is quiet difficult, you'll need to create a VSPackage, see the steps below:

Steps To Create your own Custom Project Type using VSPackages
Steps To Create Your First VSPackage.
1. To create a VSPackage just use the File->New Project->Other Project Types->Visual Studio Integration Package,

2. After this has been created you can immediatly hit F5, this will install this with the Visual Studio Experimental Hive and launch it, you should see a new Project Type listed in the Visual Studio Help, but it probably will not appear in the File->New Project dialog just yet, this requires some more work....

Tip: By hitting F5 you install your application into Visual Studio, the VSPackage template has included some commands in the build an Debug to do this for you. What it actually does in install your project in a developer sandbox called the Experimental Hive. This is is a location in the registry which you can play with, to Reset the Experimental Hive at any time goto the Start Menu->Visual Studio SDK->Tools->Reset Experimental Hive, this removes all memory of Project, add ons, item templates etc that you may have installed.

Tip: Each time you hit F5 it should rebuild you project and install it, sometimes this does not complete, you'll see in the Visual Studio installation there are an number of subfolders, there are 2 in particular we are interested in

C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\ProjectTemplatesExp

C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\ProjectTemplatesCacheExp

The Cache is populated with the unzipped version of what is in the non-cache version, and this is what Visual Studio actually uses to find the project templates. This does not always get updated however, to ensure that it does add this command to you Project's Post Build Event

"C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exe" /rootsuffix Exp /setup

or
"C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\devenv.exe" /rootsuffix Exp /InstallVSTemplates

devenv.exe switches (msdn).

3. You now have you own VSPackage but you'll also want your own Project extension (something other than the default .csproj).
You'll need this because if you wish to create Templates to group under your Project Type they'll have a Project Type the same as what you've defined, when you create new project with one of your templates you will want to add Items to the project.
In order for Items to appear in the dialog they will need to also have a type the same as your project type, this depends on the extension of your project i.e. if you leave the default extension .csproj then when you add and item to your project you'll only see the CSharp items, you'll need to change the extension to something like .gtproj, then VS will know that you want to add an item that is the same as the project which manages the extension .gtproj.

Here's a snippet of the Package code

[PackageRegistration(UseManagedResourcesOnly = true)]
[DefaultRegistryRoot("Software\\Microsoft\\VisualStudio\\8.0")]
[InstalledProductRegistration(false, "#110", "#112", "1.0", IconResourceID = 400)]
[ProvideLoadKey("Standard", "1.0", "MyProject", "My Company", 1)]
// This attribute is needed to let the shell know that this package exposes some menus.
[ProvideMenuResource(1000, 1)]
[ProvideProjectFactory(typeof(MyProjectFactory), "MyProject", "MyProject Environment project Files (*.myproj);*.myproj", "myproj", "myproj", ".\\NullPath", LanguageVsTemplate = "MyProject")]

[Guid(GuidList.guidMyProjectPkgString)]
public sealed class MyProject : Package
{

public MyProject()
{
Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering constructor for: {0}", this.ToString()));
}
protected override void Initialize()
{
base.Initialize();
base.RegisterProjectFactory(new MyProjectFactory(this));
}
protected override void Dispose(bool disposing)
{
Trace.WriteLine(string.Format(CultureInfo.CurrentCulture, "Entering Dispose() of: {0}", this.ToString()));
try
{}
finally
{
base.Dispose(disposing);
}
}
}

4. You'll need to need to implement certain interfaces in you VSPackage class, the stubs for these are provided and Visual Studios texteditor allows you to override the methods automatically by right-clickin the interface name and selecting implement from the context menu. You'll need to create a ProjectFactory and register it with your package.
Here's a snippet of the ProjectFactory code

[GuidAttribute(MyProjectFactory.MyProjectFactoryGuid)]
public class MyProjectFactory : Microsoft.VisualStudio.Package.ProjectFactory
{
public const string MyProjectFactoryGuid = "D1E0B0F6-5E61-42bf-ADD0-7CECC5665ED5";

public MyProjectFactory(MyProject package)
: base(package)
{
}
protected override ProjectNode CreateProject()
{
MyProjectNode project = new MyProjectNode();
project.SetSite((IOleServiceProvider)((System.IServiceProvider)Package).GetService(typeof(IOleServiceProvider)));
return project;
}
}

You'll notice a new instance of a class MyProjectNode, this is required, it is an Implementation of ProjectNode, this is required in order to use the Solution explorer in Visual Studio, without this you'll get an error at runtime, see step 7 for the ProjectNode code.

Hit F5 you should now see the new Project Type MyProject appear in the New Project dialog, it's Templates will be empty, so we'll move onto creating a template for your project type.

Tip: If you start to get an error which indicates a null memory address or something like that then make sure the ProjectFactory is being registered, if it is and the error persists then I'd recommend resetting the Experimental Hive with the Start menu utility I mentioned earlier and then F5 your project again.

5. You now have a VSPackage which is associated with your own project type and file type but we've mentioned nothing of your custom language yet. If you want all of the above to appear in Visual Studio from the installation (not from hitting F5 as internal developers would) you'll need to register this language and project type from the installer. A tool is used to fulfill this RegPkg.exe. To share the VSPackage with external users you'll also need a PLK, the PLK is a product key which can be obtained from Microsoft, it allows you to have your package installed on client machines without the requirement of the Visual Studio SDK. Without the PLK clients will not be allowed used your package and will get the following error when they try to create a project that uses your Language Service

RegPkg usage.
Obtain a PLK.
Using a PLK.
Also see Steps To Create Your First VSPackage, this explains how to install the PLK.
If this does not work have a look at step 8 of this post or go here "Debugging Package Load Failure (Dr. Ex)".

5. To create a Project Template file see the Topic at the end of this post "Creation of Project and Item Templates for..".
In order to associate the Project with your VSPackage type MyProject (with extenstion .myproj)
you'll need to edit the the contents of a file within the Project Template's zip file, the .vstemplate file. To do this you'll need to unzip the file. Open the .vstemplate file and edit an entry, the entry is

<ProjectType>CSharp</ProjectType>

The value CSharp could be another .NET language depending on what type of project you created your Template from.
Change the value to that of your Package i.e. MyProject.
Zip the contents back up, make sure the files are in the root of the zip file.
Now place the zip file under a new folder name MyProject, in parallel to the CSharp folder.
This zipping and installing can be done from your project using the MSBuild's ZipProject target.
To implement this you can set the type of the files to add to your template from Content to ZipProject. The files within the same folder under Template\Projects will be added to a Zip template and installed in the Visual Studio.
e.g.


creates a Project Template with the name of the last directory that the item resides in below the Templates folder.
OR

<ZipProject Include="Templates\Projects\Windows\MyProject\projectitem.cs />

results in a project template named MyProject, MyProject.zip, created and installed in the Visual Studio installation.


same for ZipItem.

Oh yes, in order to get the template to appear in the VS installation in an addition subfolder you need to add another attribute to the ZipProject

<ZipProject Include="Templates\Projects\Windows\MyProject\projectitem.cs" >
<OutputSubPath>Windows</OutputSubPath>
</ZipProject>
results in the template appearing in the VS installation at
C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\ProjectTemplatesExp\MyProjectType\Windows
6. Hit F5 you should see your project type MyProject and a project template appear in it's templates panel in the New Project dialog.
Select the project and ok, the contents listed by you in your .vstemplate file should appear in your new project.
You have a Project Type MyProject which has an extension .myproj and a project Template which appears within the Templates under your project type MyProject in the New project dialog.

7. If you want to customize the way Visual Studio handles the files found in your template then you'll need to create a ProjectNode implementation and override some methods in order to tell Visual Studio what to do when a node (file or project) is selected in the Solution Explorer of Visual Studio.
public class MyProjectNode : ProjectNode
{
public MyProjectNode()
{
// use the VS 2005 style property pages (project designer) instead of the old VS 2003 dialog
SupportsProjectDesigner = true;

// We allow destructive deletes on the project
CanProjectDeleteItems = true;
}

public override Guid ProjectGuid
{
get
{
return typeof(MyProjectFactory).GUID;
}
}

public override string ProjectType
{
get
{
return "myproj";
}
}

public override int InitializeForOuter(string filename,
string location,
string name,
uint flags,
ref Guid iid,
out IntPtr projectPointer,
out int canceled)
{
int result = base.InitializeForOuter(filename, location, name, flags, ref iid, out projectPointer, out canceled);
return result;
}

public override bool IsCodeFile(string strFileName)
{
if (String.IsNullOrEmpty(strFileName))
{
return false;
}
return
(String.Compare(Path.GetExtension(strFileName), string.Format("." + .my), StringComparison.OrdinalIgnoreCase) ==
0);
}

public override int GetFormatList(out string formatlist)
{
formatlist = string.Format("My Project File (*.myproj){1}*.myproj{2}",, "\0", "\0");
return VSConstants.S_OK;
}
#region IVsProjectSpecificEditorMap2 Members

public int GetSpecificEditorType(string pszMkDocument, out Guid pguidEditorType)
{
pguidEditorType = Guid.Empty; //typeof(YourEditorFactory).GUID;
return VSConstants.S_OK;
}

public int GetSpecificLanguageService(string pszMkDocument, out Guid pguidLanguageService)
{
pguidLanguageService = Guid.Empty; //typeof(YourLanguageService).GUID;
return VSConstants.S_OK;
}

#endregion
}
8. Debugging Package Load failures
If you were able to create a project of your custom type on your own development machine but failed when you tried it on another machine then this is the spot for you.

Tip : the easiest way to check that your package is registered with Visual Studio is to view the Help->About dialog in Visual Studio.

a. Debug the issue using a Tool called "Package Load Analyzer". It's part of the SDK version 4. It should appear in the Tools menu of Visual Studio if not the installer is present in the SDK installation, C:\Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Tools\Bin\PackageLoader.msi, and when you've installed it it should appear in Visual Studio's Tool menu.
To use it, select Tools->Package Load Analyzer.
A dialog appears, select your Package from the list. Right Click and select "Analyze" from the list.
The information given is only an indicator to what is wrong, either the PLK is at fault of some of the dependencies failed to load.
















b. A problem maybe that you've not installed the language service in the correct Hive. First try devenv /setup again from a command prompt. If this doesnt work have a look at the the registry
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0\Packages,
your Packages GUID should be here, if not it probably wasn't installed, look in the Experimantal hive's registry
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\8.0Exp\Packages,
you may see your GUID here instead, this probably means that your installed registered only the Experimental Hive.
Remember back to
RegPkg usage., you generated a registry setting using RegPkg.exe based on your packages assembly,
C:\Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Tools\Bi
n\Regpkg.exe /assembly

do this again but with the first argument as the non-Experimental hive, and the second argument is /regfile to generate a registry settings file which you Import into your Setup project.
C:\Program Files\Visual Studio 2005 SDK\2007.02\VisualStudioIntegration\Tools\Bin\Regpkg.exe /root:Software\Microsoft\VisualStudio\8.0Exp /regfile: /assembly
Reinstall.
If this is not the problem it maybe that the Visual Studio SDK is not installed on the current machine.

c.
If it isn't then you'll have to add a PLK to you VSPackage and reinstall. The PLK allows your custom package to be used on a machine that does not have the SDK, I've described some of this earlier.
According to the experts the most frequent cause of Package Load Failures is with a difference in detail supplied for the PLK and for your Package.
First look at you PLK details on the VSIP website and compare with the details in you VSPackage implementation. The Company name, Product Name and Package GUID must be identical.
If this does not work then it's time for some debugging.

d.
To simulate Visual Studio without having the SDK installed you can launch VS with
devenv /noVSIP
or
devenv /rootsuffix Exp /noVSIP
Now try to create a project of your custom type, if it fails you'll see some warning messages appear in the output console.
You can read this message later using the Visual Studio logger using
devenv /noVSIP /log
or
devenv /rootsuffix Exp /noVSIP /log
an XML log file is created in the Application data folder
C:\Documents and Settings\\Application Data\Microsoft\VisualStudio\8.0
or
C:\Documents and Settings\\Application Data\Microsoft\VisualStudio\8.0Exp
named ActivityLog.xml

e. Problems with your Package not appearing in Visual Studio can be that the Registry settings are incorrect. One problem I came across is that I had failed to generate the .reg file using RegPkg correctly, I had left out the /assembly, without this the registry does not know the Verioning details of the assembly, if you use /assembly you'll also need to let the Registry know where the assembly is this means you'll need to put the Assembly in the GAC! see my post "dotNet Miscellaneous" to see how to install the assembly in the GAC from code (you would do this in you Setup Project's Custom Action).
So now your Assembly is in the GAC (using code in your installer custom action).
You've used RegPkg to create a registry setting and added this to your Setup project.
At install time the Assembly gets added to the GAC, the Registry setting is set to register your Package with Visual Studio using the Assembly in the GAC.
Your setup runs updates Visual Studio with devenv /setup.
Your now good to go...

VSPackage Language Service
This is not the same as the Babel Language Service I mentioned earlier, this type used Flex and Bison directly and uses lots of additional resources in the VSPackage. It too allows you to create Text editors with color coding etc which you can use with a file type of your own and your own Project Types.
This too is available from the VS File->New Project dialog but at: File->New Project->Other Project Types->Visual Studio Language Package.
The wizard will step you through the setup but all is not straight forward, as usual.
The wizard requires you have Flex.exe and Bison.exe installed, the wizard will prompt you for these. Google will turn up installation for these resources.


VSPackage and Projects
To create a VSPackage Project with multiple projects being created when the solution of your type is create you need a to install a MultiFileTemplate in the VS installation along with your VSPackage implementation.
To install the MultiFileTemplate you have to add the contents to a zip file and copy the zip file with the MultiFileTemplate and sub .vstemplate files yourself to the MyDocuments or to the VS installtion directorty, C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\ProjectTemplates\MyProjects, so that VS will pick it up. This can be done from within the source project file which is generating the MultiFileTemplate using the MSBuild ZipItem or the third party Zip build task MSBuildTasks that I've mentioned in another thread MSBuild.


Examples of this functionality are included in the SDK.

Project and Item Templates
Create Reusable Project and Item Templates for the development team.


Editing VSPackage File and Project Icons and Bitmaps

There are usually 2 types of image in a project, the application icon and the filetype bitmap.
The application icon is the image that appears beside the project template in the new project dialog. This is a 32x32 pixel icon with the extension .ico. It is set with the icon element in the vstemplate file.
The second is the bitmap, this used by the VSPackage to display an image beside the file or the project in Visual Studios soulution explorer. The bitmap is created as part of a bitmap file in the Resources of your source project. The bitmap may have many images grouped together but each image should only be 16x16 pixels, this is because they are access by the code and indexed based on 16 pixels. Here's how the image is access
first you add all of the bitmaps to an imageList, remember they are indexed with 16 pixels

FileTypeImageList =
Utilities.GetImageList(typeof(MyProjectNode).Assembly.GetManifestResourceStream("MyNameSpace.Resources.FileTypeImageList.bmp"));

//Store the number of images in ProjectNode so we know the offset of the python icons.
_imageOffset = this.ImageHandler.ImageList.Images.Count;
foreach (System.Drawing.Image img in FileTypeImageList.Images)
{
this.ImageHandler.AddImage(img);
}

You now have a list of all the bitmaps. You now override the ImageIndex() method in both you FileNode implementation and your ProjectNode implementation like so
public override int ImageIndex
{
get
{
return (int)ImageOffset + (int)MyTypeImageIndex.GtProjFile;
}
}
the
MyTypeImageIndex.GtProjFile is just an enum, in the above case the enum returns 1, this indicates the the bitmap for this type, in this case this override is in my ProjectNode implementation so the if a project is created of my type then the bitmap indexed at 1 (pixel 17 to 32) in the bitmap file FileTypeImageList.bmp is used with the project and will appear in solution explorer for that project.