Расширение VSIX для VS2012 не работает при отладке
Я создал новый проект расширения VSIX в Visual Studio 2012 и написал классификатор MEF (как тест), который должен просто выделить весь текст в файле .mylang
. Вот соответствующие части моего кода .NET 4.5:
internal static class MyLangLanguage
{
public const string ContentType = "mylang";
public const string FileExtension = ".mylang";
[Export(typeof(ClassificationTypeDefinition))]
[Name(ContentType)]
[BaseDefinition("code")]
internal static ContentTypeDefinition MyLangSyntaxContentTypeDefinition = null;
[Export]
[FileExtension(FileExtension)]
[ContentType(ContentType)]
internal static FileExtensionToContentTypeDefinition MyLangSyntaxFileExtensionDefinition = null;
}
[Export(typeof(IClassifierProvider))]
[ContentType(MyLangLanguage.ContentType)]
[Name("MyLangSyntaxProvider")]
internal sealed class MyLangSyntaxProvider : IClassifierProvider
{
[Import]
internal IClassificationTypeRegistryService ClassificationRegistry = null;
public IClassifier GetClassifier(ITextBuffer buffer)
{
return buffer.Properties.GetOrCreateSingletonProperty(() => new MyLangSyntax(ClassificationRegistry, buffer));
}
}
internal sealed class MyLangSyntax : IClassifier { }
Вот полный код.
Это соответствующие части из моего файла source.extension.vsixmanifest
. Основываясь на предложениях и подобных файлах, которые я нашел через Интернет, я добавил зависимость от MPF и двух активов.
<?xml version="1.0" encoding="utf-8"?>
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011" xmlns:d="http://schemas.microsoft.com/developer/vsx-schema-design/2011">
<!-- ... -->
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" d:Source="Manual" Version="4.5" />
<Dependency d:Source="Installed" Id="Microsoft.VisualStudio.MPF.11.0" DisplayName="Visual Studio MPF 11.0" Version="[11.0,12.0)" />
</Dependencies>
<Assets>
<Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%|" />
</Assets>
</PackageManifest>
Я также пробовал манифест версии 1.0:
<?xml version="1.0" encoding="utf-8"?>
<Vsix Version="1.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010">
<!-- ... -->
<References />
<Content>
<MefComponent>|%CurrentProject%|</MefComponent>
</Content>
</Vsix>
Когда я запускаю его, он запускает экспериментальный экземпляр Visual Studio 2012, а окно "Расширения и обновления" показывает, что мое расширение активно. Однако, когда я загружаю или создаю файл .mylang, он ничего не делает. Любые исключения, которые я бросаю (как тест) из моего расширения, никогда не бросаются. Точки останова никогда не попадают и получают восклицательный знак со следующим предупреждением:
В настоящий момент точка останова не будет удалена. Для этого документа не были загружены никакие символы.
Мне кажется, что мое расширение никогда не загружается вообще. Моя проблема аналогична этой проблеме и этой проблеме, но я использую Visual Studio 2012, которая использует новый формат манифеста VSIX.
Что я знаю:
- Я могу найти свой файл DLL и VSIX в папке
%localappdata%\Microsoft\VisualStudio\11.0Exp\Extensions\MyLang\VSIXProject1\1.0
, поэтому я знаю, что они скопированы.
- Их временная метка соответствует тому, когда я последний раз строил проект, поэтому я знаю, что они актуальны.
- Свойства проектa > Отладкa > Запустить внешнюю программу: уже автоматически установлено значение
C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe
, а аргументы командной строки автоматически установлены на /rootsuffix Exp
.
- Журнал Visual Studio (созданный с помощью опции
/log
) имеет две записи, связанные с моим расширением: Successfully loaded extension...
и Extension is enabled...
.
- Моя DLL не появляется на вкладке "Модули" (список всех загруженных DLL) отладки Visual Studio, в то время как некоторые (не все) другие расширения появляются.
- Он не загружается в Visual Studio 2012 или 2010 как на моем ноутбуке, так и на моем настольном ПК.
Что я пробовал:
- Установите
<IncludeAssemblyInVSIXContainer>
в true
в файле .csproj, за это предложение, но это не имеет никакого значения.
- Я не могу добавить строку
<MefComponent>|%CurrentProject%|</MefComponent>
в файл source.extension.vsixmanifest, поскольку он использует другой формат (2.0), чем проекты VSIX для предыдущих версий Visual Studio (1.0).
- Это предложение (настройка
IncludeAssemblyInVSIXContainer
и друзей в моем .csproj на true
), но это не имеет значения. И мои контрольные точки все еще показывают предупреждение и не попадают.
- Reset Экспериментальный экземпляр VS с использованием Reset ярлыка экспериментальной инстанции Visual Studio 2012 в меню "Пуск" в соответствии с этим предложением. Это не имело значения.
Как я могу, по крайней мере, убедиться, что мое расширение VSIX MEF загружено и работает? И если это возможно, как я могу сделать работу контрольной точки и отладить ее?
Ответы
Ответ 1
Изменить: Проблема заключается в том, что вы неправильно экспортировали ContentTypeDefinition
как ClassificationTypeDefinition
. Вместо этого вы должны использовать следующее:
[Export] // <-- don't specify the type here
[Name(ContentType)]
[BaseDefinition("code")]
internal static ContentTypeDefinition MyLangSyntaxContentTypeDefinition = null;
Вот мои две догадки прямо сейчас:
-
Попробуйте удалить следующую строку из vsixmanifest. Я предполагаю, что у вас нет класса в вашем проекте, который расширяет Package
, и в этом случае Visual Studio может отказаться от загрузки вашего пакета из-за следующей строки Asset ( ваше расширение фактически не предоставляет этот актив).
<Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
-
Если это не удается, попробуйте заменить текущий источник source.extension.vsixmanifest на один, записанный на старую схему (версия 1.0). Я знаю, что эта форма все еще работает в Visual Studio 2012, потому что все ~ 20 расширений, над которыми я работаю (s > 10 общедоступными выпусками), используют старую схему.
Ответ 2
280Z28 решил проблему! Для полноты, это полный проверенный и проверенный код, который создаст сверхпростую VSIX Visual Studio MEF, которая окрасит весь текст в файл .mylang
синий (или любой цвет текущего ключевого слова).
Как создать простую раскраску расширения MEF VSIX
- Убедитесь, что установлен пакет Visual Studio SDK. (VS2010 SP1 SDK, VS2012 SDK)
- Создайте новый проект VSIX
(Из шаблона в разделе Installed → Templates → Visual С# → Расширяемость.)
- Введите что-то в поле "Автор" в редакторе манифеста VSIX, затем сохраните и закройте его.
-
Добавьте ссылки на следующие библиотеки:
версию 10.0.0.0 для VS2010 или 11.0.0.0 для VS2012:
-
Microsoft.VisualStudio.CoreUtility.dll
-
Microsoft.VisualStudio.Language.StandardClassification.dll
-
Microsoft.VisualStudio.Text.Data.dll
-
Microsoft.VisualStudio.Text.Logic.dll
-
Microsoft.VisualStudio.Text.UI.dll
-
Microsoft.VisualStudio.Text.UI.Wpf.dll
-
Добавьте ссылку на следующую библиотеку:
-
System.ComponentModel.Composition.dll
версия 4.0.0.0
-
Создайте и добавьте новый файл кода MyLang.cs
и скопируйте и вставьте код ниже в него.
-
Измените source.extension.vsixmanifest
как XML.
-
Для Visual Studio 2010 добавьте следующий XML непосредственно перед закрывающим тегом </Vsix>
и сохраните:
<Content>
<MefComponent>|%CurrentProject%|</MefComponent>
</Content>
(Если уже существует пустой <Content/>
, удалите его.)
-
Для Visual Stuio 2012 добавьте следующий XML непосредственно перед закрывающим тегом </PackageManifest>
и сохраните:
<Assets>
<Asset Type="Microsoft.VisualStudio.MefComponent" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%|" />
</Assets>
(Если уже существует пустой <Assets/>
, удалите его.)
-
Только для Visual Studio 2010:
-
Выгрузите проект VSIX (щелкните правой кнопкой мыши проект project → Unload).
-
Отредактируйте файл проекта .csproj
(щелкните правой кнопкой мыши проект → Edit MyProject.csproj).
-
Измените значение с <IncludeAssemblyInVSIXContainer>
на true
.
-
Сохраните и закройте файл.
-
Перезагрузите проект VSIX (щелкните правой кнопкой проект project → Reload).
-
Теперь создайте и запустите его. Когда вы загружаете файл .mylang
, весь текст должен быть окрашен в синий цвет (или любой цвет ключевого слова по умолчанию).
MyLang.cs
using Microsoft.VisualStudio.Language.StandardClassification;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
namespace VSIXProject1
{
internal static class MyLangLanguage
{
public const string ContentType = "mylang";
public const string FileExtension = ".mylang";
[Export]
[Name(ContentType)]
[BaseDefinition("code")]
internal static ContentTypeDefinition MyLangSyntaxContentTypeDefinition = null;
[Export]
[FileExtension(FileExtension)]
[ContentType(ContentType)]
internal static FileExtensionToContentTypeDefinition MyLangSyntaxFileExtensionDefinition = null;
}
[Export(typeof(IClassifierProvider))]
[ContentType(MyLangLanguage.ContentType)]
[Name("MyLangSyntaxProvider")]
internal sealed class MyLangSyntaxProvider : IClassifierProvider
{
[Import]
internal IClassificationTypeRegistryService ClassificationRegistry = null;
public IClassifier GetClassifier(ITextBuffer buffer)
{
return buffer.Properties.GetOrCreateSingletonProperty(() => new MyLangSyntax(ClassificationRegistry, buffer));
}
}
internal sealed class MyLangSyntax : IClassifier
{
private ITextBuffer buffer;
private IClassificationType identifierType;
private IClassificationType keywordType;
public event EventHandler<ClassificationChangedEventArgs> ClassificationChanged;
internal MyLangSyntax(IClassificationTypeRegistryService registry, ITextBuffer buffer)
{
this.identifierType = registry.GetClassificationType(PredefinedClassificationTypeNames.Identifier);
this.keywordType = registry.GetClassificationType(PredefinedClassificationTypeNames.Keyword);
this.buffer = buffer;
this.buffer.Changed += OnBufferChanged;
}
public IList<ClassificationSpan> GetClassificationSpans(SnapshotSpan snapshotSpan)
{
var classifications = new List<ClassificationSpan>();
string text = snapshotSpan.GetText();
var span = new SnapshotSpan(snapshotSpan.Snapshot, snapshotSpan.Start.Position, text.Length);
classifications.Add(new ClassificationSpan(span, keywordType));
return classifications;
}
private void OnBufferChanged(object sender, TextContentChangedEventArgs e)
{
foreach (var change in e.Changes)
ClassificationChanged(this, new ClassificationChangedEventArgs(new SnapshotSpan(e.After, change.NewSpan)));
}
}
}
Ответ 3
Установите <IncludeAssemblyInVSIXContainer>
значение true в файле .csproj, за это предложение.
У меня была точно такая же проблема, и это решило ее. Сделайте полную перестройку.