Debug custom dll that is being referenced in visual studio macro

前端 未结 5 2117
-上瘾入骨i
-上瘾入骨i 2021-02-08 19:48

I previously asked: Add dll reference to visual studio macros

the idea of creating the macros in my language (C#) makes it easier to create the macros. The prob

相关标签:
5条回答
  • 2021-02-08 20:27

    Using DLL's from other publishers is easy. But it's important to understand the code. I use IlSpy. Its free and to use. It decompiles the dll to view all methodes, classes and namespaces.

    0 讨论(0)
  • 2021-02-08 20:28

    Finally here is the solution:

    On the following steps I will describe how it will be possible to debug the dll that will be executed by a macro.

    If you want to be able to do something like:

    enter image description here (Note I am debuging a macro on c# on visual studio!!!)

    1. Create a new Solution in visual studio enter image description here

    2. Now add a new class library Project to that solution. (This is the class that will execute the macros) enter image description here

    3. Add the references EnvDTE, EbvDTE100, EnvDTE80, EnvDTE90, EnvDTE90a. Basically the same references that visual studio macros have: enter image description here

    4. Create a method that will execute the macro you plan to use on the class library.

         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. Add another project (Visual Studio Add-in)enter image description here

    6. Follow the wizzard leave the defaults except on page 4 select: enter image description here

    7. Continue selecting the default options on the wizard until the project is created: enter image description here

    8. Set that project as the startup project so that when we press f5 the addin runs.

    9. Add a reference from MyAddin1 to the class library

    10. Once we have that reference we should be able to execute the macro from the addin. In order to do so open Connect.cs and navigate to the method Exec add ClassLibrary1.Class1.Macro1(_applicationObject); so it looks like: enter image description here

    11. Add a break point at the start of the Exec method so we can debug it.

    12. Execute MyAddin1 by pressing F5. A new instance of visual studio should open.

    13. On the new instance of visual studio open any solution. In this case I am opening the same solution again>

    14. Got to tools then click on MyAddin1 but make sure a document is open: enter image description here

    15. Once you click on my addin you should hit the breakpoint! enter image description here

    15. NOTE! For some reason I had to comment the line ClassLibrary1.Class1.Macro1(_applicationObject);

    So I comment out that line and on that line I placed:

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

    finally when I click on MyAddin1 located on tools Hello world will be inserted!


    Once I know the macro is running fine I could export the class to a class library and have the macro call the method on the dll instead of the plug in.

    0 讨论(0)
  • 2021-02-08 20:33

    Tono,

    Have you referenced your dll for the wcf application and made it a debug version?

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

    No matter how you start debugging, make sure that you build the Debug version of the DLL first and make sure that the Debug version is in the location where the application expects to find it. This may seem obvious, but if you forget this step, the application might find a different version of the DLL and load it. The program will then continue to run, while you wonder why your breakpoint was never hit. When you are debugging, you can verify which DLLs your program has loaded by opening the debugger's Modules window. The Modules window lists each DLL or EXE loaded in the process you are debugging. For more information, see How to: Use the Modules Window.


    If you are attempting to debug a referenced dll, this SO article might be of assistance here: How to debug a referenced dll (having pdb)

    ~JOL

    0 讨论(0)
  • 2021-02-08 20:34

    The way to debug visual studio add-ins is to open another visual studio instance and attach to the one that will activate your add-in. It is described here. Also make sure that the add-in is built on the local machine and pdbs are available otherwise it will not hit your breakpoints.

    0 讨论(0)
  • 2021-02-08 20:47

    I have yet another answer which is even better!

    The only reason why I created the addin is because I needed a reference of the DTE. Why not reference the dte that I need.

    The the algorithm is as follow:

    1. Use class Ide to get the DTE of whatever instance of visual studio.

    2. Once you have that dte create the macro.

    Here is the Ide class:

    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;
                    }
                }
    
            }
        }
    }
    

    then if I have an instance of visual studio runing that contains a solution with the name ConsoleApp1 then I will be able to do:

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

    and the text My macro is working! will be inserted in the active document. make sure there is an active document though

    0 讨论(0)
提交回复
热议问题