I am writing a VS 2012 plug-in, which contains a Package
as well as an IWpfTextViewCreationListener
MEF
extension class.
It is installed using a WiX project created MSI, placing all of the files in C:\Program Files\...[Application]
; which creates the Packages registry entry to point to the DLL containing the Package implementation.
When debugging the plug-in in an experimental Visual Studio instance, everything runs correctly.
When running the MSI installer, the Package code runs fine, but the MEF class is not instantiated.
Note: if I install the package using the VSIX (which I do not use for MSI install) everything also works fine.
The MEF class (in same Assembly as Package):
[Export(typeof (IWpfTextViewCreationListener))]
[ContentType("text")]
[TextViewRole(PredefinedTextViewRoles.Document)]
internal sealed class HighlightAdornerFactory : IWpfTextViewCreationListener
{
[Import]
public IClassificationTypeRegistryService ClassificationRegistry = null;
[Import]
public IClassificationFormatMapService FormatMapService = null;
[Export(typeof (AdornmentLayerDefinition))]
[Name(HighlightAdornment.Name)]
[Order(After = PredefinedAdornmentLayers.Selection, Before = PredefinedAdornmentLayers.Text)]
public AdornmentLayerDefinition editorAdornmentLayer = null;
public void TextViewCreated(IWpfTextView textView)
{ /** ... **/ }
}
I used VisualMEFX
to examine the DLL that this is packaged in. It reports that no exports match IClassificationTypeRegistryService
. This doesn't explain why it works when installed with VSIX, or debugged via the IDE. But it might be useful to know in troubleshooting the problem.
[Export] MySolution.HighlightAdornerFactory (ContractName="Microsoft.VisualStudio.Text.Editor.IWpfTextViewCreationListener")
[Export] MySolution.Adornment.HighlightAdornerFactory.editorAdornmentLayer (ContractName="Microsoft.VisualStudio.Text.Editor.AdornmentLayerDefinition")
[Import] MySolution.Adornment.HighlightAdornerFactory.ClassificationRegistry (ContractName="Microsoft.VisualStudio.Text.Classification.IClassificationTypeRegistryService")
[Exception] System.ComponentModel.Composition.ImportCardinalityMismatchException: No exports were found that match the constraint:
ContractName Microsoft.VisualStudio.Text.Classification.IClassificationTypeRegistryService
RequiredTypeIdentity Microsoft.VisualStudio.Text.Classification.IClassificationTypeRegistryService
at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(ImportDefinition definition, AtomicComposition atomicComposition)
at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(ImportDefinition definition)
at Microsoft.ComponentModel.Composition.Diagnostics.CompositionInfo.AnalyzeImportDefinition(ExportProvider host, IEnumerable`1 availableParts, ImportDefinition id) in C:\Temp\MEF_Beta_2\Samples\CompositionDiagnostics\Microsoft.ComponentModel.Composition.Diagnostics\CompositionInfo.cs:line 157
[Import] MySolution.HighlightAdornerFactory.FormatMapService (ContractName="Microsoft.VisualStudio.Text.Classification.IClassificationFormatMapService")
[Exception] System.ComponentModel.Composition.ImportCardinalityMismatchException: No exports were found that match the constraint:
ContractName Microsoft.VisualStudio.Text.Classification.IClassificationFormatMapService
RequiredTypeIdentity Microsoft.VisualStudio.Text.Classification.IClassificationFormatMapService
at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(ImportDefinition definition, AtomicComposition atomicComposition)
at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(ImportDefinition definition)
at Microsoft.ComponentModel.Composition.Diagnostics.CompositionInfo.AnalyzeImportDefinition(ExportProvider host, IEnumerable`1 availableParts, ImportDefinition id) in C:\Temp\MEF_Beta_2\Samples\CompositionDiagnostics\Microsoft.ComponentModel.Composition.Diagnostics\CompositionInfo.cs:line 157
I have tried adding all the referenced libraries from my assembly into the MSI, but this did not help. I am not seeing any exceptions being thrown, the IWpfTextViewCreationListener
class simply does not get loaded.
The behavior you are seeing is by design; assemblies are included in the MEF composition only if they're listed in a .vsixmanifest somewhere. When you added the Package registry keys through your MSI, this will not add your assemblies to the MEF composition. When were you were testing in the experimental hive or installing the extension directily, you were including your assembly into the MEF composition as you expected.
You have a few ways to fix this, in my order of recommendation:
Don't use an MSI. I strongly encourage this if possible. VSIXes are quite powerful, and offer many advantages for the user: they are easier to install and uninstall, and they integrate with the extension manager and Visual Studio gallery. Unless you can prove that a VSIX is unacceptable for your scenario, please use them.
Use WiX 3.6, which has a VsixPackage element which will install your VSIX for you. The documentation is available here.
Have your MSI install the contents of your VSIX into [Program Files]\Microsoft Visual Studio 11.0\Common7\IDE\Extensions\[Your Product Name] and then run devenv /setup as a part of a custom action. This is very tricky to do and requires a bunch of manual WiX authoring. Option #2 exists for a reason -- the WiX folks actually know what they're doing. ;-)