如何使VSIX安装程序自动注册程序集

时间:2014-03-25 12:39:00

标签: visual-studio-2013 vsix regasm

我已经开发了一个自定义代码生成器并通过VSIX进行部署,问题是我应该在安装VSIX后通过regasm.exe注册程序集,但我看到一些项目,如DSLTool,自定义代码生成,自动注册,任何body知道如何在我的VSIX项目中自动注册?

1 个答案:

答案 0 :(得分:6)

您应该能够执行以下操作:

0。删除旧的(不良做法)COM代码

  1. 将您的项目构建设置编辑为而不是有"注册COM互操作"检查。
  2. 修改 AssemblyInfo.cs 并将ComVisible设置为false

    [assembly: ComVisible(false)]
    
  3. 假设您的生成器名为MyCodeGenerator,请打开MyCodeGenerator的定义并添加属性:

    [ComVisible(true)]
    
  4. 1。编辑VSIX项目以生成pkgdef文件。

    1. 解决方案资源管理器中右键单击您的项目,然后选择卸载项目
    2. 右键单击已卸载的项目,然后选择编辑 MyProject .csproj ,其中 MyProject 是项目的名称。
    3. 找到XML元素<GeneratePkgDefFile>

      1. 如果元素存在,请确保其值设置为true
      2. 否则,将以下内容添加到项目文件中第一个<PropertyGroup>元素的末尾,具有Condition属性(这几乎总是如此)文件中的第一个PropertyGroup

        <GeneratePkgDefFile>true</GeneratePkgDefFile>
        
    4. 重复步骤3,将<CopyBuildOutputToOutputDirectory>设为true

    5. 保存并关闭 .csproj 文件。
    6. 右键单击解决方案资源管理器中的已卸载项目,然后选择重新加载项目
    7. 打开项目的 source.extension.vsixmanifest 文件,找到<Content>元素。将以下元素添加为子元素:

      <VsPackage>|%CurrentProject%|</VsPackage>
      

      如果您的扩展程序未提供任何其他内容元素,则整个<Content>元素现在将是:

      <Content>
        <VsPackage>|%CurrentProject%|</VsPackage>
      </Content>
      
    8. 2。定义所需的属性类型

      本答案的最后部分是 ProvideGeneratorAttribute.cs ProvideAssemblyObjectAttribute.cs 的部分。将这些文件添加到您的项目中。

      3。注册代码生成器类

      1. 打开您的项目 AssemblyInfo.cs
      2. 假设您的自定义代码生成器类名为MyCodeGenerator,请将以下属性添加到程序集信息文件中。

        [assembly: ProvideAssemblyObject(typeof(MyCodeGenerator))]
        
      3. 4。将代码生成器与语言服务

        相关联
        1. 打开您的项目 AssemblyInfo.cs
        2. 假设您的自定义代码生成器类名为MyCodeGenerator,并且您希望使用C#语言服务注册代码生成器,请将以下属性添加到程序集信息文件中。

          [assembly: ProvideGenerator(
              typeof(MyCodeGenerator),
              VSConstants.UICONTEXT.CSharpProject_string,
              Description = "Description of the generator",
              GeneratesDesignTimeSource = true)]
          
        3. 附录A:ProvideGeneratorAttribute.cs

          免责声明:此代码完全未经过测试。

          using System;
          using Microsoft.VisualStudio.Shell;
          
          [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
          public sealed class ProvideGeneratorAttribute : RegistrationAttribute
          {
              private readonly Type _generatorType;
              private readonly Guid _languageServiceGuid;
              private string _name;
              private string _description;
              private bool _generatesDesignTimeSource;
          
              public ProvideGeneratorAttribute(Type generatorType, string languageServiceGuid)
              {
                  if (generatorType == null)
                      throw new ArgumentNullException("generatorType");
                  if (languageServiceGuid == null)
                      throw new ArgumentNullException("languageServiceGuid");
                  if (string.IsNullOrEmpty(languageServiceGuid))
                      throw new ArgumentException("languageServiceGuid cannot be empty");
          
                  _generatorType = generatorType;
                  _languageServiceGuid = new Guid(languageServiceGuid);
                  _name = _generatorType.Name;
              }
          
              public Type GeneratorType
              {
                  get
                  {
                      return _generatorType;
                  }
              }
          
              public Guid LanguageServiceGuid
              {
                  get
                  {
                      return _languageServiceGuid;
                  }
              }
          
              public string Name
              {
                  get
                  {
                      return _name;
                  }
          
                  set
                  {
                      if (value == null)
                          throw new ArgumentNullException("value");
                      if (string.IsNullOrEmpty(value))
                          throw new ArgumentException("value cannot be empty");
          
                      _name = value;
                  }
              }
          
              public string Description
              {
                  get
                  {
                      return _description;
                  }
          
                  set
                  {
                      _description = value;
                  }
              }
          
              public bool GeneratesDesignTimeSource
              {
                  get
                  {
                      return _generatesDesignTimeSource;
                  }
          
                  set
                  {
                      _generatesDesignTimeSource = value;
                  }
              }
          
              private string RegistrationKey
              {
                  get
                  {
                      return string.Format(@"Generators\{0}\{1}", LanguageServiceGuid.ToString("B"), Name);
                  }
              }
          
              public override void Register(RegistrationContext context)
              {
                  using (Key key = context.CreateKey(RegistrationKey))
                  {
                      if (!string.IsNullOrEmpty(Description))
                          key.SetValue(string.Empty, Description);
                      key.SetValue("CLSID", GeneratorType.GUID.ToString("B"));
                      key.SetValue("GeneratesDesignTimeSource", GeneratesDesignTimeSource ? 1 : 0);
                  }
              }
          
              public override void Unregister(RegistrationContext context)
              {
                  context.RemoveKey(RegistrationKey);
              }
          }
          

          附录B:ProvideAssemblyObjectAttribute.cs

          免责声明:此代码完全未经过测试。

          using System;
          using Microsoft.VisualStudio.Shell;
          
          [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
          public sealed class ProvideAssemblyObjectAttribute : RegistrationAttribute
          {
              private readonly Type _objectType;
              private RegistrationMethod _registrationMethod;
          
              public ProvideAssemblyObjectAttribute(Type objectType)
              {
                  if (objectType == null)
                      throw new ArgumentNullException("objectType");
          
                  _objectType = objectType;
              }
          
              public Type ObjectType
              {
                  get
                  {
                      return _objectType;
                  }
              }
          
              public RegistrationMethod RegistrationMethod
              {
                  get
                  {
                      return _registrationMethod;
                  }
          
                  set
                  {
                      _registrationMethod = value;
                  }
              }
          
              private string ClsidRegKey
              {
                  get
                  {
                      return string.Format(@"CLSID\{0}", ObjectType.GUID.ToString("B"));
                  }
              }
          
              public override void Register(RegistrationContext context)
              {
                  using (Key key = context.CreateKey(ClsidRegKey))
                  {
                      key.SetValue(string.Empty, ObjectType.FullName);
                      key.SetValue("InprocServer32", context.InprocServerPath);
                      key.SetValue("Class", ObjectType.FullName);
                      if (context.RegistrationMethod != RegistrationMethod.Default)
                          _registrationMethod = context.RegistrationMethod;
          
                      switch (RegistrationMethod)
                      {
                      case Microsoft.VisualStudio.Shell.RegistrationMethod.Default:
                      case Microsoft.VisualStudio.Shell.RegistrationMethod.Assembly:
                          key.SetValue("Assembly", ObjectType.Assembly.FullName);
                          break;
          
                      case Microsoft.VisualStudio.Shell.RegistrationMethod.CodeBase:
                          key.SetValue("CodeBase", context.CodeBase);
                          break;
          
                      default:
                          throw new InvalidOperationException();
                      }
          
                      key.SetValue("ThreadingModel", "Both");
                  }
              }
          
              public override void Unregister(RegistrationContext context)
              {
                  context.RemoveKey(ClsidRegKey);
              }
          }