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

Visual studio 2013 如何使VSIX安装程序自动注册程序集,visual-studio-2013,vsix,regasm,Visual Studio 2013,Vsix,Regasm,我开发了一个自定义代码生成器,并通过VSIX进行部署,问题是在安装VSIX后,我应该通过regasm.exe注册程序集,但我见过一些项目,例如具有自动注册的自定义代码生成的DSLTool,任何人都知道如何在我的VSIX项目中自动注册?您应该能够执行以下操作: 0删除旧的(不良做法)COM代码 编辑项目生成设置,使其不选中“注册COM互操作” 编辑您的AssemblyInfo.cs并将ComVisible设置为false: [assembly: ComVisible(false)] 假设您的生

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

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

0删除旧的(不良做法)COM代码
  • 编辑项目生成设置,使其不选中“注册COM互操作”
  • 编辑您的AssemblyInfo.cs并将
    ComVisible
    设置为
    false

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

    [ComVisible(true)]
    
  • 1.编辑VSIX项目以启用pkgdef文件的生成。
  • 在解决方案资源管理器中右键单击项目,然后选择卸载项目
  • 右键单击卸载的项目并选择编辑MyProject.csproj,其中MyProject是项目的名称
  • 找到XML元素

  • 如果元素存在,请确保其值设置为
    true
  • 否则,将以下内容添加到项目文件中第一个
    元素的末尾,该元素没有
    条件
    属性(这几乎总是文件中的第一个
    属性组

    如果扩展不提供任何其他内容元素,则整个
    元素现在将是:

    <Content>
      <VsPackage>|%CurrentProject%|</VsPackage>
    </Content>
    
  • 4.将代码生成器与语言服务关联
  • 打开项目的AssemblyInfo.cs
  • 假设您的自定义代码生成器类名为
    MyCodeGenerator
    ,并且您希望向C#language服务注册代码生成器,请将以下属性添加到程序集信息文件中

    [assembly: ProvideAssemblyObject(typeof(MyCodeGenerator))]
    
    [assembly: ProvideGenerator(
        typeof(MyCodeGenerator),
        VSConstants.UICONTEXT.CSharpProject_string,
        Description = "Description of the generator",
        GeneratesDesignTimeSource = true)]
    
  • 附录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);
        }
    }
    
    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);
        }
    }
    
    附录B:ProvideAssemblyObjectAttribute.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);
        }
    }
    
    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);
        }
    }
    

    我在“项目属性”窗口的“构建”选项卡中找到了“注册COM互操作”选项,似乎这就是解决方案,但在设置之后,我得到了这个错误错误3未为COM互操作注册程序集“Microsoft.VisualStudio.Shell.Interop,版本=7.1.40304.0,区域性=中性,PublicKeyToken=b03f5f7f11d50a3a”。请使用regasm.exe/tlb.dsl包注册“我编辑了我的答案,以确保删除此生成设置以及其他不再需要的COM相关元素。非常感谢,它可以工作,但我使用了内置的ProvideGeneratorAttribute,而不是VS2019上内置的ProvideGeneratorAttribute和ProvideGeneratorAttribute-“在此系统上找不到自定义工具XYZ”;对于ComVisible的使用方式,它不起作用。我想它确实需要regasm注册。。。