There are some docs and sample code here:
http://msdn2.microsoft.com/en-us/library/ms185301.aspx
I wrote one recently: Here was my code:
/////////////////////////////////////////////////////////////////////////
<VSTemplate Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Item">
<TemplateData>
<Name Package="{39c9c826-8ef8-4079-8c95-428f5b1c323f}" ID="3062"/>
<Description Package="{39c9c826-8ef8-4079-8c95-428f5b1c323f}" ID="3063"/>
<Icon Package="{39c9c826-8ef8-4079-8c95-428f5b1c323f}" ID="4533"/>
<TemplateID>WebForm</TemplateID>
<TemplateGroupID>Web</TemplateGroupID>
<ProjectType>CSharp</ProjectType>
<ProjectSubType>Web</ProjectSubType>
<ShowByDefault>false</ShowByDefault>
<SortOrder>1</SortOrder>
<DefaultName>WebForm.aspx</DefaultName>
</TemplateData>
<TemplateContent>
<References>
<Reference>
<Assembly>System.Web</Assembly>
</Reference>
<Reference>
<Assembly>System</Assembly>
</Reference>
<Reference>
<Assembly>System.Data</Assembly>
</Reference>
<Reference>
<Assembly>System.Drawing</Assembly>
</Reference>
<Reference>
<Assembly>System.Xml</Assembly>
</Reference>
</References>
<CustomParameters>
<CustomParameter Name="$ParentExtension$" Value=".aspx"/>
<CustomParameter Name="$ChildExtension$" Value=".cs"/>
</CustomParameters>
<ProjectItem ReplaceParameters="true" TargetFileName="$fileinputname$.$fileinputextension$">Default.aspx</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="$fileinputname$.$fileinputextension$.cs" SubType="ASPXCodeBehind">Default.aspx.cs</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="$fileinputname$.$fileinputextension$.designer.cs">Default.aspx.designer.cs</ProjectItem>
</TemplateContent>
<WizardExtension>
<Assembly>Microsoft.VisualStudio.Web.Application, Version=8.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</Assembly>
<FullClassName>Microsoft.VisualStudio.Web.Application.WATemplateWizard</FullClassName>
</WizardExtension>
</VSTemplate>
/////////////////////////////////////////////////////////////////////////////////////
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.TemplateWizard;
using System;
using System.Collections.Generic;
using System.Globalization;
namespace Microsoft.VisualStudio.Web.Application
{
public class WATemplateWizard : IWizard
{
string _parentExtension;
string _childExtension;
EnvDTE.ProjectItem _parent;
List<EnvDTE.ProjectItem> _children;
void IWizard.BeforeOpeningFile(EnvDTE.ProjectItem projectItem)
{
}
void IWizard.ProjectFinishedGenerating(EnvDTE.Project project)
{
}
void IWizard.ProjectItemFinishedGenerating(EnvDTE.ProjectItem projectItem)
{
if (projectItem != null && !string.IsNullOrEmpty(_parentExtension) && !string.IsNullOrEmpty(_childExtension))
{
string name = projectItem.Name;
if (name.EndsWith(_parentExtension, true, CultureInfo.InvariantCulture))
{
_parent = projectItem;
}
else if (name.EndsWith(_childExtension, true, CultureInfo.InvariantCulture))
{
if (_parent != null)
{
MakeChild(_parent, projectItem);
}
else
{
if (_children == null)
{
_children = new List<EnvDTE.ProjectItem>();
}
if (_children != null)
{
_children.Add(projectItem);
}
}
}
}
}
void IWizard.RunFinished()
{
if (_parent != null && _children != null)
{
foreach (EnvDTE.ProjectItem child in _children)
{
MakeChild(_parent, child);
}
}
_parentExtension = null;
_childExtension = null;
_parent = null;
if (_children != null)
{
_children.Clear();
_children = null;
}
}
void IWizard.RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
{
try
{
_parentExtension = replacementsDictionary["$ParentExtension$"];
_childExtension = replacementsDictionary["$ChildExtension$"];
}
catch
{
}
}
bool IWizard.ShouldAddProjectItem(string filePath)
{
return true;
}
static private void MakeChild(EnvDTE.ProjectItem parent, EnvDTE.ProjectItem child)
{
if (parent != null && child != null)
{
string file = child.get_FileNames(1);
if (!string.IsNullOrEmpty(file))
{
parent.ProjectItems.AddFromFileCopy(file);
}
}
}
}
/////////////////////////////////////////////////////////////
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Shell.Design.Serialization;
using System;
using System.Diagnostics;
using System.IO;
using System.Collections;
using System.Runtime.InteropServices;
using System.Web;
namespace Microsoft.VisualStudio.Web.Application
{
[...]
[ProvideObject(typeof(WATemplateWizard))]
internal class WAPackage : Package
{
...
}
}
//////////////////////////////////////////////////////////////
Tim McBride
This posting is provided "AS IS" with no warranties, and confers no rights.