6

Visual Studio 2008 SP1 用の独自のカスタム ツールがあります。これは 5 つのアセンブリで構成されています。私の他のプロジェクトで頻繁に使用されるコードを含む 3 つのアセンブリ、VS2008 SDK 上のアセンブリ ラッパーが 1 つ、ツールを含むアセンブリが 1 つです。

コマンド ライン「C:\Program Files (x86)\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe」と引数「/ranu / rootsuffix Exp」はすべて完全に機能します。

その後、実験的なハイブではなく、作業中のVSコピーに展開しようとしています。gacutil /i Asm1.dllすべてのアセンブリRegAsm Asm1.dllに対して、カスタムツールを使用したアセンブリに対してのみ実行しています。どちらのユーティリティもエラーを出力せず、すべてが計画どおりに機能し、レジストリ キーも表示されます。しかし、PC を再起動してもツールが機能しません (「このシステムでカスタム ツール 'TransportGeneratorTool' が見つかりません」というエラーが発生しました)。私は何を間違えましたか?

ラッパーは次のようになります。

[ComVisible(true)]
public abstract class CustomToolBase : IVsSingleFileGenerator, IObjectWithSite
{
    #region IVsSingleFileGenerator Members
    int IVsSingleFileGenerator.DefaultExtension(out string pbstrDefaultExtension)
    {
        pbstrDefaultExtension = ".cs";
        return 0;
    }

    int IVsSingleFileGenerator.Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress)
    {
        GenerationEventArgs gea = new GenerationEventArgs(
            bstrInputFileContents,
            wszInputFilePath,
            wszDefaultNamespace,
            new ServiceProvider(Site as Microsoft.VisualStudio.OLE.Interop.IServiceProvider)
                .GetService(typeof(ProjectItem)) as ProjectItem,
            new GenerationProgressFacade(pGenerateProgress)
                );

        if (OnGenerateCode != null)
        {
            OnGenerateCode(this, gea);
        }

        byte[] bytes = gea.GetOutputCodeBytes();

        int outputLength = bytes.Length;
        rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(outputLength);
        Marshal.Copy(bytes, 0, rgbOutputFileContents[0], outputLength);
        pcbOutput = (uint)outputLength;
        return VSConstants.S_OK;
    }
    #endregion

    #region IObjectWithSite Members
    void IObjectWithSite.GetSite(ref Guid riid, out IntPtr ppvSite)
    {
        IntPtr pUnk = Marshal.GetIUnknownForObject(Site);
        IntPtr intPointer = IntPtr.Zero;
        Marshal.QueryInterface(pUnk, ref riid, out intPointer);
        ppvSite = intPointer;
    }

    void IObjectWithSite.SetSite(object pUnkSite)
    {
        Site = pUnkSite;
    }
    #endregion

    #region Public Members
    public object Site { get; private set; }

    public event EventHandler<GenerationEventArgs> OnGenerateCode;

    [ComRegisterFunction]
    public static void Register(Type type)
    {
        using (var parent = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\VisualStudio\9.0", true))
            foreach (CustomToolRegistrationAttribute ourData in type.GetCustomAttributes(typeof(CustomToolRegistrationAttribute), false))
                ourData.Register(x => parent.CreateSubKey(x), (x, name, value) => x.SetValue(name, value));
    }

    [ComUnregisterFunction]
    public static void Unregister(Type type)
    {
        using (var parent = Registry.LocalMachine.OpenSubKey(@"Software\Microsoft\VisualStudio\9.0", true))
            foreach (CustomToolRegistrationAttribute ourData in type.GetCustomAttributes(typeof(CustomToolRegistrationAttribute), false))
                ourData.Unregister(x => parent.DeleteSubKey(x, false));
    }

    #endregion
}

私のツールコード:

[ComVisible(true)]
[Guid("55A6C192-D29F-4e22-84DA-DBAF314ED5C3")]
[CustomToolRegistration(ToolName, typeof(TransportGeneratorTool))]
[ProvideObject(typeof(TransportGeneratorTool))]
public class TransportGeneratorTool : CustomToolBase
{
    private const string ToolName = "TransportGeneratorTool";

    public TransportGeneratorTool()
    {
        OnGenerateCode += GenerateCode;
    }

    private static void GenerateCode(object s, GenerationEventArgs e)
    {
        try
        {
            var serializer = new XmlSerializer(typeof (Parser.System));
            using (var reader = new StringReader(e.InputText))
            using (var writer = new StringWriter(e.OutputCode))
            {
                Generator.System = (Parser.System) serializer.Deserialize(reader);
                Generator.System.Namespace = e.Namespace;
                Generator.GenerateSource(writer);
            }
        }
        catch (Exception ex)
        {
            e.Progress.GenerateError(ex.ToString());
        }
    }
}

結果のレジストリ キー:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators\{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\Generators\{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}\TransportGeneratorTool]
@="TransportGeneratorTool"
"CLSID"="{55a6c192-d29f-4e22-84da-dbaf314ed5c3}"
"GeneratesDesignTimeSource"=dword:00000001
"GeneratesSharedDesignTimeSource"=dword:00000001

これが私のカスタム属性のコードです(ラッパーアセンブリにあります):

[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
public class CustomToolRegistrationAttribute : RegistrationAttribute
{
    public CustomToolRegistrationAttribute(string name, Type customToolType)
    {
        Name = name;
        CustomToolType = customToolType;
    }

    /// <summary>
    /// The type that implements the custom tool.  This starts 
    /// as MyCustomTool by default in the template.
    /// </summary>
    public Type CustomToolType { get; set; }

    public string Name { get; set; }

    #region RegistrationAttribute abstract member implementations
    public override void Register(RegistrationContext context)
    {
        Register(x => context.CreateKey(x), (x, key, value) => x.SetValue(key, value));
    }

    public void Register<T>(Func<string, T> keyCreator, Action<T, string, object> valueCreator)
    {
        var keyName = CreateKeyName(Name);
        var key = keyCreator(keyName);

        valueCreator(key, string.Empty, Name);
        valueCreator(key, "CLSID", CustomToolType.GUID.ToString("B"));
        valueCreator(key, "GeneratesDesignTimeSource", 1);
        valueCreator(key, "GeneratesSharedDesignTimeSource", 1);

        var disposable = key as IDisposable;
        if (disposable != null)
            disposable.Dispose();
    }

    private static string CreateKeyName(string name)
    {
        return string.Format(@"Generators\{0}\{1}", vsContextGuids.vsContextGuidVCSProject, name);
    }

    public override void Unregister(RegistrationContext context)
    {
        Unregister(context.RemoveKey);
    }

    public void Unregister(Action<string> keyRemover)
    {
        keyRemover(CreateKeyName(Name));
    }

    #endregion
}
4

2 に答える 2

6

私の解決策は、セットアップ プロジェクトを作成することです。パッケージの csproj ファイルに以下を追加して、pkgdef ファイルからレジストリ設定を取得します。

<Target Name="GeneratePackageRegistryFiles">
  <Exec Command="&quot;$(VSSDK90Install)VisualStudioIntegration\Tools\Bin\RegPkg.exe&quot; /root:Software\Microsoft\VisualStudio\9.0 /codebase &quot;$(TargetPath)&quot; /regfile:&quot;$(OutDir)$(TargetName).reg&quot;" />
</Target>
<PropertyGroup> 
  <BuildDependsOn>$(BuildDependsOn);GeneratePackageRegistryFiles;</BuildDependsOn>
</PropertyGroup>

出力ディレクトリをビルドすると、セットアップ プロジェクトにインポートできる .reg ファイルが見つかるはずです。

プロジェクトを変更できない場合は、明らかにコマンドラインから regpkg.exe を実行できます。

于 2010-04-09T10:14:26.747 に答える
4

これは前回、カスタム ツールを登録するのに苦労したときの結果です。この説明が十分に詳細であり、すべてを網羅していることを願っています。次の MSDN 記事が出発点として使用されました。http://msdn.microsoft.com/en-US/library/bb166527(v=vs.80).aspx残念ながら、単独では使用できません。本当に必要なことは次のとおりです。

  1. アセンブリが署名されていることを確認します。なんで?そうしないと、以下のステップ 6 で GAC に入れることができないからです。アセンブリに署名するには、次の手順に従います。

    1.1。プロジェクトのプロパティ画面に移動します。

    1.2. そこに移動したら、 [署名] タブに移動します。

    1.3。そこで、[ Sign the assembly ] チェックボックスをオンにします。

  2. アセンブリのバージョン番号を確認してください。この番号は、後でASSEMBLY_VERSIONパラメータを指定するために必要になります。この番号を取得するには、プロジェクトのPropertiesフォルダーにあるAssemblyInfo.csファイルを開き、 [assembly: AssemblyVersion(

  3. ジェネレーター クラスの GUID を確認してください。後でGENERATOR_GUIDパラメータを指定するために必要になります。この GUID を取得するには、ジェネレーター クラスでファイルを開き、このクラスを装飾するGuidクラス属性を探します。

  4. プロジェクトをビルドする

  5. アセンブリの公開トークン キーを取得します。これを行うには、次のコマンドを実行する必要があります。

    sn.exe -T ASSEMBLY_FILE

    この情報は、後でPUBLIC_TOKEN_KEYを使用するときに必要になります。sn.exeファイルは、C :\Program Files\Microsoft SDKs\Windows\v8.0A\bin\sn.exe にあります。上記のファイル パスのフレームワーク (v8.0A) のバージョン番号に注意してください。プロジェクトのコンパイルに使用されるフレームワークのバージョンと一致している必要があります。

  6. 次のコマンドを使用して、アセンブリを GAC に配置します。

    gacutil.exe /i ASSEMBLY_FILE /f

    GAC に登録するには、管理者権限が必要です。gacutil.exeファイルは、C :\Program Files\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\gacutil.exe にあります。ファイルパスのフレームワーク (v8.0A) のバージョン番号に注意してください。その上。プロジェクトのコンパイルに使用されるフレームワークのバージョンと一致している必要があります。

  7. .REG (以下を参照) ファイルに次の変更を加えます。注意: GENERATOR_GUID と PROJECT_TYPE_GUID の両方を中かっこで指定する必要があることに注意してください: {XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX}

    7.1. Visual Studio の修正バージョン番号が使用されます (例: 10.0 または 9.0): VS_VERSION

    7.2. ジェネレーターの GUID を修正: GENERATOR_GUID

    7.3. アセンブリの名前空間を修正してください: NAMESPACE_NAME

    7.4. ジェネレーターのクラス名を修正: GENERATOR_TYPE_NAME

    7.5. ジェネレーターを登録するために、Visual Studio は、このジェネレーターを適用できるプロジェクトの種類を認識する必要があります。そのため、適切なプロジェクト タイプ (C#、VB.NET など) の GUID を取得する必要があります。プロジェクト タイプの GUID を確認するには、Visual Studio プロジェクト ファイル (*.csproj) をテキスト エディターで開き、 ProjectTypeGuids XML 要素で GUID を探す必要があります。これらの GUID ごとに、.REG ファイルの最後の 3 つのエントリのブロックを繰り返し、PROJECT_TYPE_GUIDを、見つかった GUID に置き換えます。

    7.6. カスタム ツールに関連付けられているファイルの拡張子を修正します: FILE_EXTENSTION

  8. .REG ファイルを実行します。これを行うには、管理者権限が必要になる場合があります。

.REG ファイル:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\CLSID\GENERATOR_GUID]
@="COM+ class: NAMESPACE_NAME.GENERATOR_TYPE_NAME"
"InprocServer32"="C:\\WINDOWS\\system32\\mscoree.dll"
"ThreadingModel"="Both"
"Class"="NAMESPACE_NAME.GENERATOR_TYPE_NAME"
"Assembly"="NAMESPACE_NAME, Version=ASSEMBLY_VERSION, Culture=Neutral, PublicKeyToken=PUBLIC_TOKEN_KEY"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID]

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID\\.FILE_EXTENSTION]
@="GENERATOR_TYPE_NAME"

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\VS_VERSION\Generators\PROJECT_TYPE_GUID\GENERATOR_TYPE_NAME]
@="Code generator for whatever you like"
"CLSID"="GENERATOR_GUID"
"GeneratesDesignTimeSource"=dword:00000001

PS。残念ながら、REG ファイル内のプレースホルダーを区別することができませんでした。残念ながら、StackOverflow が使用するテキスト エディターは、そのマークアップ要素とコンテンツを区別できません。

于 2012-10-13T23:17:58.690 に答える