我已经开发了一个自定义代码生成器并通过VSIX进行部署,问题是我应该在安装VSIX后通过regasm.exe注册程序集,但我看到一些项目,如DSLTool,自定义代码生成,自动注册,任何body知道如何在我的VSIX项目中自动注册?
答案 0 :(得分:6)
您应该能够执行以下操作:
修改 AssemblyInfo.cs 并将ComVisible
设置为false
:
[assembly: ComVisible(false)]
假设您的生成器名为MyCodeGenerator
,请打开MyCodeGenerator
的定义并添加属性:
[ComVisible(true)]
找到XML元素<GeneratePkgDefFile>
。
true
。否则,将以下内容添加到项目文件中第一个<PropertyGroup>
元素的末尾,不具有Condition
属性(这几乎总是如此)文件中的第一个PropertyGroup
。
<GeneratePkgDefFile>true</GeneratePkgDefFile>
重复步骤3,将<CopyBuildOutputToOutputDirectory>
设为true
。
打开项目的 source.extension.vsixmanifest 文件,找到<Content>
元素。将以下元素添加为子元素:
<VsPackage>|%CurrentProject%|</VsPackage>
如果您的扩展程序未提供任何其他内容元素,则整个<Content>
元素现在将是:
<Content>
<VsPackage>|%CurrentProject%|</VsPackage>
</Content>
本答案的最后部分是 ProvideGeneratorAttribute.cs 和 ProvideAssemblyObjectAttribute.cs 的部分。将这些文件添加到您的项目中。
假设您的自定义代码生成器类名为MyCodeGenerator
,请将以下属性添加到程序集信息文件中。
[assembly: ProvideAssemblyObject(typeof(MyCodeGenerator))]
假设您的自定义代码生成器类名为MyCodeGenerator
,并且您希望使用C#语言服务注册代码生成器,请将以下属性添加到程序集信息文件中。
[assembly: ProvideGenerator(
typeof(MyCodeGenerator),
VSConstants.UICONTEXT.CSharpProject_string,
Description = "Description of the generator",
GeneratesDesignTimeSource = true)]
免责声明:此代码完全未经过测试。
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);
}
}