On this page....
Archives
<October 2008>
SunMonTueWedThuFriSat
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

Feed your aggregator (RSS 2.0)
Search
Categories
About

My LinkedIn profile

Powered by: newtelligence dasBlog 2.1.8102.813

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

© Copyright 2012, Christian Bækdorf

Send mail to the author(s) E-mail



Sign In
# Wednesday, October 08, 2008
« DSL and Visual Studio Shell tutorial: Ad... | Main | DSL and Visual Studio Shell tutorial: Cr... »

This post is part of a larger tutorial on DSL Tools and Visual Studio 2008 Isolated Shell, in this post I will go through the steps to add a custom project type to the Shell application.

Previous step: Adding the DSL to the Shell

Creating a new Visual Studio Integration Package

A custom project types is implemented as a Visual Studio Integration Package, so the first step is to add a new integration package to the Shell solution.

1. New project

Choose Add New Project and select the Visual Studio Integration Package project template.

Name the project “MyDslProject” and accept the default location.

2. Welcome page

Just click next

3. Choose programming language and strong name key

Choose C# as programming language and just create a new strong name key.

4. Company name and package name

Specify company name and package name as shown below

5. Testing project

Deselect both Integration Test Project and Unit Test Project.

Press Finish to create the project

6. Resulting solution

The solution should now look as shown below.

7. Shell Dependencies

Now set the shell dependencies for the “MyDslShell” project, so the project will depend on “MyDslProject”. Right-click “MyDslShell” project and choose “Shell Dependencies…”.

Adding a Package Load Key (PLK)

The “MyDslProject” is a Visual Studio integration package, so we need to add a Package Load Key (PLK) to the project.

1. Gathering necessary information for obtaining a PLK

To obtain a PLK you will need the following information:

  • Company name
  • Package name
  • Package Guid
  • Package version

The first part of the information can be found in “MyDslProjectPackage.cs” file, as shown below

The package Guid can be found in “Guids.cs”

2. Obtaining a Package Load Key (PLK)

You can obtain a Package Load Key (PLK) from MSDN: Generate Load Keys

Enter the information about your package; choose “Standard” as Min. Product Edition and “Visual Studio 2008” as min. VS Version. Finally press “Generate PLK”.

3. Adding the Package Load Key (PLK) to MyDslProject

We have to add the PLK to the “MyDslProject” projects resource file “VSPackage.resx”. Insert in in the entry with “1” as name without any newlines.

Integrating Managed Package Framework for Projects

Next we have to integrate the Managed Package Framework for Projects into the “MyDslProject” project. This we will do be manually editing the “MyDslProject.csproj” in it’s XML form. If you have Power Commands for Visual Studio 2008 installed you can right-click the project and choose Edit Project File.

1. Editing the project file

First you will have to add the line shown below:

    <ProjectBasePath>..\..\MPFProj\9.0\Src\CSharp</ProjectBasePath>

Then add the line below as shown below:

  <Import Project="$(ProjectBasePath)\ProjectBase.Files" />

2. Reload the project in Visual Studio

When reloading the project, you will get a warning as show below. Just choose Load project normally.

3. Adding required reference

The Managed Package Framework for Projects uses some extra assemblies, which we need to reference before the project can compile.

Add a reference to EnvDTE, as show below.

Add a reference to Microsoft.VisualStudio.Designer.Interfaces, as show below.

The “MyDslProject” should now be able to compile.

Implementing the custom project type

Now we are ready to implement the new custom project type for the DSL project.

1. Defining a project type Guid

First we have to define a Guid for our new project type, just generate a new Guid.

Add the new project type Guid to the “Guids.cs” file as show below:

    public const string guidMyDslProjectFactoryString =

        "1584A98D-D032-4709-9AC0-C3F2A8C93857";

    public static readonly Guid guidMyDslProjectFactory =

        new Guid(guidMyDslProjectFactoryString);

2. Adding factory and node classes

To implement a custom project we need a factory class for instantiating new projects and project node class.

Add two C# classes to the “MyDslProjectFactory” and “MyDslProjectNode.cs” to the “MyDslProject” project. Your solution should then look as shown below.

3. Implement the “MyDslProjectNode” class

Implement a simple project node as shown below:

    [Guid("8D681873-2A8D-442b-82CE-ED96C69D02D7")]

    public class MyDslProjectNode : ProjectNode

    {

        internal const string ProjectTypeName = "MyDslProject";

        private MyDslProjectPackage m_Package;

 

        public MyDslProjectNode(MyDslProjectPackage package)

        {

            m_Package = package;

        }

 

        public override string ProjectType

        {

            get { return ProjectTypeName; }

        }

 

        public override Guid ProjectGuid

        {

            get { return typeof(MyDslProjectFactory).GUID; }

        }

    }

The project node needs a Guid, just generate a new Guid not used in any other place.

4. Implement the “MyDslProjectFactory” class

Implement a simple project factory as shown below:

using System;

using System.Runtime.InteropServices;

using Microsoft.VisualStudio.Project;

using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider;

 

namespace MyCompany.MyDslProject

{

    [Guid(GuidList.guidMyDslProjectFactoryString)]

    public class MyDslProjectFactory : ProjectFactory

    {

        private MyDslProjectPackage m_Package;

 

        public MyDslProjectFactory(MyDslProjectPackage package)

            : base(package)

        {

            m_Package = package;

        }

 

        protected override ProjectNode CreateProject()

        {

            MyDslProjectNode project = new MyDslProjectNode(this.m_Package);

            IServiceProvider serviceProvider = (IServiceProvider)this.m_Package;

            IOleServiceProvider oleServiceProvider =

                (IOleServiceProvider)serviceProvider.GetService(typeof(IOleServiceProvider));

            project.SetSite(oleServiceProvider);

            return project;

        }

    }

}

5. Change package base class

Change the base class in “MyDslProjectPackage” class, so that it inherits from ProjectPackage, as show below:

    public sealed class MyDslProjectPackage : ProjectPackage

    {

        /// ...

    }

6. Register project type

The project factory must be registered in the Initialize method in the MyDslProjectPackage class. Add a call to RegisterProjectFactory as shown below:

    public sealed class MyDslProjectPackage : ProjectPackage

    {

        protected override void Initialize()

        {

            Trace.WriteLine (string.Format(CultureInfo.CurrentCulture,

                "Entering Initialize() of: {0}", this.ToString()));

            base.Initialize();

            this.RegisterProjectFactory(new MyDslProjectFactory(this));

        }

    }

7. Adding ProvideProjectFactory attribute

A package implementing a project type must be attributed with the “ProvideProjectFactory” attribute. Add a “ProvideProjectFactory” attribute to the “MyDslProjectPackage” class as show below:

    [ProvideProjectFactory(typeof(MyDslProjectFactory),

        "MyDsl Project",

        "MyDsl Project Files (*.mydslproj);*.mydslproj",

        "mydslproj", "mydslproj",

        @"\\null",

        LanguageVsTemplate = "MyDslProject",

        NewProjectRequireNewFolderVsTemplate = true)]

    public sealed class MyDslProjectPackage : ProjectPackage

    {

    }

Adding a project template

Finally we have to create a new project template for our custom project type.

1. Add template folder

First we have to add a template folder in the “MyDslProject”. Add a folder named “Templates”, a subfolder named “Projects” and finally a subfolder “MyDslProject”, as show below.

2. Add a DSL item file

Add an empty text file named “MyDsl1.mydsl1” to the “MyDslProject” folder, as shown below.

3. Add a project icon

Add an icon file named “MyDslProject.ico” to the “MyDslProject” folder, as shown below.

4. Add a project file

Add a project file named “MyDslProject.mydslproj” to the “MyDslProject” folder, with the content shown below:

<Project InitialTargets="" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <PropertyGroup>

    <SchemaVersion>2.0</SchemaVersion>

    <ProjectGuid>{1584A98D-D032-4709-9AC0-C3F2A8C93857}</ProjectGuid>

    <OutputPath>bin\Debug\</OutputPath>

  </PropertyGroup>

  <ItemGroup>

    <Content Include="MyDsl1.mydsl1">

      <SubType>Content</SubType>

    </Content>

  </ItemGroup>

  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

</Project>

5. Add a vstemplate file

Add a project file named “MyDslProject.vstemplate” to the “MyDslProject” folder, with the content shown below:

<VSTemplate Version="2.0.0" Type="Project"

    xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">

  <TemplateData>

    <Name>MyDsl Project</Name>

    <Description>Create a new MyDsl project</Description>

    <ProjectType>MyDslProject</ProjectType>

    <SortOrder>1000</SortOrder>

    <CreateNewFolder>true</CreateNewFolder>

    <DefaultName>MyDslProject</DefaultName>

    <ProvideDefaultName>true</ProvideDefaultName>

    <LocationField>Enabled</LocationField>

    <EnableLocationBrowseButton>true</EnableLocationBrowseButton>

    <Icon>MyDslProject.ico</Icon>

  </TemplateData>

  <TemplateContent>

    <Project TargetFileName="MyDslProject.mydslproj" File="MyDslProject.mydslproj" ReplaceParameters="true">

      <ProjectItem TargetFileName="MyDsl1.mydsl1">MyDsl1.mydsl1</ProjectItem>

    </Project>

  </TemplateContent>

</VSTemplate>

6. Set build action

Select the four template files added in the above steps and set the build action to ZipProject.

7. Add copy events

Add an after build action to copy the template file to the output folder. Open the “MyDslProject.csproj” file so you can edit it directly, and add the XML shown below:

  <Target Name="AfterBuild">

    <MakeDir Directories="$(SolutionDir)$(Configuration)\ProjectTemplates" />

    <MakeDir Directories="$(SolutionDir)$(Configuration)\ItemTemplates" />

    <Copy SourceFiles="@(IntermediateZipProject)" DestinationFolder="$(SolutionDir)$(Configuration)\ProjectTemplates" />

    <Copy SourceFiles="@(IntermediateZipItem)" DestinationFolder="$(SolutionDir)$(Configuration)\ItemTemplates" />

  </Target>

8. Specify template folder

The Shell application needs to know where to look for templates, so you have to specify the template folders.

Open the “MyDslShell.pkgdef” in the “MyDslShell” project and append the following in to bottom of the file:

[$RootKey$\VSTemplate\Project]

"UserFolder"="$RootFolder$\ProjectTemplates"

"CacheFolder"="$RootFolder$\ProjectTemplatesCache"

 

[$RootKey$\VSTemplate\Item]

"UserFolder"="$RootFolder$\ItemTemplates"

"CacheFolder"="$RootFolder$\ItemTemplatesCache"

Testing the project

Everything should now be in place and we are ready to test the new custom project type.

1. Building the solution

Rebuild the entire solution. After rebuilding completes check the output folder (e.g. ), it should look as shown below.

2. Running the application

Run the solution and select File -> New -> Project on the menu and you should see the new project type as shown below.

3. Create a new project

Choose OK in the new project and you should get a new project with a DSL file as shown below.

You can now start use the DSL and create diagrams.

Summary

This end the fifth post about adding custom project type to the Shell application, next step is about creating a setup project for the entire Shell application, so it can be deployed.

Next step: Coming soon!

Download: DslToolsAndVsShell-05.zip (7 MB)

Wednesday, October 08, 2008 8:04:16 PM (Romance Standard Time, UTC+01:00)  #    Disclaimer  |  Comments [151]  |