9

私は以前に尋ねました: ビジュアルスタジオマクロへのdll参照を追加します

私の言語(C#)でマクロを作成するというアイデアは、マクロの作成を容易にします。問題は、dllをデバッグできないことです

私が試した問題を解決するために:

  1. dll内のメソッドにステップインしてデバッグできるようになることを期待して、myClassLibrary.pdb隣に配置しました。myClassLibrary.dll

  2. WCFサービスを作成しました。vbaからサービスを参照する方法がわからなかったため、クラスライブラリからサービスを参照します。問題は、などの変数を使用する必要があることです。DTE.ActiveDocumentこれらの変数はシリアル化できません。つまり、wcfサービスに渡すことができませんでした。

C#で作業するというアイデアは非常に優れていますが、デバッグして何が起こっているのかを確認できないため、多少困難になります。以前のオプションに移動する必要があるかもしれません。C#でコードを作成し、リフレクターを使用してvbaに逆コンパイルしました。


編集

私は解決策を間近に控えていると思います。コンソールアプリケーションでマクロを作成してみませんか?アクティブなドキュメントテキストを取得できますが、変更できません。

        EnvDTE80.DTE2 MyDte;
        MyDte = (EnvDTE80.DTE2)System.Runtime.InteropServices.Marshal.GetActiveObject( "VisualStudio.DTE.10.0" );
        Console.WriteLine( "The Edition is " + MyDte.Edition );

        Console.ReadLine( );

        // write to the console the text that is selected. "sometimes it does not work don't know why"
        Console.WriteLine(
            MyDte.ActiveDocument.Selection.Text
        );

次の参照に加えて、vbaマクロが持つ1回を追加したことに注意してください。

ここに画像の説明を入力してください

4

5 に答える 5

5

最後にここに解決策があります:

次の手順では、マクロによって実行されるdllをデバッグする方法について説明します。

次のようなことができるようにしたい場合:

ここに画像の説明を入力してください (Visual StudioのC#でマクロをデバッグしていることに注意してください!!!)

  1. VisualStudioで新しいソリューションを作成するここに画像の説明を入力してください

  2. 次に、そのソリューションに新しいクラスライブラリプロジェクトを追加します。(これはマクロを実行するクラスです)ここに画像の説明を入力してください

  3. 参照EnvDTE、EbvDTE100、EnvDTE80、EnvDTE90、EnvDTE90aを追加します。基本的に、VisualStudioマクロと同じ参照があります。ここに画像の説明を入力してください

  4. クラスライブラリで使用する予定のマクロを実行するメソッドを作成します。

       namespace ClassLibrary1
       {
           public static class Class1
           {
               public static void Macro1(EnvDTE80.DTE2 DTE)
               {
                   // make sure an active text document is open before calling this method
                   DTE.ActiveDocument.Selection.Insert("Hello World!!!");
               }
           }
       }
    
  5. 別のプロジェクトを追加する(Visual Studioアドイン)ここに画像の説明を入力してください

  6. ウィザードに従って、4ページを除いてデフォルトのままにします。次を選択します。 ここに画像の説明を入力してください

  7. プロジェクトが作成されるまで、ウィザードでデフォルトオプションを選択し続けます。 ここに画像の説明を入力してください

  8. そのプロジェクトをスタートアッププロジェクトとして設定し、f5キーを押したときにアドインが実行されるようにします。

  9. MyAddin1からクラスライブラリへの参照を追加します

  10. その参照を取得すると、アドインからマクロを実行できるようになります。これを行うには、メソッドaddConnect.csを開いてナビゲートし、次のようにします。 ExecClassLibrary1.Class1.Macro1(_applicationObject);ここに画像の説明を入力してください

  11. Execメソッドの先頭にブレークポイントを追加して、デバッグできるようにします。

  12. を押してMyAddin1を実行しF5ます。VisualStudioの新しいインスタンスが開くはずです。

  13. Visual Studioの新しいインスタンスで、任意のソリューションを開きます。この場合、私は同じソリューションを再び開きます>

  14. ツールに移動し、MyAddin1をクリックしますが、ドキュメントが開いていることを確認してください。 ここに画像の説明を入力してください

  15. 私のアドインをクリックしたら、ブレークポイントに到達するはずです! ここに画像の説明を入力してください

15.注!どういうわけか私はその行にコメントしなければなりませんでしたClassLibrary1.Class1.Macro1(_applicationObject);

だから私はその行と私が置いたその行にコメントアウトします:

 var textDoc = (TextDocument)(_applicationObject.ActiveDocument.Object(string.Empty));
 textDoc.Selection.Insert("Hello world");

最後に、ツールにあるMyAddin1をクリックすると、Hello worldが挿入されます!


マクロが正常に実行されていることがわかったら、クラスをクラスライブラリにエクスポートし、プラグインではなくdllのメソッドをマクロに呼び出させることができます。

于 2012-07-28T17:08:47.590 に答える
2

さらに良い答えがもう1つあります。

アドインを作成した唯一の理由は、DTEの参照が必要だったためです。必要なdteを参照してみませんか。

アルゴリズムは次のとおりです。

  1. クラスIdeを使用して、VisualStudioのインスタンスのDTEを取得します。

  2. そのdteを取得したら、マクロを作成します。

Ideクラスは次のとおりです。

public class Ide
{        
    [DllImport("ole32.dll")]
    private static extern void CreateBindCtx(int reserved, out IBindCtx ppbc);

    [DllImport("ole32.dll")]
    private static extern void GetRunningObjectTable(int reserved, out IRunningObjectTable prot);

    public static DTE2 GetDte(string solutionName)
    {
        DTE2 dte = null;

        GetDte((displayName, x) =>
        {
            if (System.IO.Path.GetFileName(x.Solution.FullName).Contains(solutionName))
            {
                dte = x;
                return false; // we found it stop seraching
            }
            else
            {
                return true; // continue searching
            }

        });

        return dte;
    }

    public static DTE2 GetDte(int processId)
    {
        DTE2 dte = null;

        GetDte((displayName, x) =>
        {
            if (displayName.Contains(processId.ToString()))
            {
                dte = x;
                return false; // stop searching we found matching dte
            }
            else
            {
                return true; // continue searching
            }
        });

        return dte;
    }

    public static List<DTE2> GetAllDte()
    {
        List<DTE2> list = new List<DTE2>();
        GetDte((displayName, x) =>
        {
            list.Add(x);
            return true; // continue serching we want all dte's
        });
        return list;
    }

    private static void GetDte(Func<string, DTE2, bool> foo)
    {
        Dictionary<string, string> dtesProcessIds = new Dictionary<string, string>();

        //rot entry for visual studio running under current process.            
        IRunningObjectTable rot;
        GetRunningObjectTable(0, out rot);
        IEnumMoniker enumMoniker;
        rot.EnumRunning(out enumMoniker);
        enumMoniker.Reset();
        IntPtr fetched = IntPtr.Zero;
        IMoniker[] moniker = new IMoniker[1];
        while (enumMoniker.Next(1, moniker, fetched) == 0)
        {
            IBindCtx bindCtx;
            CreateBindCtx(0, out bindCtx);
            string displayName;
            moniker[0].GetDisplayName(bindCtx, null, out displayName);
            object comObject;
            rot.GetObject(moniker[0], out comObject);

            if (comObject != null)
            {
                DTE2 dteCurrent = null;
                try
                {
                    dteCurrent = (EnvDTE80.DTE2)comObject;

                    // if solution is not open continue
                    // this will cause an exception if it is not open
                    var temp = dteCurrent.Solution.IsOpen;

                    string solName = dteCurrent.Solution.FullName;

                    // if there is an instance of visual studio with no solution open continue                        
                    if (string.IsNullOrEmpty(solName))
                    {
                        continue;
                    }

                    // avoid adding duplicate ide's
                    if (dtesProcessIds.ContainsKey(displayName) == false)
                    {
                        dtesProcessIds.Add(displayName, displayName);
                    }
                    else
                    {
                        continue;
                    }

                }
                catch (System.Runtime.InteropServices.COMException e)
                {
                    continue;
                }
                catch (Exception e)
                {
                    continue;
                }
                if (dteCurrent != null)
                {
                    var cont = foo(displayName, dteCurrent);

                    if (cont == false)
                        return;
                }
            }

        }
    }
}

次に、名前の付いたソリューションを含むVisual Studioの実行インスタンスがある場合、次のConsoleApp1ことができるようになります。

 var dte = Ide.GetDte("ConsoleApp1");
 dte.ActiveDocument.Selection.Insert("My macro is working!");

テキストMy macro is working!はアクティブなドキュメントに挿入されます。ただし、アクティブなドキュメントがあることを確認してください

于 2012-07-29T21:23:22.280 に答える
0

遠野、

wcfアプリケーションのdllを参照して、デバッグバージョンにしましたか?

差出人:http://msdn.microsoft.com/en-us/library/ms164704.aspx

デバッグを開始する方法に関係なく、最初にデバッグバージョンのDLLをビルドし、デバッグバージョンがアプリケーションが検出する予定の場所にあることを確認してください。これは当たり前のように思えるかもしれませんが、この手順を忘れると、アプリケーションが別のバージョンのDLLを見つけてロードする可能性があります。その後、プログラムは実行を継続しますが、ブレークポイントがヒットしなかった理由を疑問に思います。デバッグ中は、デバッガーの[モジュール]ウィンドウを開くことで、プログラムがロードしたDLLを確認できます。[モジュール]ウィンドウには、デバッグしているプロセスにロードされている各DLLまたはEXEが一覧表示されます。詳細については、「方法:モジュールウィンドウを使用する」を参照してください。


参照されたdllをデバッグしようとしている場合は、このSOの記事が役立つ可能性があります:参照されたdllをデバッグする方法(pdbを使用)

〜JOL

于 2012-07-25T19:20:50.523 に答える
0

他の発行元のDLLを使用するのは簡単です。ただし、コードを理解することが重要です。IlSpyを使用しています。その無料で使用できます。dllを逆コンパイルして、すべてのメソッド、クラス、および名前空間を表示します。

于 2012-07-31T10:11:54.690 に答える
0

Visual Studioアドインをデバッグする方法は、別のVisual Studioインスタンスを開き、アドインをアクティブ化するインスタンスに接続することです。ここで説明します。また、アドインがローカルマシン上に構築されており、pdbが使用可能であることを確認してください。そうでない場合、ブレークポイントに到達しません。

于 2012-08-03T22:56:36.487 に答える