***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
This time I will talk about the new DSL extensibility feature in DSL VS10. This feature allows a model to be extended after it is deployed. This opens a huge number of possible scenarios including third party ones.
In this part I will cover the core changes and concepts in the new version of DSL to support the extensibility feature.
A DSL extension is indeed another DSL. This means that a DSL is extended by creating another DSL.
From now on I will refer to them as the extendee DSL and extension DSL respectively.
These are just a couple of extensibility points that can be provided (just to mention some of them):
- Add new domain classes / domain relationships
- Add new extension elements to existing model elements
- Add new commands
- Add modeling rules
But the real thing is that we can completely override the behavior of the extendee DSL. What really happen behind the scenes is that the extendee domain model plus all the extension domain models found are being loaded into the same store.
The new ExtensionElement domain class
In the runtime there is a new abstract class called “ExtensionElement” that inherits from the well known ModelElement. This class is used to represent an extension to a model element. It also called “MEX”.
The new “Extensions” domain relationship
The ModelElement was updated and now includes a new “Extensions” domain property. This is basically an embedding relationship between ModelElement and ExtensionElement.
MEX extension methods
Under the new Microsoft.VisualStudio.Modeling.Extensibility namespace, there are a couple of useful extension methods for the ModelElement class to do CRUD operation over the ModelElement extensions.
Next part : MEF, extension providers and how extension domain models are being injected
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
In the previous version of the VS SDK, when we create an Isolated Shell project, there is a command to specify Shell Dependencies:
When we compile the project, those dependencies plus any pkgdef file are being copied to the \PackagesToLoad subfolder.
Now is VS10, the Shell Dependencies command is gone and the way to add dependencies is via the References button. (which seems more natural to me)
Another change is that the PackagesToLoad subfolder was renamed to “Extensions” to be sync with the full IDE extension naming thing. :)
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
Another new feature of the new version of the DSL toolkit is the ability to locks certain operations in a DSL. The idea is that we can define locking policies for a DSL and those policies are executed at runtime to constraint specific operations such as Add/Delete/Update etc.
These locking policies can be defined at three different levels , Store, Partition and ModelElement respectively.
Defining our own locking policies
It is really simple to create our own policy class, we just need to create a class that inherits from ILockingPolicy.
Then we need to define the locks that we are going to return, and for that we have three levels of granularity:
- Store
- Partition
- ModelElement
Locks are transitive following the “Store –> Partition –> ModelElement” object hierarchy.
That means that if we set locks at the Store level, those locks also apply to the Partition and the ModelElement levels.
The lock types are:
public class MyLockingPolicy : ILockingPolicy
{
public Locks RefineLocks(ModelElement element, Locks proposedLocks)
{
return proposedLocks;
}
public Locks RefineLocks(Partition partition, Locks proposedLocks)
{
return proposedLocks;
}
public Locks RefineLocks(Store store, Locks proposedLocks)
{
// TODO: return corresponding locks and they will also apply to Partition and ModelElement
}
}
Injecting our own ILockingPolicy
The Store class constructor sets the locking policy by querying for a ILockingPolicy service. That means that one possible way to inject our own locking policy is to override the GetService method and return our policy class:
internal partial class MyDocData
{
private ILockingPolicy myLockingPolicy;
public override object GetService(Type serviceType)
{
if (serviceType == typeof(SLockingPolicy) || serviceType == typeof(ILockingPolicy))
{
if (myLockingPolicy == null)
{
myLockingPolicy = new MyLockingPolicy();
}
return myLockingPolicy;
}
return base.GetService(serviceType);
}
}
At runtime the DSL infrastructure will query for existing locks using a set of extension methods located in the new ImmutabilityExtensionMethods class and constraint or not an operation accordingly.
The hardware model sample
I published a sample that shows how to lock a DSL.
The scenario is that there are two personas:
- Developer: He uses the VS full IDE to author a hardware model.
- Architect: He uses an Isolated shell to review the model and cannot do any modifications to it.
The locks are being set by detecting the shell SKU.
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
Creating a custom instance/hive for Visual Studio is easier than ever. In this post I will show the details to create a fictitious “pga” instance and configure our VSX development environment to point to it.
This can be useful in some testing scenarios or when we just don’t want to reset the experimental instance to test something.
Creating the pga instance
To create a new instance we use the CreateExpInstance tool:
%VSSDK_Installdir%\VisualStudioIntegration\Tools\Bin\CreateExpInstance.exe /Reset /VSInstance=10.0 /RootSuffix=pga
Once we do that the following directory is created:
%LocalAppData%\Microsoft\VisualStudio\10.0pga\Extensions\
And all existing extensions in the main hive are copied to:
%LocalAppData%\Microsoft\VisualStudio\10.0pga\Extensions\Extensions-10.0
Redirecting the VS SDK msbuild target to the pga instance
Every time that we compile a VSPackage project the Microsoft.VsSDK.targets msbuild target is executed doing all the necessary steps to deploy our extension.
But the default behavior is to deploy the extension under the experimental instance. To override that behavior we need to include the following property in the VSPackage csproj file:
<PropertyGroup>
<VSSDKTargetPlatformRegRootSuffix Condition="'$(VSSDKTargetPlatformRegRootSuffix)' == ''">pga</VSSDKTargetPlatformRegRootSuffix>
</PropertyGroup>
Executing VS pointing to the pga instance
To point Visual Studio to a particular instance we just use the /rootSuffix switch:
%VS_Installdir%\devenv.exe /rootSuffix pga
Or we can just enable the F5 experience from the Debug tab in the project properties:
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
In the first part I covered the details of the T4 Preprocessing API.
Now it’s time to create a preprocessed text template and mimic the GAX property directive processor feature.
Let’s add a preprocessed text template. For that purpose there is a new item template in the VS10 Add new item dialog:
After we add a pre-compiled template item, we can see the output of the transformation:
As you can see, the namespace is calculated from the project default namespace property, and the tt item name is used to calculate the class name.
Using properties to mimic the GAX PropertyProcessor directive
After the TemplatedPreprocessor runs we end up with a template class, which is just a regular class with some helper methods to write the transformation.
These methods are similar to the ones provided in the base TextTransformation class. But to remove the dependency to the Microsoft.VisualStudio.TextTemplating.10.0 assembly those methods are now part of our template class.
To add properties that will be consumed inside the template, it is just a matter of declaring a partial class and adding them there:
namespace PreTT
{
public partial class MyPreTextTemplate
{
public string MyProperty { get; set; }
}
}
Then from within the template we can just refer to the property:
<#@ template language="C#" #>
MyProperty value is <#= this.MyProperty #>
To test the transformation we create an instance of the template class and we call the TransformText method:
public static void Main(string[] args)
{
Console.WriteLine(
new MyPreTextTemplate { MyProperty = "Foo" }
.TransformText());
Console.Read();
}
And the transformation output is :
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
Gareth wrote some time ago two nice posts about the T4 Preprocessing feature:
This post will have two parts. The first one will cover the details of the new API and the second one will show how to create a preprocessed text template and the how to mimic the GAX property directive processor feature using partial classes.
The precompiled text template feature is really useful in scenarios where the text templates doesn't change at run time.
Let’s say that we have an application that uses a set of templates for code generation, and those templates never change.
This is a perfect fit for precompiled templates. Instead of deploying a set of .tt files as part of the application, we can pre-compile them and they now can be part of the main application assembly or any other component assembly.
This *drastically* improves the performance because on each transformation this is what happens behind the scenes in order to get a transformation result:
- A template processor calls the template engine that:
- Parses the template
- Processes the directives
- Generates the template class
- If the text template doesn’t cache the assemblies (CacheAssemblies="false”) or if the application domain needs to be recycled
- The template host creates an application domain
- The template host resolves the assembly references that are defined in the template
- The template host creates a transformation runner that:
- Compiles the generated template class into a temporary assembly
- Loads the temporary assembly into the application domain
- Calls the “TransformText” method that returns the transformation result
- Else
- The template host creates a transformation runner that:
- Uses the cached assembly
- Calls the “TransformText” method that returns the transformation result
With a precompiled template we skip all the steps in *bold* and we just call the “TransformText” method in the compiled template class that is part of the application or component assembly.
Also, having a precompiled template means that a transformation can run in any .Net environment without the need of having Visual Studio or the Microsoft.VisualStudio.TextTemplating.* assemblies installed.
API changes to support template preprocessing
- The following two interfaces were updated to include the new PreprocessTemplate method:
public interface ITextTemplating
{
string PreprocessTemplate(string inputFile, string content, ITextTemplatingCallback callback, string className, string classNamespace, out string[] references);
}
public interface ITextTemplatingEngine
{
string PreprocessTemplate(string content, ITextTemplatingEngineHost host, string className, string classNamespace, out string language, out string[] references);
}
- A new TemplatedPreprocessor custom tool /single file generator was added:
This new custom tool is the responsible for creating the template class at design time. This tool basically does the following:
- Parses the template
- Processes the directives
- Generates the template class
Stay tuned,
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
In the first part of this series I described general concepts around the ModelBus infrastructure. In this second part I will describe the model bus service and how MEF is involved.
The ModelBus as a Service
The Microsoft.VisualStudio.Modeling.Sdk.Integration.Shell.10.0 is a VS Package that defines one core service, the IModelBus service.
The model bus service creates and uses its own MEF composition container with two directory catalogs pointing to:
- %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions
- %VS10_Install_Dir%\Extensions
A DSL exports an adapter manager and provides some metadata to specify which adapter this manager manages:
[Export(typeof(ModelBusAdapterManager))]
[HandlesAdapter(“MyAdapterId”)]
public partial class MyAdapterManager : VsModelingAdapterManager
{
…
}
The main responsibility of the model bus is to find registered adapter managers, for that the composition container is used:
container.GetExportedObjects<ModelBusAdapterManager>()
In order to register a DSL with the model bus we need to do the following steps:
- Update the model definition to introduce a domain property that will hold the model reference
- Update the model serialization behavior to include the model reference serialization
- Create an adapter for the DSL
- Create an export an adapter manager for the DSL
- Deploy the DSL under extensions (done automatically at compilation time via the VS SDK msbuild target)
Stay tuned,
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
One of the new main features of the new version of the DSL toolkit is the “ModelBus”. The model bus basically allows a model element to reference another model element (ModelBusReference). These two model elements could be defined either in the same DSL or in different ones. With a ModelBusReference we can do interesting model interactions such as navigating the references back and forth, performing validation across models, etc.
The ModelBus infrastructure lives in two core assemblies:
- Microsoft.VisualStudio.Modeling.Sdk.Integration.10.0
- Microsoft.VisualStudio.Modeling.Sdk.Integration.Shell.10.0
Microsoft.VisualStudio.Modeling.Sdk.Integration.10.0
As the name implies, this assembly contains concepts that are totally decoupled from Visual Studio.
The main generic concepts are:
ModeBusAdapter
Is a bridge between the model bus and the underlying model. Therefore each model has its own adapter.
It’s main responsibilities are:
- Get all references of an element type
- Resolve a reference into an object
- Get the view associated with the model
ModelBusAdapterManager
Is used to create and control the lifetime of adapters.
It’s main responsibilities are:
- Create adapters
- Create reference to a model
- Return the list of supported adapters
- Return the list of exposed element types. An exposed element type is an element that can be referenced by another element
ModelBusReference
Encapsulates information about a reference in the model bus. It is composed of:
- Adapter reference
- Adapter id
- Model display name
- Element display name
It is being serialized as:
ModelBusAdapterReference
Represents the base class for adapter references
ModelBusView
Allows a client to manipulate the design surface of the model (if applicable)
It’s main responsibilities are:
- Open view
- Close view
- Show view
- Hide view
- Select UI elements
Then we have a set of derived classes that are specific to DSLs:
- ModeBusAdapter<- ModelingAdapter
- ModelBusAdapterReference <- ModelingAdapterReference
ModelingAdapter
Represents the base class for DSL based adapters. In this case the model is a DSL model.
ModelingAdapterReference
Encapsulates information about a model element reference, it is composed of:
- Model element id
- View id
- Model file absolute path
It is being serialized as:
Microsoft.VisualStudio.Modeling.Sdk.Integration.Shell.10.0
In this assembly there are concepts that are coupled to the Visual Studio infrastructure.
VsModelingAdapterManager
This adapter manager introduces the notion of document handlers that knows how to handle a DocData concept.
VsModelingView
This implementation is tied to the DocView concept.
Stay tuned,
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
There is a really useful utility in the new version of DSL, that is the Store Viewer.
The API to use it is really simple:
using Microsoft.VisualStudio.Modeling.Diagnostics;
StoreViewer.Show(store);
With this viewer already implemented, the next logic step for me is to have a VS debugger visualizer. We should cross the fingers and maybe in the next Beta 2 we will see it.
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
When we are developing a VS package it is really common to declare and promote services.
Let’s first recap how do we create a VS service:
- We decorate our package class with the ProvideService attribute
- We promote the service (make it visible to other VS Packages) at service creation time
[ProvideService(typeof(SMyService))]
public sealed class ServicesPackage : Package
{
public ServicesPackage()
{
}
protected override void Initialize()
{
base.Initialize();
IServiceContainer serviceContainer = (IServiceContainer)this;
serviceContainer.AddService(typeof(SMyService), new MyService(), true); //true to promote the service
}
}
[Guid("70673710-F36C-4B09-9468-0D0A7A1F7BCF")]
public interface SMyService : IMyService
{
}
public interface IMyService
{
void DoStuff();
}
internal class MyService : SMyService
{
public void DoStuff()
{
}
}
Once the service is declared and promoted it can be consumed from other packages or components.
Couple of points with this implementation:
- VS Services are singletons
- VS Packages are lazy loaded by VS
- In this particular case the VS Package will be loaded when another component queries the service via the GetService method.
var myService = (IMyService)GetService(typeof(SMyService)); myService.DoStuff();
Now let’s create a MEF export:
- We create a CompositionContainer
- We declare the Export
public sealed class ServicesPackage : Package
{
public ServicesPackage()
{
}
protected override void Initialize()
{
base.Initialize();
var editorCompositionContainer =
VsCompositionContainer.Create(
this.ComponentModel.GetCatalog("FooCatalog"),
new VsExportProviderSettings(
null, VsExportProvidingPreference.Default, VsExportSharingPolicy.ShareEverything, false));
}
}
To declare the export we use the PartCreationPolicy attribute to specify that the part will be a singleton. (Just to mimic VS Services behavior)
[Export(typeof(IMyMEFService))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class MyMEFService : IMyMEFService
{
public MyMEFService()
{
}
public void DoStuff()
{
}
}
Consuming the export:
var componentModel = this.GetService(typeof(SComponentModel)) as IComponentModel;
var myMEFService = componentModel.GetExtensions<IMyMEFService>().FirstOrDefault();
myMEFService.DoStuff();
No lazy loading:
Before we can consume the export the container should be created.
But for that, the VS Package should be initialized. Therefore the package should be loaded before any other component tries to consume the exports.
This can be achieved with the ProvideAutoLoad attribute and the NoSolution context guid. But that means the VSPackage will be loaded at VS startup and therefore we loose the VS package lazy initialization feature that the ProvideService model has.
Maybe in the next VS10 Beta version we see a core package that creates a general purpose container that can be used to add global services, but for the time being there is no such container and you need to create a VS package that creates it.
Stay tuned,
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
This is the final part of this post series. I will show how to get the available exports.
To get the available exports I will use a command under the Tools menu:
The menu callback get the first registered IMessagingService export and calls the display message method:
private void MenuItemCallback(object sender, EventArgs e)
{
var componentModel = base.GetService(typeof(SComponentModel)) as IComponentModel;
var messaging = componentModel.GetExtensions<IMessagingService>().FirstOrDefault();
messaging.DisplayMessage("Hello MEF");
}
Couple of points:
- The SComponentModel service is used to get the available extensions
- The GetExtension method calls the GlobalCompositionContainer, which find all availables <TExport> in the list of containers that are maintaned by the VsExportProviderService class
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
In part 2 I will create the MEF contracts and parts. Two new projects will be added to the solution:
Let’s add a project for the contracts to the solution and name it MEFMessaging.Interfaces:
And declare the contract:
namespace MEFMessaging.Interfaces
{
public interface IMessagingService
{
void DisplayMessage(string message);
}
}
Now the parts:
For the parts I will use a project template that creates a VSIX MEF component, you can download from here
Let’s add a VSIX MEF component project to the solution and name it MEFMessagingComponent:
And define the parts:
For that we need to add a reference to the MEFMessaging.Interfaces project.
[Export(typeof(IMessagingService))]
[PartCreationPolicy(CreationPolicy.Shared)]
public class MessagingService : IMessagingService
{
[Import]
public IVsUIShell UIShell { get; set; }
public void DisplayMessage(string message)
{
int result = 0;
Guid guid = Guid.Empty;
UIShell.ShowMessageBox(
0, ref guid, string.Empty, message,
string.Empty, 0, OLEMSGBUTTON.OLEMSGBUTTON_OK,
OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST,
OLEMSGICON.OLEMSGICON_INFO, 0, out result);
}
}
Couple of points:
- We export the contract IMessagingService defined in the MEFMessaging.Interfaces project
- We import the IVsUIShell service, exported by the VSPackage class in part 1
- We use the VS Service to display a message box with the message
Specifying the catalog name:
To specify the catalog name we need to update VsCatalogName attribute to the AssemblyInfo.cs file
[assembly: VsCatalogName("Foo")] –> [assembly: VsCatalogName("MEFContainer")]
The MEF Component content type:
Because we used the MEF VSIX project template, we already have the content type set up.
In the next a final part I will show how to get the available exports (IMessagingService) and show messages.
Stay tuned,
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
In this series of post I will create a VS Package that will create a MEF container and export parts.
Those parts are going to be consumed by another project that will be another MEF component.
The source code for this sample is already in the Code Gallery.
Let’s first create a VS Package project and name it “MEFContainer”:
Then we need to add the following references to the project:
- Microsoft.VisualStudio.ComponentModelHost.dll
- Microsoft.VisualStudio.ExtensibilityHosting.dll
- System.ComponentModel.Composition.dll
Creating the container:
As I explained in a previous post, Visual Studio has its own version of a CompositionContainer, and it is the VsCompositionContainer class.
Lets examine the following piece of code:
var componentModel = this.GetService(typeof(SComponentModel)) as IComponentModel;
var editorCompositionContainer =
VsCompositionContainer.Create(
componentModel.GetCatalog("MEFContainer"),
new VsExportProviderSettings(null, VsExportProvidingPreference.Default, VsExportSharingPolicy.ShareEverything, false));
To create the container we need to provide a Catalog. Visual Studio also has its own version of a catalog, and it is the AssemblyListCatalog. This catalog holds a list of AssemblyCatalog instances.
To get the catalog we use the IComponentModel.GetCatalog method. This methods returns a list of assemblies that contains a VsCatalogName attribute with the “MEFContainer” value.
Also we need to provide a VsExportSettings, where we can define a scope, a sharing policy and export providing preference.
The following chunk of code creates the container:
public sealed class MEFContainer : Package
{
private static object synchLock;
static MEFContainer()
{
synchLock = new object();
}
protected override void Initialize()
{
base.Initialize();
InitializeContainer();
}
private void InitializeContainer()
{
object obj = null;
bool lockTaken = false;
try
{
Monitor.Enter(obj = synchLock, ref lockTaken);
var componentModel = this.GetService(typeof(SComponentModel)) as IComponentModel;
var editorCompositionContainer =
VsCompositionContainer.Create(
componentModel.GetCatalog("MEFContainer"),
new VsExportProviderSettings(null, VsExportProvidingPreference.Default, VsExportSharingPolicy.ShareEverything, false));
var batch = new CompositionBatch();
batch.AddPart(this);
editorCompositionContainer.Compose(batch);
}
finally
{
if (lockTaken)
{
Monitor.Exit(obj);
}
}
}
}
Exporting a part:
In this example I will declare an Export for the IVsUIShell service. And this export will be imported later in the MEF component project.
[Export(typeof(IVsUIShell))]
public IVsUIShell ServiceProvider
{
get
{
return (IVsUIShell)this.GetService(typeof(SVsUIShell));
}
}
Once we have the export defined, somehow it needs to be composed in the container, and that is being done when we compose the container:
var batch = new CompositionBatch();
batch.AddPart(this);
editorCompositionContainer.Compose(batch);
Specifying the catalog name:
To specify the catalog name we need to add the following attribute to the AssemblyInfo.cs file
[assembly: VsCatalogName("MEFContainer")]
The MEF Component content type:
The VS Package itself is a MEFcomponent and we need to specify that in the VSIX extension manifest.
Stay tuned,
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
One of the first new things that you notice when running VS10 for the first time is the new “New Project” dialog.
In this post I will describe how we can tweak a VSIX project template extension to show the information in the dialog.
I will use as a sample the VSIX template extension that I created for MEF VSIX projects.
The information in the new dialog comes from the vstemplate file, but instead of describing the mapping, I think that a picture is worth a thousand words:
As you can see from the picture, the ProjectType node in the vstemplate file, defines the category (Visual C#) in the tree on the left.
But how the template is being added under the “Extensibility” node in the tree?
Let’s take a look at the VSIX deployment installation folder:
%LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Pablo Galiano\MEF VSIX Project template\1.0\MEFVSIXProject\Extensibility
Every subfolder below \MEFVSIXProject is rendered as node in the tree. If we have for example:
%LocalAppData%\Microsoft\VisualStudio\10.0\Extensions\Pablo Galiano\MEF VSIX Project template\1.0\MEFVSIXProject\Pablo\Galiano
Pablo
I just created a new site in the Code Gallery that centralizes all the VSIX samples that I will create from now on.
The first sample uploaded is the source code of the MEF VSIX project template that I described in a previous post.
Enjoy,
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
Let’s say that we want to deliver our extension with a installer. How we can easily deploy our VSIX?
The VSIXInstaller tool supports the /quiet switch. That means that we can just have a custom action that calls the tool from within our msi:
<Property Id="VSINSTALLDIR">
<RegistrySearch Id="VSInstallRegistry" Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\10.0" Name="InstallDir" Type="directory" />
</Property>
<CustomAction Id="SetVSIXInstaller" Return="check" Execute="immediate" Property="VSIXInstaller" Value="[VSINSTALLDIR]VSIXInstaller.exe" />
<CustomAction Id="DeployVSIX" Property="VSIXInstaller" Execute="deferred" Impersonate="no" ExeCommand="/quiet" Return="asyncWait"/>
<InstallExecuteSequence>
<Custom Action="Set_SetVSIXInstaller" After="ValidateProductID">VSIXInstaller=""</Custom>
<Custom Action="DeployVSIX" After="MsiPublishAssemblies" />
</InstallExecuteSequence>
Pablo
I have just uploaded a new Visual Studio extension to the Visual Studio Gallery
It is basically a new project template to create MEF based Visual Studio extensions (VSIX)
The differences between this project template and the one that comes with the VS SDK are:
- Assembly references
- System.ComponentModel.Composition.dll
- Microsoft.VisualStudio.ExtensibilityHosting.dll
- A MyExport class in created
public interface IMyExport
{
}
[Export(typeof(IMyExport))]
public class MyExport : IMyExport
{
}
- The AssemblyInfo contains the VsCatalogName attribute
//TODO: Specify the catalog name for the exported objects
[assembly: VsCatalogName("Foo")]
- The extension manifest contains the MEFComponent content type
<Content>
<MEFComponent>MEFVSIXProject3</MEFComponent>
</Content>
After you install it, it is displayed under the Visual C# category
You can also discover it by browsing the Online Templates tab in the new Add New Project dialog:

Enjoy,
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
The following list describes the registry hives used by VS 2008 and VS10
VS 2008
Main hive
- Root: HKLM\Software\Microsoft\VisualStudio\9.0
- User settings: HKCU\Software\Microsoft\VisualStudio\9.0
Exp hive
- Root: HKCU\Software\Microsoft\VisualStudio\9.0Exp\Configuration
- User settings: HKCU\Software\Microsoft\VisualStudio\9.0Exp\UserSettings
VS10
Main hive
- Root: HKLM\Software\Microsoft\VisualStudio\10.0
- Root cache: HKCU\Software\Microsoft\VisualStudio\10.0_Config
- User settings: HKCU\Software\Microsoft\VisualStudio\10.0
Exp hive
- Root: HKCU\Software\Microsoft\VisualStudio\10.0Exp_Config
- User settings: HKCU\Software\Microsoft\VisualStudio\10.0Exp
The registry root cache
This is the real hive that is being used by Visual Studio and its being created / updated at Visual Studio startup time.
Creation / Reconstruction
If the hive doesn’t exist it is created using the root (HKLM\Software\Microsoft\VisualStudio\10.0) base information. This means that we can safely delete the hive and it will be created again on next Visual Studio launch.
If it exists but it differs from the root (HKLM\Software\Microsoft\VisualStudio\10.0) is its reconstructed.
Update
If we recall the No more Devenv /Setup post Visual Studio monitors the following folders:
- %LocalAppData%\Microsoft\VisualStudio\10.0\Extensions
- %VS10_Install_Dir%\Common7\IDE\Extensions
- %VS10_Install_Dir%\Common7\IDE\CommonExtensions
During VS startup if any changes are detected in those folders (new / delete / update) the pkgdef are merged again into the hive to reflect the latest definition.
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
Let’s say that we want to deploy our extension as a trusted extension.
For that VSIXInstaller tool supports the /admin switch.
When we pass the /admin argument to the tool the VSIX is deployed under %VS10_Install_Dir%\Common7\IDE\Extensions
Notice that you will need to execute the VSIXInstaller tool with administration privileges.
Pablo
***Disclaimer: This information applies to Visual Studio 2010 Beta 1 only.***
If we want to hide an extension in the extension manager dialog we need to add the “SystemComponent” node in our VSIX manifest.
For example let’s take a look at the Visual Studio editor VSIX manifest:
<VSIX xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010">
<Identifier ID="Microsoft.VisualStudio.Editor">
<Name>Microsoft Visual Studio Editor</Name>
<Author>Microsoft Corporation</Author>
<Version>10.0</Version>
<Description>Microsoft Visual Studio Editor</Description>
…
<SystemComponent>true</SystemComponent>
…
</Identifier>
<References/>
<Content>
…
<MEFComponent>Microsoft.VisualStudio.Editor.dll</MEFComponent>
…
</Content>
</VSIX>
The extension manager dialog then filters extensions with the “SystemComponent” node and the result is that they are hidden to the user. As you can see in the screenshot below the core Visual Studio Editor extension is not shown.
Pablo