Click to Rate and Give Feedback
Related Articles
Here the author introduces SQL Server Data Services, which exposes its functionality over standard Web service interfaces.

By David Robinson (July 2008)
Here the author answers questions regarding the Entity Framework and provides an understanding of how and why it was developed.

By Elisa Flasko (July 2008)
Here we present techniques for programmatic and declarative data binding and display with Windows Presentation Foundation.

By Josh Smith (July 2008)
Systems that handle failure without losing data are elusive. Learn how to achieve systems that are both scalable and robust.

By Udi Dahan (July 2008)
More ...
Articles by this Author
In this article we introduce you to BizTalk Services, new technology that offers the Enterprise Service Bus features of BizTalk Server as a hosted service.

By Jon Flanders and Aaron Skonnard (June 2008)
The Windows Presentation Foundation provides new techniques for UI-based developing applications and makes better use of current hardware and technologies. In this article, Ian Griffiths and Chris Sells explain 10 of the most significant advances that make WPF superior to its Win32 predecessors.

By Ian Griffiths and Chris Sells (January 2006)
The System.Windows.Forms namespace has increased by approximately 134 percent over the .NET Framework 1.1. There are 446 new public types; 113 existing types have been updated with new members and values; 218 types have been carried over from the original namespace. Read about it here.

By Chris Sells and Michael Weinhardt (Visual Studio 2005 Guided Tour 2006)
In this article, the winning Windows Forms duo of Chris Sells and Michael Weinhardt team up again to explore lots of new features and additions to Windows Forms 2.0 that will let you build more flexible, feature-rich controls, get better resource management, more powerful data-binding abilities, and make your development life a whole lot more fun.

By Michael Weinhardt and Chris Sells (May 2005)
The upcoming version of the .NET Framework offers a host of enhancements an order of magnitude over and above existing versions. In particular, developers writing Windows Forms benefit from a variety of new and improved features targeting development, deployment, increased productivity, and auto-generated code. This article covers some of the key new features including designer enhancements, new controls, data binding, and deployment to give you a taste of what's to come.

By Michael Weinhardt and Chris Sells (May 2004)
This is the second of two articles discussing the extremely rich design-time features of the .NET Framework. Part 1 discussed the basics, showing you where to start and how to extend your control implementation through attributes and interfaces, as well as their effects on the property browser, code serialization, and other controls. Part 2 continues the journey by concentrating on design-time functionality that you can implement beyond your components and controls, including TypeConverters, UITypeEditors, and Designers. It would be impossible to cover everything you can do in two short articles, which is a testament to just how all-encompassing and flexible the design-time capability of the .NET Framework is.

By Michael Weinhardt and Chris Sells (May 2003)
Visual Studio .NET provides support for designing rich features into your controls and components, allowing you to set properties, set form placement, inherit from base classes, and much more. So how does Visual Studio .NET do all this? What does the Windows Forms designer do? What's the difference between a control and a component? How does Visual Studio integrate your controls so that they can access features of the .NET Framework?In this article, the authors answer these common questions by building a clock control and taking the reader along for the ride. In building the control, hosts and containers are illustrated, the property browser is explained, debugging is discussed, and a general overview of the design-time infrastructure is presented.

By Michael Weinhardt and Chris Sells (April 2003)
With the much-anticipated release of the .NET Framework 1.1, developers are eager to know what's been added to their programming bag of tricks. In this article, the author focuses on new developments in Windows Forms, such as namespace additions, support for hosting managed controls in unmanaged clients, and designer support for C++ and J#. Integrated access to the Compact Framework and new mobile code security settings also make this release noteworthy. Along with these features, the author reviews the best ways to handle multiple versions of the common language runtime and highlights some potential pitfalls.

By Chris Sells (March 2003)
More ...
Popular Articles
Kenny Kerr sings the praises of the new Visual C++ 2008 Feature Pack, which brings modern conveniences to Visual C++.

By Kenny Kerr (May 2008)
Learn how to create a workflow that uses InfoPath forms and other office documents for passing data to targeted activities and for use in Office documents.

By Rick Spiewak (June 2008)
Microsoft Robotics Studio is not just for playing with robots. It also allows you to build service-based applications for a wide range of hardware devices.

By Sara Morgan (June 2008)
Speech Server 2007 lets you create sophisticated voice-response applications with Microsoft .NET Framework and Visual Studio tool integration. Here’s how.

By Michael Dunn (April 2008)
More ...
Read the Blog
SQL Server Data Services (SSDS) is a robust, scale-free data service that internally uses proven SQL Server technology and exposes its functionality over industry standard Web service interfaces. In the July 2008 issue of MSDN Magazine, David Robinson introduces ...
Read more!
Windows Presentation Foundation (WPF) offers excellent support for managing the display and editing of complex data. In the December 2007 edition of MSDN Magazine, John Papa did a great job of explaining essential WPF data binding concepts. ...
Read more!
The most fundamental form of Web testing is HTTP request/response testing. This involves programmatically sending an HTTP request to the Web application, fetching the HTTP response, and examining the response for an expected value. In the May 2008 issue of MSDN Magazine, Read more!
In the November issue of MSDN Magazine, Jeffrey Richter demonstrates some recent additions to the C# programming language that make working with the APM significantly easier. In the June ...
Read more!
The July 2008 issue of MSDN Magazine is now available online. Here's what's in the issue: Data Services: Develop ...
Read more!
The June 2008 issue features the first installment of a new MSDN Magazine column on software design fundamentals. We’ll discuss design patterns and principles in a manner that isn't bound to a specific tool or lifecycle methodology. In this issue, Jeremy Miller starts the Patterns in Practice column ...
Read more!
More ...
Top Ten Cool Features of Visual Studio .NET Help You Go From Geek to Guru

Visual Studio .NET

Jon Flanders and Chris Sells
This article assumes you're familiar with Visual Studio .NET SUMMARY Visual Studio .NET has lots of cool features. Obviously, it supports languages that target the common language runtime, like C# and Visual Basic .NET, and it lets you write CLR-managed code. But did you know that there are features of the environment itself, independent of the language features, that earn Visual Studio .NET the cool tool stamp of approval?      In this article the authors count down their favorite environment features—the ones they think every developer will applaud. They include support for debugging stored procedures, project reference management, metadata in Class View, a richer immediate window, custom environment programming with macros, and more. hen we were just lads, knee-high to a 16-bit window, we religiously read the predecessor of this magazine, Microsoft Systems Journal. We always scoured the magazine cover-to-cover, but would especially savor the words of Dave Edson, who more than once presented his gems as David Letterman-style Top Ten lists. In the spirit of those bygone days and to focus on some of our favorite parts of Visual Studio� .NET, the culmination and combination of more than a decade of work on Visual C++�, Visual Basic�, Visual InterDev�, and Visual J++�, here's our list of the top ten coolest features in Visual Studio .NET.

10. Processes Dialog

      In order to debug your DLL projects (for example a COM or Microsoft� .NET component), you first need to launch an EXE that loads your component. If there's an EXE project in the same solution as your DLL project, you can right-click on that project in the Solution Explorer and choose Set as Start-Up Project, press F5 to debug, and you're all set. Or, if the EXE you'd like to use is outside of the solution but can be started manually, you can use the path to the EXE as the Start Application. Unfortunately, neither of these techniques works if you need to debug your DLL inside of an already running process, like the ASP or ASP.NET worker processes that are started by Internet Information Services (IIS).      If you want to debug your code inside of an existing process, you can set the breakpoints in your source file and select Debug | Processes. This brings up the Processes dialog (see Figure 1), which allows you to pick a process to which you would like Visual Studio .NET to attach its debugger. You can choose to see all processes on a machine including system processes and processes in other logon sessions.Figure 1 Processes DialogFigure 1 Processes Dialog      Once you select a process to debug and press the Attach button, you get the Attach to Process dialog, which gives you the option of debugging any combination of managed common language runtime (CLR) code, Microsoft T-SQL code, native (unmanaged) code, and script. After you have attached to the process, all you need to do is cause that process to trigger your breakpoints, perhaps by surfing to the appropriate URL if you are debugging an ASP.NET application in the aspnet_wp.exe process. Once your breakpoints have been hit, you can debug away.

9. SQL Server Stored Procedure Debugging

      Not only does Visual Studio .NET make attaching to processes much easier, one option you have when attaching to those processes is debugging SQL Server™ stored procedures. To enable this feature, you'll need to make sure that the SQL Server debugging components have been installed on your machine and that you have the appropriate permissions to debug stored procedures. Once that's been taken care of, you can use the Server Explorer to select any SQL Server database on your network, bring up your stored procedure, set a breakpoint, and then execute the code that calls that stored procedure. Once your SQL breakpoint is hit, you've got single-stepping, stepping in, data tips, and the rest of the Visual Studio .NET debugging tricks that you've grown to know and love. Figure 2 shows a breakpoint hit in a stored procedure.Figure 2 Stored Procedure DebuggingFigure 2 Stored Procedure Debugging

8. Project References

      Solutions are often made up of multiple projects, like a Windows� Forms EXE project with one or two dependent component DLL projects. When that happens, not only will you be using the EXE project as the startup project, you'll want to make sure that the DLL projects are built first and referenced appropriately. To build the DLL project first, you can use the Project Build Order dialog, available by right-clicking on the solution in the Solution Explorer. However, as your solution grows, and components depend on other components, you don't want to be messing with the build order directly; you really want to establish dependencies. This can be done via the Project Dependencies dialog (see Figure 3), also available in the context menu of your solution in the Solution Explorer.Figure 3 Project DependenciesFigure 3 Project Dependencies      Rearranging these dependencies will make sure that things are built in the appropriate order. However, this is still too much work. If one project depends on another assembly, shouldn't Visual Studio .NET be smart enough to notice this, figure out the dependencies, and make sure everything builds appropriately? Yes it should be, and yes it is. The key is Project References.      To add an assembly reference to your project, right-click on the referencing project in the Solution Explorer and choose Add Reference. This will bring up the Project References dialog. You should use the third tab on this dialog box when working with component references between projects. If you create or add your existing component projects to your solution, you can then share a project reference between your projects, rather than a file reference (which is what the other two tabs give you). When you use a project reference, Visual Studio .NET will calculate the dependencies and build order and make sure that the referenced assemblies are always up to date and copied to the appropriate directories so that everything runs properly.

7. Class View

      Previous versions of Visual Studio, notably Visual C++, had a Class View window, but never like the one in Visual Studio .NET. Of course, like its predecessor, the Class View allows you to see the metadata for the types in your project, providing for more complete information than Visual C++ 6.0 ever did. You can even add methods, properties, fields, and so on, to your types, depending on whether it's a C++ class, a C# class, or a COM interface. You can do this by right-clicking on a class in the Class View window, selecting Add, and choosing the member to add to your type.      But that's not all; you can also use the Class View to generate skeleton implementations of methods to override or entire interfaces (unfortunately this does not work under Visual Basic .NET projects). To override a method in a base class, right-click on the method in the Class View under Bases and Interfaces and choose Add | Override. To implement an entire interface, make sure that your class lists the interface as one it implements, right-click on the interface under the Bases and Interfaces node of your class, right-click on the interface and choose Add | Implement Interface. Starting with the following C# code
class Foo : IDisposable {
}
and then using Add | Implement Interface will yield the following skeleton implementation:
class Foo : IDisposable {
  #region Implementation of IDisposable
  public void Dispose() {
  }
  #endregion
}

6. Command Window

      The Command window in Visual Studio .NET has the same capabilities as the Immediate windows you were used to in earlier IDEs—in other words, the ability to set and get values from a stopped program (see Figure 4).Figure 4 Command WindowFigure 4 Command Window      However, there's more to Command than just value checking. Almost any command that you can execute with a menu, keyboard shortcut, or toolbar button can also be executed in the Command window. For example, to open a Solution in the Command window, type File.NewFile followed by the name of the file to create. This starts a new editor window with all of the syntax highlighting in place, but without the hassle of the New File dialog.      While you were executing the File.NewFile command, you might have noticed that as soon as you typed the period, you got a list of all of the file-related commands via IntelliSense�. This is because IntelliSense extends to the file system as well. For example, if you typed File.OpenSolution followed by "c:\", you'd be presented with a list of the files and directories in the root of your hard drive. For more documentation on your favorite commands, you can see the usage by passing /? as an argument, which will show the online help page for that command.      Furthermore, if you grow tired of typing File.NewFile, you can assign an alias to it like so:
>alias new File.NewFile
Now you can create a new file in the Command window with just the alias:
>new foo.cs
If you like aliases, there are a number of predefined aliases listed in the Visual Studio .NET online help.      Finally, if for some reason you'd like to avoid the Command window altogether but you'd still like its benefits, you can type commands directly into the mini Find window in the toolbar by preceding all commands with a leading ">". You even get IntelliSense. What will they think of next?

5. Designer-friendly Custom Controls

      So far we've shown cool features in Visual Studio .NET from the user's point of view. These last five cool features are oriented towards the developer interested in extending the capabilities of Visual Studio .NET. Let's start with integrating custom controls more tightly into the Visual Studio .NET designers.      The Framework Class Library (FCL) classes are built with the idea that components need to be easier to work with at design time. Towards that end, Microsoft added features to the FCL that allow Visual Studio .NET (or any compatible IDE) to work with a class or control at design time in a special way. For example, if you create a WebForm or Windows Form and add a button control, when you double-click on the button a function gets generated automatically for the "default" event for that control and the event is hooked up to the newly generated function. The secret to making this, and other similar integration tasks, work lies inside the System.ComponentModel namespace. This namespace contains the classes that can be used to decorate a class with attributes which, in turn, tell Visual Studio .NET how to deal with that class at design time. For event generation specifically, the attribute in question is System.ComponentModel.DefaultEventAttribute. This attribute gets applied at a class level, like so:
[DefaultEvent("ClickMe")]
class MyControl : Control {
  public event EventHandler ClickMe;
}
       Of course, finding the default event is one thing, but generating the code is another. Visual Studio .NET itself doesn't actually generate this code; that task is reserved for another object. This object is created by the Visual Studio .NET editor to act as the designated designer object for the object being designed. Another attribute class in the System.ComponentModel namespace, DesignerAttribute, can be applied to a class. Once the editor detects this attribute, it creates an instance of this designer class and uses that object as the controller for dealing with the object being designed:
[Designer("System.Windows.Forms.Design.ControlDesigner,
System.Design.DLL", typeof(IRootDesigner))]
class MyControl : Control
{
  public event EventHandler ClickMe;
}
When the MyControl class is dropped onto a form in the designer, the designer class is notified and then given the chance to persist whatever code it wants to the source file to which it is being added.      This model has multiple extensibility points built into it. This will allow you to not only take advantage of the designers that come with the .NET Framework, but also to create your own custom designers or decorate your own custom controls with the designer attributes. You can read more about creating and using designer classes in the documentation for System.ComponentModel.

4. Macros

      The next step to extending Visual Studio .NET is to program it directly. The easiest way to do that is using macros. Macros are files written in Visual Basic .NET that are saved and loaded by the IDE and executed on command. They interact with the IDE through its automation object model.      The best way to get started using macros, and the macro IDE embedded inside the Visual Studio .NET IDE, is to record one. Start recording by choosing Tools | Macros | Record Temporary Macro, and then manipulate Visual Studio .NET to perform the operations you'd like recorded. When you press the Stop button on the macro tool bar (which will appear when you are recording a macro), you can examine your new macro using the Macros IDE (Tools | Macros | Macros IDE). Once you've got the cursor inside of a macro, debugging is as simple as setting a breakpoint on your source line (F9) and pressing F5 to run the macro.      Recording macros can be a powerful way to automate simple repetitive tasks. Also, since almost all of the functionality in Visual Studio .NET is exposed via its automation object model, hand-crafted macros can also be used to automate tasks that don't lend themselves to recording.

3. Custom Add-ins

      Although macros are useful, once a macro runs it has no further effect. If you need some custom manipulation of the IDE that has a longer lifetime than a single operation, you'll want to create an add-in. An add-in is a COM class that implements the IDTExtensibility2 interface. There are several things you can do with an add-in that you can't do with a macro: create custom property pages for the Options dialog, use tool windows, add menu items, and add information to the Visual Studio .NET About box.      For example, one thing that I find missing in Visual Studio .NET is an integrated shell. The Command window is great, but it's not a full shell. I want a full shell integrated into Visual Studio .NET, as shown in Figure 5.      To create an add-in, Visual Studio .NET provides the Add-in project template. In addition to the basics (like the name and description of the add-in), this wizard asks all kinds of questions like what language would you like to use to implement the add-in, what IDE to plug into (Visual Studio .NET is just one of several possibilities), whether to add the add-in to the Tools menu, allow access to the add-in on the command line, start the add-in immediately when Visual Studio .NET starts up, and even whether you'd like a default About box.      Choosing one of the managed languages causes the wizard to build a project that exposes a .NET class as a COM object that implements the IDTExtensibility2 interface. Creating a command-line shell in the IDE begins with creating a tool window for holding the control that interacts with cmd.exe. It's best to place this code in the OnConnection method, which Visual Studio .NET will call when the add-in is first loaded (see Figure 6).      The call to CreateToolWindow creates the new tool window (the Command line window as shown in Figure 5) and also gives the IDE the ProgID that it should use to create an ActiveX� control to host in the new tool window (which, in our case, is a .NET Windows Form control acting as an ActiveX control). The ActiveX control then becomes the client area for the new tool window.      To make this window appear, we'll need a new command in the Tools menu, which is what the call to AddNamedCommand does in OnConnection. When the user selects the new command from the Tools menu, Visual Studio .NET calls the Exec method of the IDTCommandTarget interface to handle it:
public void Exec(
  string CmdName,
  EnvDTE.vsCommandExecOption ExecuteOption,
  ref object VariantIn,
  ref object VariantOut,
  ref bool handled)
{
    if (CmdName == "CmdAddIn.Connect.ShowToolWindow" )
    {
        windowToolWindow.Visible = true;
        handled = true;
    }
}
       When you create an add-in project with Visual Studio .NET, it creates a setup project that will add all the appropriate registry entries. Once your new add-in has been built, you can load it via Tools | Add-In Manager. At this point, you should be able to choose the new menu item from the Tools menu and start enjoying command-line shell goodness inside Visual Studio .NET (although the sample is admittedly far short of the ideal in this area).

2. Custom Tools

      One popular use for macros and add-ins is to generate code. For example, as nice as the built-in collection classes in .NET are, they only hold objects, not specific types. This means that it's easy to put things into a collection that don't belong, and you'd never know it until you hit a runtime error, which is too late. One classic way around this problem is to wrap the collection in a type-safe wrapper, as shown in Figure 7.      The problem, unfortunately, is that to really wrap a collection completely requires a lot of work for each combination of types, which is why code generation add-ins and macros are often used. However, even add-ins and macros require manual activation. What we'd really like is a way to describe the type of collection we're after (for example, an ArrayList of Int32 or a HashTable of Point), and just have the code generated as needed, maybe even as part of the build process. For that, Visual Studio .NET provides custom tools for all of your C# and Visual Basic .NET projects.      Visual Studio .NET provides two built-in custom tools, the MSDataSetGenerator that generates a type-safe DataSet from an XSD file, and the MSDiscoCodeGenerator that generates a Web Service proxy class from a MAP file. If you've added a DataSet file or a Web Service proxy to a project, you can see from the properties that each of them has a Custom Tool setting, as shown in Figure 8.Figure 8 Custom Tool PropertiesFigure 8 Custom Tool Properties      A custom tool is a component that is run every time the input file changes and is saved. The custom tool is handed the name of the input file as well as bytes in the file via the Generate method on the IVsSingleFileGenerator COM interface. This method is responsible for producing bytes that will be dumped into C# or Visual Basic .NET, depending on what kind of a project it is. A generated file associated with a custom tool can be seen by pressing the Show All Files button in the Solution Explorer. The generated file provides the IntelliSense during development time and the code at compile time.      While you can implement the IVsSingleFileGenerator interface directly to build your own custom tool, it's far easier to derive from a managed class provided in Visual Studio .NET: Microsoft.VSDesigner.BaseCodeGeneratorWithSite. The class needs to be decorated with the appropriate COM attributes, but even so, a minimal custom tool is very simple:
[Guid("A0B5E5E9-3DF8-48bc-A6BA-E0DFD35C6237")]
public class MyGenerator : BaseCodeGeneratorWithSite
{
    public override byte[] GenerateCode(string file, string contents)
    {
        string code = "<<generated code>>";
        return System.Text.Encoding.ASCII.GetBytes(code);
    }
}
       Once you've built your custom tool, the COM class needs to be exposed from your .NET component and registered via regasm. Also, custom keys letting Visual Studio .NET know about a new custom tool are needed in the Registry. You can take a look at the Registry entries required for the collection generator custom tool sample that are shown in Figure 9.      Once your custom tool has been registered, using it is just a matter of setting it in the file properties of the input file, just like Visual Studio .NET does for its custom tools. For a more complete custom tool sample, check out the SBCollectionGenerator in the code download (see the link at the top of this article). It generates complete type-safe vector and hashtable collections from input files like this:
  <typeSafeCollections>
    <typeSafeCollection>
      <templateKind>Vector</templateKind>
      <itemType>int</itemType>
      <collectionName>MyIntegerCollection</   
       collectionName>
    <collectionNamespace>MyCollections</collectionNamespace>
  </typeSafeCollection>
</typeSafeCollections>

1. Custom Wizards

      As nifty as the custom collection generation tool is, the input files are pretty primitive XML files, which are easy to edit once the initial options have been laid down, but a pain to start from scratch—not to mention the agony of setting the custom tool properties every time you want to add collections to a new project. It would be nice to have an automated way to add XML input files to a project so they can be used to set up the custom tool properties. To do that, you'll need to build a custom wizard, just like the DataSet project item wizard that comes with Visual Studio .NET.      One way to do this is to build a custom COM object that implements an interface named IDTWizard. After adding some configuration information to the Visual Studio .NET configuration files and implementing all of the user interface and the code generation back end, you can have your very own project template wizard that plugs into Visual Studio .NET. But why would you go to all the trouble of writing a bunch of custom code when you can use the generic wizard engine that runs all of the project wizards provided by Microsoft?      When you create a new project using one of the built-in project templates, Visual Studio .NET creates an instance of a particular COM object (the ProgID of this class is VsWizard.VsWizardEngine). The wizard object displays an HTML-based UI which can take input and can use these input values to expand a set of template files, which can then be added to the project. The basic wizard model is the same whether you're creating a new project or adding a new item to an existing project.      To build a custom tool item wizard, the first thing you need is a .vsz file. This file tells Visual Studio .NET the ProgID of the COM object to create for this wizard, the type of wizard, and whether the wizard has a UI. Also you can specify a directory where the wizard files live. Here is the .vsz file for the custom tool item wizard:
VSWIZARD 7.0
Wizard=VsWizard.VsWizardEngine
Param="PROJECT_TYPE = CSPROJ"
Param="WIZARD_NAME = SBCollectionItem"
Param="ABSOLUTE_PATH = C:\Documents and Settings\All
Users.WINDOWS\Documents\SBCollectionItem"
Param="FALLBACK_LCID = 1033"
Param="WIZARD_UI = TRUE"
       An optional item in a .vsz file (but one that does appear in this .vsz file) is the ABSOLUTE_PATH element. A wizard's files can either live in the well-known folder for each language (C:\Program Files\Microsoft Visual Studio .NET\VC#\VC#Wizards for C# wizards) or in a separate folder. Having this wizard in a separate folder allows you to reuse this wizard for other languages. The .vsz file needs to be in the appropriate folder (appropriate both for language and for type of wizard). On our machine, the C# item wizards are in the C:\Program Files\Microsoft Visual Studio .NET\VC#\CSharpProjectItems folder.      Once the .vsz file is in place, you'll also need to edit a .vsdir file, which will tell Visual Studio .NET where in the New Item dialog to show the new wizard. Adding the new wizard to the local project items for C# projects means editing the C:\Program Files\Microsoft Visual Studio .NET\ VC#\CSharpProjectItems\LocalProjectItems\LocalProjectItems.vsdir file and adding the following line:
..\SBCollectionItem.vsz|{FAE04EC1-301F-11d3-BF4B-
00C04F79EFBC}|SBCollectionItem|10|A Type-safe collection
metafile|{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}|4524|0|Collection.xml
       We've got several fields here, all separated by old-fashioned pipes. The first field is the relative path of the .vsz file we created earlier. The third field is a short description for the Add New Item dialog. A long description (also shown in the dialog) can be provided in the fifth field. The fourth field is the sort order, where smaller means closer to the top. Also notice the last field. It's the template for the file to be generated and added to the project. The other fields are GUIDs that we copied from the other entry in this file to use their icon for display.      The contents of the Template\1033 (US English) directory is the manifest for the project item in a file called templates.inf and the template file itself. The template file and the templates.inf file use wizard-provided symbols to expand statements like [!output SAFE_CLASS_NAME] into strings like MyClass. The template file for the collection generator item looks like this:
<typeSafeCollections>
  <typeSafeCollection>
    <templateKind>[!output TEMPLATE_KIND]</templateKind>
    <itemType>[!output TYPE]</itemType>
    <collectionName>[!output COLLECTION_NAME]</collectionName>
    <collectionNamespace>[!output COLLECTION_NAMESPACE]
    </collectionNamespace>
  </typeSafeCollection>
</typeSafeCollections>
To populate the symbols, we'll need a UI that we will put into the HTML\1033 directory. The HTML file gets loaded by the wizard when it executes, as shown in Figure 10.Figure 10 Custom Project Item Wizard UIFigure 10 Custom Project Item Wizard UI      In addition to showing the UI, the HTML is responsible for taking the values the user enters and putting them into the name/value dictionary that the wizard uses to expand the templates. This is most easily accomplished using the OnWizFinish helper function provided by the standard wizard environment and providing a mapping between the HTML control managing the value for each template argument using the custom SYMBOL tag, as shown here:
<INPUT id="COLLECTION_NAME" type="text" name="Text2">
<SYMBOL VALUE="IntHash" TYPE="text" NAME="COLLECTION_NAME"></SYMBOL>
       Once the user presses Finish, the default.js file in the Script\1033 directory of your wizard is what uses the templates.inf file to process each template file. Adding the generated file to the project after it's been generated can be accomplished in the OnFinish function in default.js using the AddFilesToCSharpProject helper function, as shown in the sample. Once all files have been generated, the wizard will give the script one last chance to set any project options by calling it back via the SetFileProperties function. The collection generation project item uses this opportunity to set the custom tool property of the newly generated file:
function SetFileProperties(oFileItem, strFileName)
{
  oFileItem.Properties.Item("CustomTool").Value =
    "SBCollectionGenerator";    
}

Visual Studio Community

      As a final note it must be pointed out that as cool as Visual Studio .NET is, it's the community of users and extenders that really makes Visual Studio .NET shine. It only takes a quick check of the Visual Studio .NET Web site to realize just how much community involvement has strengthened Visual Studio .NET. Of course, Visual Studio .NET enables the community by providing so many features and extensibility hooks. This article has really just scratched the surface of what's available in Visual Studio .NET, and who knows where the community will continue to take it into the future. For background information see:
Visual Studio .NET Home Page
DevelopMentor Mailing List
Visual Studio .NET Fun Facts
Jon Flanders teaches Essential ASP.NET at DevelopMentor. He is the author of ASP Internals (Addison-Wesley, 2000) and coauthor with Chris Sells of Mastering Visual Studio .NET (O'Reilly, October 2002). Reach Jon at JFland@develop.com.
Chris Sells is an independent consultant, specializing in distributed applications in .NET and COM and an instructor for DevelopMentor. More information about Chris and his various projects is available at http://www.sellsbrothers.com.
From the October 2002 issue of MSDN Magazine.
Figure 5 Full Shell Integration

Figure 6 Create Window
public void OnConnection(
  object application,
  Extensibility.ext_ConnectMode connectMode,
  object addInInst,
  ref System.Array custom)
{
  applicationObject = (_DTE)application;
  addInInstance = (AddIn)addInInst;
  object objTemp = null;
  String guidstr = "{858C3FCD-8B39-4540-A592-F31C1520B174}";

  // Create the Command line tool window
  windowToolWindow =
      applicationObject.Windows.CreateToolWindow(
      addInInstance,
      "CmdAddIn.CommandWindow",
      "Command Line window",
      guidstr,
      ref objTemp);
  windowToolWindow.Visible = true;

  // Add a new command to the Tool menu
  object[] o = null;
  Command cmd =
      applicationObject.Commands.AddNamedCommand(
      addInInstance,"ShowToolWindow", "", "", false, 1000, ref o,0);
  cmd.AddControl(applicationObject.CommandBars["Tools"],1);
}
Figure 7 Creating a Type-safe Wrapper
class IntList {
  public int Add(int value) {
    return _list.Add(value);
  }

  •••

  private ArrayList _list = new ArrayList();

  // Test
  static void Main() {
    IntList list = new IntList();
    list.Add(1); // OK
    list.Add("two"); // ERR (good)
  }
}
Figure 9 Custom Tool Registry Settings

Page view tracker