Speed Up with Project Templates Using Visual Studio 2005 - Part 3
 
Published: 11 Sep 2006
Abstract
In this third part of the article Ameet explains how you can use the IWizard interface and customize the templates and Starter Kits.
by Ameet Phadnis
Feedback
Average Rating: This article has not yet been rated.
Views (Total / Last 10 Days): 41670/ 120

Introduction

In my previous article entitled "Speed Up with Project Templates Using Visual Studio 2005 - Part 2," I dealt with how you can create Project Templates with the export template wizard.  In that article I did mention the IWizard interface and how it could be used to perform some preliminary steps for your project.  The IWizard interface implementation can achieve various tasks such as registering the SQL database for ASPNET_Memberships or even setting up a few settings in Web.Config file before we start coding our project.

IWizard Interface

Before we start looking at building our own template with a Wizard, I would like to explain some elements of the IWizard interface.

IWizard interface allows us to define the logic for a template.  You have to create a class by implementing the IWizard interface.

The IWizard interface has the following methods.

BeforeOpeningFile - Runs custom wizard logic before opening an item in the template.

ProjectFinishedGenerating - Runs custom wizard logic when a project has finished generating.

ProjectItemFinishedGenerating - Runs custom wizard logic when a project item has finished generating.

RunFinished - Runs custom wizard logic when the wizard has completed all tasks.

RunStarted - Runs custom wizard logic at the beginning of a template wizard run.

ShouldAddProjectItem - Indicates whether the specified project item should be added to the project.

Based on your Wizard template requirements you can code any of the above events.  In this article I will code the RunStarted event.

$<variable>$ Use

The majority of the time the templates are required to replace a few words when the project is created.  For example, if you wanted to assign the connectionstring in Web.Config file based on user input, then you would create the Web.Config connectionstrings section as the following.

Listing 1

<connectionStrings>
    <remove name="LocalSqlServer"/>
    <add name="LocalSqlServer" connectionString="$LocalHostString$"
 providerName="System.Data.SqlClient"/>
  </connectionStrings>

The Wizard Interface will be tasked with replacing the $LocalHostString$ value.  The way the Wizard replaces this string is by using the System.Collections.Generic.Dictionary object.

Before we begin

In this article I will give step-by-step information on creating a Wizard template which gets the information about the server, database, userID and Password.  Based on this information, it will register the database to be used for login, membership, roles, etc. for the website.  In order to register a database for ASPNET, you would normally use the aspnet_regsql.exe wizard.  This wizard will walk you through creating the related tables and stored procedures on specified server.

aspnet_regsql.exe wizard

This wizard will display various screens to get information from the user to create the tables and stored procedures.  In our scenario we would like to automate this procedure and not display all these screens.  In order to do this, we need to look at the various options of aspnet_regsql.exe

Figure 1

-W

Will run in Wizard Mode

-C

Connection String to the computer running SQL Server where the database will be installed.  You can also specify -S and login parameters and not use this option.

-S

The name of the computer running SQL Server where the database will be installed.

-U

The SQL Server User ID to login with

-P

The password to login with

-E

Authenticates using the Windows credential

-d

The database to create or modify

-A all|m|r|p|c|w

What all support needs to be added

 Options are

All - All features

M - Membership

R - Role Management

P - Profile

C - Web Parts Personalization

W - Web Events

- R all|m|r|p|c|w

Removes support for specified feature

- Q

Runs the tool in Quiet Mode and does not confirm before removing any feature

In order to create our database with all features, you will use the following command:

Listing 2

aspnet_regsql.exe -S<servername> -E -d<databasename> -A all 

In order to call this command we will use the Shell function. The syntax will be the following code.

Listing 3

Shell("C:\Windows\system32\cmd.exe /C
 C:\WINDOWS\Microsoft.Net\Framework\v2.0.50727\aspnet_regsql.exe -S
 """ & txtServer.Text & """ -E -d
 """ & txtDatabase.Text & """ -A
 all", AppWinStyle.Hide)

The AppWinStyle.Hide will make sure that we do not see the command window popup and go away.

Creating your IWizard Implementation Class

In order to create your own IWizard class, you need to follow these steps:

·         Create a Project of the type Class Library.

·         By Default, the project will open a class file with the name Class1.  Change the class name appropriately.

·         You will need to import the following:

Listing 4

Imports System
Imports system.collections.Generic
Imports Microsoft.VisualStudio.TemplateWizard
Imports System.Windows.Forms

·         Make sure your class implements IWizard interface.

·         As soon as you implement the IWizard interface, VS will add the methods that can be implemented in this class.

With the above steps you just created your own Wizard implementation class.  In our example we are going to use a Window form to get user input regarding Server, database, userID and password information.  In order to create the window you will need to follow these steps.

·         Right Click on the project and click on Add->Windows Form. With VS 2005 you can also add dialog form directly by Add->New Item and selecting Dialog template if you are interested.

·         The form will be added.  Add four label controls and set the text to Server:, Database:, UserID: and Password:.  Add four textboxes and set the ID property to txtServer, txtDatabase, txtUserID and txtPassword.  Your form should look like the following figure.

Figure 2

·         View Code for this form.

·         Declare a private variable for the LocalHostString to store the connection String.

Private LocalHostString As String

·         Code the Ok buttons click event as follows.

Listing 5

Private Sub btnOk_Click(ByVal sender As System.ObjectByVal e As System.EventArgs) Handles btnOk.Click
        If txtServer.Text <> "" AndAlso txtDatabase.Text <> "" Then
            Shell( _
 "C:\Windows\system32\cmd.exe /C C:\WINDOWS\Microsoft.Net\Framework\v2.0.50727\aspnet_regsql.exe -S""" & _
  txtServer.Text & """ -E -d""" & _
  txtDatabase.Text & """ -A all", AppWinStyle.Hide)
            LocalHostString = "Initial Catalog=" & txtDatabase.Text & ";Data Source=" &
 txtServer.Text & ";User ID=" & txtUserId.Text &
 ";Password=" & txtPassword.Text
        End If
        Me.DialogResult = System.Windows.Forms.DialogResult.OK
        Me.Close()
    End Sub

·         In the above code we first do the registration using the Shell command to call the ASPNet_regsql command and pass in the server and database name.  Once that is done, we build the LocalHostString based on the user input.

·         Now we need to create another function that will return the LocalHostString.

Listing 6

Public Function GetLocalHostString() As String
        Return LocalHostString
    End Function

·         Now our form is ready to accept user input for server, database, userID and password.  The next step is to call this form through Wizard implementation class.

·         In order to call this form, we will be implementing the RunStarted method in our class.

·         We need to declare LocalHostString as Private variable on our Implementation class too.  Also, we will define the form as a private member.

Listing 7

Private dbform As ArticleForm
    Private LocalHostString As String

·         This method will open the form, get the LocalHostString value and then use the System.Collections.Generic.Dictionary to replace the $LocalHostString$ variable in our template.  The code in RunStarted will look like Listing 8.

Listing 8

Public Sub RunStarted(ByVal automationObject As ObjectByVal replacementsDictionary As System.Collections.Generic.Dictionary(Of StringString), _
 ByVal runKind As Microsoft.VisualStudio.TemplateWizard.WizardRunKind, ByVal customParams() As Object) _
Implements Microsoft.VisualStudio.TemplateWizard.IWizard.RunStarted
        dbform = New ArticleForm
        dbform.ShowDialog()
        LocalHostString = dbform.GetLocalHostString
        replacementsDictionary.Add("$LocalHostString$", LocalHostString)
End Sub

·         In the above code we are opening the ArticleForm (my form) as a dialog box and once the dialog box is closed we are getting the LocalHostString value.  We then add this variable to the dictionary to be used in our template at a later stage.

·         Once this is created, you need to sign this assembly and then install it in GAC to be used with your template.

Signing the Assembly

In Visual Studio 2005, signing assembly is easy.  Steps involved are:

·         In Solution Explorer, from the Project Menu, Click Properties.

·         In the Project Designer click the Signing Tab.

·         Select the Sign the Assembly check box.

·         In the Choose a strong name key file dropdown list select New…

·         The new key file will be stored as .pfx format.

·         In the create Strong Name Key dialog box enter a name and password for the new key file.

Figure 3

·          Click Ok.

·         Your signing tab should now look like the following.

Figure 4

·         You can also browse to an existing key file if you have already created one.

Installing the assembly in GAC

There are various methods for installing the assembly in GAC.  For this article I will explain how to install the assembly using .NET framework 2.0 configuration tools.

·         Go to Control Panel -> Administrative Tools and in Microsoft .NET framework 2.0 Configuration tool.

Figure 5

·         Expand My Computer.

·         Click on Assembly Cache.

Figure 6

·         Click on Add an Assembly to the Assembly Cache Link.

·         The Add an Assembly dialog box will open.

Figure 7

·         Select the Wizard assembly.

·         You can view the assemblies by clicking on View List of Assemblies in the Assembly Cache.

Figure 8

You will notice that ArticleWizard has been added to the assembly cache now.

Web.Config file

We can use the same project which we used in the previous article.  Open the Web.Config file and add the following to the ConnectionStrings Section.

Listing 9

<remove name="LocalSqlServer"/>
    <add name="LocalSqlServer" connectionString="$LocalHostString$" providerName="System.Data.SqlClient"/>

The $LocalHostString$ will be replaced once the wizard is run.

Making changes to the vsTemplate file

Once the above changes are done on Web.Config file, you can export the template.  Follow these steps to make changes to the vsTemplate file to use this wizard.

·         Locate the zip file that was created when you exported the file.  You can find the location of the zip file by going to Tools->options->Projects and Solutions.

Figure 9

·         Extract the contents of the zip file.

·         Edit the MyTemplate.vsTemplate file.

·         Add the following after the TemplateContent section.

Listing 10

<WizardExtension>
    <Assembly>ArticleWizard, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=78777d1dc618b0a3</Assembly>
    <FullClassName>ArticleWizard.Class1</FullClassName>
</WizardExtension>

·         ArticleWizard in Assembly element is the assembly name while version is the current version of the assembly.  The PublicKeyToken can be found out by just going to the GAC and the publickeytoken is specified next to the assembly.

·         Zip the template again.

With the above steps you have created the Template which uses a Wizard.  Now you can open VS 2005 and click on New->Web Site.  Select the newly created Wizard; you should be able to enter your server, database, userID and password information.  After clicking ok, it will create the database on the server specified and also create the connection string in the Web.Config file.

Summary

In this article I explained how we could use the Wizard interface to create a Wizard based template and automate some of the steps involved in creating a project.  There are many ways developers can automate their processes for new project development; it all depends on your visualization.  For me, I am always looking at ways to speed up the development process.



User Comments

Title: Clarification   
Name: Jon
Date: 2007-01-09 3:34:33 PM
Comment:
As a clarification, VS will still use the old version even after I go into the cache through the control panel and remove it.
Title: Development Process   
Name: Jon
Date: 2007-01-09 3:32:22 PM
Comment:
What's the best way to actually build and test a wizard from the ground up?

I have my build process for the Wizard's project set up to sign the DLL and automatically add itself to the GAC (using: "gacutil.exe /if $(TargetPath)").

The problem is they will stay in the cache after every rebuild, so I need to either update the version number in the vsTemplate file and the project after each compile, or restart Visual Studio each time I want to test a new build.

Advice?
Title: VB Bug ?   
Name: frisla
Date: 2006-09-20 9:52:51 AM
Comment:
Hi A

The test for C# and VB.NET wore created as separated projects - C# Custom wizard and template project, VB Custom wizard and template project.

In VB as soon as I try to access my IWizard implementation, my VB template project wil not unfold, hence the error message. The template itself executes perfectly, but again as soon as I try to reference my custom wizard, using an "WizardExtension" entry in the xx.vstemplate I get the error message.

Any suggestions

- Thanks -
Title: No   
Name: Ameet
Date: 2006-09-19 7:37:26 PM
Comment:
The article was written using VB.NET and not C#.NET.

Check whether you have created the template itself for C#.NET...
Title: VB Bug ?   
Name: frisla
Date: 2006-09-19 4:01:54 PM
Comment:
Why is it you get a, "Unable to copy the file 'Application.myapp' from the project template to the project. Cannot find file ...." failure when you use VB.NET (2005), but using C# is a walk in the park ??????

Is the execution of the IWizard interface different in VB.NET ?????

Product Spotlight
Product Spotlight 





Community Advice: ASP | SQL | XML | Regular Expressions | Windows


©Copyright 1998-2019 ASPAlliance.com  |  Page Processed at 2019-10-19 1:18:18 PM  AspAlliance Recent Articles RSS Feed
About ASPAlliance | Newsgroups | Advertise | Authors | Email Lists | Feedback | Link To Us | Privacy | Search