8

背景: xml 入力を受け取り、cs 出力を生成するカスタムツールがあります。カスタム ツールをそのバージョンの Visual Studio で動作させるには、Visual Studioに登録する必要があります。

行ったこと: Visual Studio 2015 でカスタム ツールの登録を行いましたが、正常に動作しています。しかし、問題は Visual Studio 2017 にあります。

問題:これまでの調査で、Visual Studio 2015 までは、VS にはツールの登録を許可する直接のレジストリ エントリがありましたが、VS 2017 から、Microsoft はレジストリ エントリの保存方法に変更を加えました (よく読んでください) VS2017 の変更点を理解してください)。

VS 2017 を開いてカスタム ツールを実行しようとすると、エラーが発生します。

このシステムでカスタム ツール"ツール名"が見つかりません。

ここに画像の説明を入力

カスタム ツールがまだ VS 2017 に登録されていないため、これは明らかです。

ファイルをレジストリにロードするように言っているこの男をフォローしようとしまし.binたが、VS 2017 の起動が無効になるとも言っています。VS を起動するには、ハイブをアンロードする必要があります。調査によると、.bin ファイルは、インストールされている VS のタイプ (エンタープライズ、プロなど) に基づいて異なる場所にある可能性があります。

誰もこれを以前にやったことがありますか?

ティア

4

2 に答える 2

23

ここでは、Visual Studio 拡張機能 (VSIX) を作成することにより、別のアプローチに従う必要がある場合があります。以下で詳細に説明しました。

Visual Studio 2017 でカスタム ツールまたは単一ファイル ジェネレーターを作成する方法:

VS2017 より前にカスタム ツールを作成するにはIVsSingleFileGenerator、カスタム ツールをシステム レジストリに登録および登録解除するためのインターフェイスとコードを実装する必要がありましたが、VS2017 では、Microsoft はレジストリ構造全体を変更しました。変更点は、システム レジストリが台無しにならないように、VS がプライベート レジストリにレジストリ エントリを作成することです。以前はレジストリ エントリがシステム レジストリに作成されていましたが、現在はシステム レジストリに作成されています。

C:\Users\xyz\AppData\Local\Microsoft\VisualStudio\15.0_xx\privateregistry.bin

Visual Studio 2017 では、Visual Studio 自体 (F5 キー) からツールを直接実行してテストすることもサポートされています。これにより、 Visual Studio Experimental Instanceと呼ばれる Visual Studio の別のインスタンスが開始され、レジストリ エントリが作成されるため、その中でツールをテストできます。

C:\Users\xyz\AppData\Local\Microsoft\VisualStudio\15.0_xxExp\privateregistry.bin

以下の手順に従って、VS2017 でカスタム ツールを作成します。

  1. VSIX 拡張機能を作成する必要があります
  2. 新しい Visual Studio パッケージを追加する
  3. 埋め込むIVsSingleFileGenerator
  4. レジストリ エントリ コードを追加する
  5. ツールを VS2017 で実行してコンパイルおよびテストする
  6. 生成された .VSIX ファイルをダブルクリックして、ツールをインストールします。

例として、「CountLines」という名前の拡張機能/カスタム ツールを作成します。このツールは、ファイル (カスタム ツール プロパティが CountLines に設定されている) を読み取り、ファイルの行数を含む XML ファイルを生成します。例えば<LineCount>1050</LineCount>

1. VSIX 拡張機能 を作成する 拡張機能を作成するには、Visual Studio セットアップのオプション機能として含まれている Visual Studio Extensibility Tools をインストールしておく必要があります。インストールされていない場合は、VS 2017 セットアップを変更してインストールすることもできます。を選択して、新しい VSIX (Visual Studio 拡張機能) プロジェクトを作成します。

新しいプロジェクト -> 拡張性 -> VSIX プロジェクト

「CountLinesVSIX」のような名前を付けます。

2. 新しい Visual Studio パッケージを 追加する VSIX プロジェクトが作成されたら、新しい Visual Studio パッケージを選択して追加します。

追加 -> 新しい項目 -> 拡張性 -> Visual Studio パッケージ

「CountLines.cs」という名前を付けます。既存のコードを削除し、実装CountLines.cs用のコードに置き換える必要がありますIVsSingleFileGenerator

3. IVsSingleFileGenerator の実装 interface のカスタム実装を記述しIVsSingleFileGeneratorます。サンプル コードは次のとおりです。

using System;
using System.Runtime.InteropServices;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System.Text;

namespace CountLinesVSIX
    {
    [PackageRegistration(UseManagedResourcesOnly = true)]
    [InstalledProductRegistration( "CountLines", "Generate XML with line count", "1.0")] 
    [Guid("202E7E8B-557E-46CB-8A1D-3024AD68F44A")]
    [ComVisible(true)]
    [ProvideObject(typeof(CountLines))]
    [CodeGeneratorRegistration(typeof(CountLines), "CountLines", "{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}", GeneratesDesignTimeSource = true)]
    public sealed class CountLines : IVsSingleFileGenerator
    {

        #region IVsSingleFileGenerator Members

        public int DefaultExtension(out string pbstrDefaultExtension)
        {
            pbstrDefaultExtension = ".xml";
            return pbstrDefaultExtension.Length;
        }

        public int Generate(string wszInputFilePath, string bstrInputFileContents,
          string wszDefaultNamespace, IntPtr[] rgbOutputFileContents,
          out uint pcbOutput, IVsGeneratorProgress pGenerateProgress)
        {
            try
            {
                int lineCount = bstrInputFileContents.Split('\n').Length;
                byte[] bytes = Encoding.UTF8.GetBytes("<LineCount>" + lineCount.ToString() + "</LineCount>" );
                int length = bytes.Length;
                rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(length);
                Marshal.Copy(bytes, 0, rgbOutputFileContents[0], length);
                pcbOutput = (uint)length;
            }
            catch (Exception ex)
            {
                pcbOutput = 0;
            }
            return VSConstants.S_OK;
        }

        #endregion
    }
}

上記のコードのように、拡張機能に一意の GUID を提供する必要があります[Guid("202E7E8B-557E-46CB-8A1D-3024AD68F44A")]。GUID は VS2017 から「ツール -> GUID の作成」を選択して作成できます。レジストリ形式として GUID 形式を選択します。上記のコードの GUID には中かっこがないことに注意してください。

[ComVisible(true)]COM 相互運用には必須

[CodeGeneratorRegistration(typeof(CountLines), "CountLines", "{FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}", GeneratesDesignTimeSource = true)]ツールを登録するためのコードを持つクラス属性です。パラメータは GeneratorType、GeneratorName、および C# 言語 GUID です

カスタム TextTemplate 書式設定をサポートする "TemplatedCodeGenerator" から派生させることもできます。これには、追加のコード実装が必要になる場合があります。

4. レジストリ エントリ コードを追加します。 以下のコードで新しいクラス ファイルを作成し、CodeGeneratorRegistrationAttribute.cs という名前を付けます。

using System;
using System.Globalization;
using Microsoft.VisualStudio.Shell;

namespace CountLinesVSIX
{

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
    public sealed class CodeGeneratorRegistrationAttribute : RegistrationAttribute
    {
        private string _contextGuid;
        private Type _generatorType;
        private Guid _generatorGuid;
        private string _generatorName;
        private string _generatorRegKeyName;
        private bool _generatesDesignTimeSource = false;
        private bool _generatesSharedDesignTimeSource = false;

        public CodeGeneratorRegistrationAttribute(Type generatorType, string generatorName, string contextGuid)
        {
            if (generatorType == null)
                throw new ArgumentNullException("generatorType");
            if (generatorName == null)
                throw new ArgumentNullException("generatorName");
            if (contextGuid == null)
                throw new ArgumentNullException("contextGuid");

            _contextGuid = contextGuid;
            _generatorType = generatorType;
            _generatorName = generatorName;
            _generatorRegKeyName = generatorType.Name;
            _generatorGuid = generatorType.GUID;
        }

        /// <summary> 
        /// Get the generator Type 
        /// </summary> 
        public Type GeneratorType
        {
            get { return _generatorType; }
        }

        /// <summary> 
        /// Get the Guid representing the project type 
        /// </summary> 
        public string ContextGuid
        {
            get { return _contextGuid; }
        }

        /// <summary> 
        /// Get the Guid representing the generator type 
        /// </summary> 
        public Guid GeneratorGuid
        {
            get { return _generatorGuid; }
        }

        /// <summary> 
        /// Get or Set the GeneratesDesignTimeSource value 
        /// </summary> 
        public bool GeneratesDesignTimeSource
        {
            get { return _generatesDesignTimeSource; }
            set { _generatesDesignTimeSource = value; }
        }

        /// <summary> 
        /// Get or Set the GeneratesSharedDesignTimeSource value 
        /// </summary> 
        public bool GeneratesSharedDesignTimeSource
        {
            get { return _generatesSharedDesignTimeSource; }
            set { _generatesSharedDesignTimeSource = value; }
        }


        /// <summary> 
        /// Gets the Generator name  
        /// </summary> 
        public string GeneratorName
        {
            get { return _generatorName; }
        }

        /// <summary> 
        /// Gets the Generator reg key name under  
        /// </summary> 
        public string GeneratorRegKeyName
        {
            get { return _generatorRegKeyName; }
            set { _generatorRegKeyName = value; }
        }

        /// <summary> 
        /// Property that gets the generator base key name 
        /// </summary> 
        private string GeneratorRegKey
        {
            get { return string.Format(CultureInfo.InvariantCulture, @"Generators\{0}\{1}", ContextGuid, GeneratorRegKeyName); }
        }
        /// <summary> 
        ///     Called to register this attribute with the given context.  The context 
        ///     contains the location where the registration inforomation should be placed. 
        ///     It also contains other information such as the type being registered and path information. 
        /// </summary> 
        public override void Register(RegistrationContext context)
        {
            using (Key childKey = context.CreateKey(GeneratorRegKey))
            {
                childKey.SetValue(string.Empty, GeneratorName);
                childKey.SetValue("CLSID", GeneratorGuid.ToString("B"));

                if (GeneratesDesignTimeSource)
                    childKey.SetValue("GeneratesDesignTimeSource", 1);

                if (GeneratesSharedDesignTimeSource)
                    childKey.SetValue("GeneratesSharedDesignTimeSource", 1);

            }
        }

        /// <summary> 
        /// Unregister this file extension. 
        /// </summary> 
        /// <param name="context"></param> 
        public override void Unregister(RegistrationContext context)
        {
            context.RemoveKey(GeneratorRegKey);
        }
    }
}

上記のコードは、エントリが VS プライベート レジストリに作成されていることを確認します。

5. VS2017 で実行して、ツールをコンパイルおよびテストします。 「source.extension.vsixmanifest」に「インストール ターゲット」を追加して、異なる VS2017 エディションが拡張機能でサポートされるようにすることができます。VS 2017 でツールを実行して、期待どおりに機能しているかどうかをテストします。VSIX を実行すると、Visual Studio 実験的インスタンスによって拡張機能がインストールされ、レジストリ "C:\Users\xyz\AppData\Local\Microsoft\VisualStudio\15.0_xxExp\privateregistry.bin" に登録されます。「ツール -> 拡張機能と更新プログラム」を選択すると、インストールされている拡張機能を確認できます。ツールをテストするには、ダミー プロジェクトを開き、ソリューション エクスプローラーでファイルを選択し、そのプロパティに移動して、カスタム ツール プロパティを「CountLines」に更新する必要があります。これが完了すると、VS はツールをバックグラウンドで実行し、出力を生成します。この例では、選択したファイルの下に xml ファイルを生成します。あるいは、

6. 生成された .VSIX ファイルをダブルクリックしてツールをインストールします。 テストが正常に終了したら、「projectName/bin/debug」にある VSIX をインストールしてみてください。ファイルをダブルクリックして VSIX をインストールし、インストール手順に従います。これで、VS2017 でツールを使用できるようになります。ツールの使用方法も同様です。カスタム ツールを実行するファイルを右クリックし、[カスタム ツールの実行] を選択します。

拡張機能をアンインストールする場合は、[ツール] -> [拡張機能と更新プログラム] -> [拡張機能を選択] に移動し、[アンインストール] をクリックします。VS を閉じるまで、ツールはアンインストールされないことに注意してください。閉じると、アンインストールするためのポップアップ ウィンドウが表示されます。[変更] を選択してアンインストールします。

于 2018-05-28T12:35:56.900 に答える
3

さて、研究中に、私はこの問題の答えを得ました。

解決:

  1. .bin ファイルをロードする必要があります (load hiv 経由)。
  2. ビンを変更または編集して、ツールを登録します。
  3. ハイブをアンロードします。

ステップ #1: ハイブをロードします。

a) レジストリを開きます (regedit)。ノードを選択しますHKEY_LOCAL_MACHINE

b) | に移動します。ファイル -> ハイブのロード

c) -> で入手できる bin ファイルを選択します%LocalAppData%\ Microsoft\ VisualStudio\ 15.0_'instance_id'\privateregistry.bin

d) キー名を指定します。これにより、キー名で新しいキー エントリが作成さHKEY_LOCAL_MACHINEれます。

e) .bin ファイルは次の場所で確認できます。HKEY_LOCAL_MACHINE\YourKeyName\Software\Microsoft\VisualStudio\

ここに画像の説明を入力

ステップ #2: ビンを編集する: 他の VS バージョンで行っていたのと同じ方法で、カスタム ツールを登録できるようになりました。実際、唯一の問題は、VS2017 キーをグローバル レジストリに取得することでした。これは、上記の手順 1 を使用して解決されます。

ステップ #3: ハイブをアンロードします。

a) でキーを選択しますHKEY_LOCAL_MACHINE

b) | に移動します。ファイルメニュー

c) ハイブをアンロードします。

ここに画像の説明を入力

于 2018-05-25T11:29:52.853 に答える