Debug custom dll that is being referenced in visual studio macro

前端 未结 5 2204
-上瘾入骨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: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 GetAllDte()
        {
            List list = new List();
            GetDte((displayName, x) =>
            {
                list.Add(x);
                return true; // continue serching we want all dte's
            });
            return list;
        }
    
        private static void GetDte(Func foo)
        {
            Dictionary dtesProcessIds = new Dictionary();
    
            //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

提交回复
热议问题