10

我在 Visual Studio 2012 中创建了一个新的 VSIX 扩展项目,并编写了一个 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,所以我知道它们被复制了。
  • 它们的时间戳对应于我上次构建项目的时间,所以我知道它们是最新的。
  • 项目属性 > 调试 > 启动外部程序:已自动设置为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没有出现在调试 Visual Studio 的“模块”选项卡(所有加载的 DLL 列表)上,而一些(不是全部)其他扩展确实出现了。
  • 它不会在我的笔记本电脑和台式电脑上加载到 Visual Studio 2012 或 2010 中。

我试过的:

  • 根据这个建议.csproj文件中设置<IncludeAssemblyInVSIXContainer>为,但没有任何区别。true
  • 无法将该行添加<MefComponent>|%CurrentProject%|</MefComponent>source.extension.vsixmanifest文件,因为它使用的格式 (2.0) 与以前版本的 Visual Studio (1.0) 的 VSIX 项目不同。
  • 这个建议(在我的.csproj中设置IncludeAssemblyInVSIXContainer和朋友)但它没有任何区别。而且我的断点仍然显示警告并且没有被击中。true
  • 根据此建议,使用开始菜单中的重置 Visual Studio 2012 实验实例快捷方式重置 VS 实验实例。这并没有什么不同。

我怎样才能至少确保我的 VSIX MEF 扩展已加载并正常工作?如果可能的话,我怎样才能通过断点工作并调试它?

4

3 回答 3

7

编辑:问题是您不正确地将您的导出ContentTypeDefinitionClassificationTypeDefinition. 您应该改用以下内容:

[Export] // <-- don't specify the type here
[Name(ContentType)]
[BaseDefinition("code")]
internal static ContentTypeDefinition MyLangSyntaxContentTypeDefinition = null;

这是我现在的两个猜测:

  1. 尝试从您的 vsixmanifest 中删除以下行。我假设您的项目中没有扩展的类Package,在这种情况下,Visual Studio 可能会由于以下资产行而拒绝加载您的包(您的扩展实际上并未提供此资产)。

    <Asset Type="Microsoft.VisualStudio.VsPackage" d:Source="Project" d:ProjectName="%CurrentProject%" Path="|%CurrentProject%;PkgdefProjectOutputGroup|" />
    
  2. 如果失败,请尝试将当前的 source.extension.vsixmanifest 替换为写入旧架构(1.0 版)的文件。我知道这种形式在 Visual Studio 2012 中仍然有效,因为我处理的所有 ~20 个扩展(超过 10 个公共版本)都使用旧模式。

于 2013-05-10T15:22:11.893 回答
4

280Z28解决了问题!为了完整起见,这是完整的经过试验和测试的代码,它将创建一个超级简单的 VSIX Visual Studio MEF 扩展,将.mylang文件中的所有文本着色为蓝色(或任何当前关键字颜色)。

如何创建简单的着色 MEF VSIX 扩展

  1. 确保已安装 Visual Studio SDK。(VS2010 SP1 SDKVS2012 SDK
  2. 创建一个新的 VSIX 项目
    (从InstalledTemplatesVisual C#Extensibility下的模板。)
  3. 在 VSIX 清单编辑器的作者字段中输入内容,然后保存并关闭它。
  4. 添加对以下库的引用,
    VS2010 版本 10.0.0.0,或 VS2012 版本 11.0.0.0:

    • 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
  5. 添加对以下库的引用:

    • System.ComponentModel.Composition.dll版本 4.0.0.0
  6. 创建并添加一个新的代码文件,然后将下面的代码MyLang.cs复制并粘贴到其中。

  7. 编辑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/>,删除它。)

  8. 仅适用于 Visual Studio 2010

    • 卸载 VSIX 项目(右键单击项目 →卸载项目)。

    • 编辑.csproj项目文件(右键单击项目 →编辑 MyProject.csproj)。

    • 将 处的值更改<IncludeAssemblyInVSIXContainer>true

    • 保存并关闭文件。

    • 重新加载 VSIX 项目(右键单击项目 →重新加载项目)。

  9. 现在构建并运行它。加载.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)));
        }
    }
}
于 2013-05-11T00:47:35.177 回答
0

<IncludeAssemblyInVSIXContainer>根据此建议,在 .csproj 文件中设置为 true。

我有完全相同的问题,这解决了它。进行全面重建。

于 2013-05-07T19:08:32.300 回答