Отладка пользовательской библиотеки dll, на которую ссылается макрос visual studio

я раньше спрашивал:добавить ссылку dll на макросы visual studio

идея создания макросов на моем языке (C#) упрощает создание макросов. проблема в том, что я не могу отладить dll

чтобы решить проблему, я пробовал:

  1. Я поставил myClassLibrary.pdb рядом с myClassLibrary.dll надеясь, что я смогу отладить методы в 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
        );

примечание. Я добавил следующие ссылки плюс onces, которые имеют макросы vba:

enter image description here

5 ответов


наконец, вот решение:

на следующих шагах я опишу, как можно будет отлаживать dll, которая будет выполняться макросом.

если вы хотите иметь возможность сделать что-то вроде:

enter image description here(обратите внимание, что я отлаживаю макрос на c# в visual studio!!!)

  1. создайте новое решение в visual studio enter image description here

  2. теперь добавьте к этому новый проект библиотеки классов решение. (Это класс, который будет выполнять макросы) enter image description here

  3. добавьте ссылки EnvDTE, EbvDTE100, EnvDTE80, EnvDTE90, EnvDTE90a. В основном те же ссылки, что и макросы visual studio:enter image description here

  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 Add-in)enter image description here

  6. следуйте wizzard оставьте значения по умолчанию, кроме как на странице 4 Выберите: enter image description here

  7. продолжить выбор параметров по умолчанию в Мастере до создания проекта: enter image description here

  8. установите этот проект как проект запуска, чтобы при нажатии F5 запускался addin.

  9. добавить ссылку из MyAddin1 в библиотеку классов

  10. как только мы имеем эта ссылка мы должны иметь возможность выполнить макрос из addin. Для этого откройте Connect.cs перейдите к методу Exec добавить ClassLibrary1.Class1.Macro1(_applicationObject); так выглядит: enter image description here

  11. добавьте точку останова в начале метода Exec, чтобы мы могли ее отладить.

  12. выполнить MyAddin1, нажав F5. Должен открыться новый экземпляр visual studio.

  13. на новом экземпляре visual studio откройте любое решение. В этом случай я снова открываю то же решение>

  14. Got to tools затем нажмите на MyAddin1, но убедитесь, что документ открыт: enter image description here

  15. как только вы нажмете на мое добавление, вы должны попасть в точку останова! enter image description here

15. Примечание! По какой-то причине мне пришлось прокомментировать строку ClassLibrary1.Class1.Macro1(_applicationObject);

поэтому я комментирую эту строку и на этой строке я разместил:

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

наконец, когда я нажмите на MyAddin1, расположенный на инструментах Hello world будет вставлен!


как только я узнаю, что макрос работает нормально, я мог бы экспортировать класс в библиотеку классов и вызвать метод макроса в dll вместо плагина.


у меня есть еще один ответ, который еще лучше!

единственная причина, по которой я создал addin, заключается в том, что мне нужна ссылка на DTE. Почему бы не ссылаться на dte, который мне нужен.

алгоритм выглядит следующим образом:

  1. использовать класс Ide чтобы получить DTE любого экземпляра visual studio.

  2. после этого ООД создать макрос.

вот 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 runing, который содержит решение с именем ConsoleApp1 тогда я смогу сделать:

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

и текст My macro is working! будет вставлен в активный документ. убедитесь, что есть активный документ, хотя


Тоно,

вы ссылались на свою dll для приложения wcf и сделали его отладочной версией?

From:http://msdn.microsoft.com/en-us/library/ms164704.aspx:

независимо от того, как вы начинаете отладку, убедитесь, что вы создаете отладку сначала версия DLL и убедитесь, что отладочная версия находится в место, где приложение ожидает найти его. Это может показаться очевидно, но если вы забудете этот шаг, приложение может найти другая версия DLL и загрузите ее. Затем программа продолжайте бежать, в то время как вы задаетесь вопросом, почему ваша точка останова никогда не была поражена. При отладке можно проверить, какие библиотеки DLL имеются в программе загружается путем открытия окна модулей отладчика. окно модуля список каждой DLL или EXE, загруженных в процессе отладки. Для дополнительные сведения см. В разделе Как использовать окно модули.


Если вы пытаетесь отлаживать ссылка на dll, эта статья SO может помочь здесь:как отладить ссылочную dll (имеющую pdb)

~JOL


использование DLL от других издателей легко. Но важно понимать код. Я использую IlSpy. Его бесплатно и использовать. Он декомпилирует dll для просмотра всех методов, классов и пространств имен.


способ отладки надстроек visual studio-открыть другой экземпляр visual studio и присоединить его к тому, который активирует надстройку. Это описано здесь. Также убедитесь, что надстройка построена на локальном компьютере, а pdbs доступны, иначе она не попадет в ваши точки останова.