调试在visual studio宏中引用的自定义dll [英] Debug custom dll that is being referenced in visual studio macro

查看:229
本文介绍了调试在visual studio宏中引用的自定义dll的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我以前问过:将dll参考添加到visual studio宏

以我的语言(C#)创建宏的想法使得创建宏更容易。 问题是我无法调试dll

the idea of creating the macros in my language (C#) makes it easier to create the macros. The problem is that I cannot debug the dll

要解决我尝试过的问题:


  1. 我将 myClassLibrary.pdb 旁边的 myClassLibrary.dll 希望我能够通过加入dll来调试方法。

  1. I placed myClassLibrary.pdb next to myClassLibrary.dll hoping I where going to be able to debug the methods in the dll by steping in to them.

创建了一个WCF服务。因为我不知道如何引用vba的服务,我从类库中引用它。问题是我需要使用诸如 DTE.ActiveDocument 的变量,这些变量不是可序列化的,这意味着我无法将它们传递给wcf服务。

Created a WCF service. Because I did not knew how to reference the service from vba I reference it from the class library. The problem is that I need to use variables such as DTE.ActiveDocument and those variables are not serializable meaning I could not pass them to the wcf service.

在C#中工作的想法是非常好的,但无法调试,看到发生了什么,这使得它有点困难。我可能要去我的旧选项,我在C#编译时创建了我的代码,然后用反射器反编译成vba。

the idea of working in C# is very nice but not being able to debug and see what is going on makes it somewhat difficult. I might have to go to my older option where I created my code on C# compiled then decompiled into vba with reflector.

我想我得到一个解决方案。我以为为什么不在控制台应用程序中创建宏?我可以获得活动的文档,但无法更改。

I think I am close on getting a solution. I thought why not create the macro in a console application? I am able to get the active document text but not able to change it.

        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宏具有的权限:

note I added the following references plus the onces that vba macros have:

推荐答案

我还有另一个答案更好!

创建的加载项是因为我需要一个引用的DTE。为什么不参考我需要的dte

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.

该算法如下:


  1. code> Ide 获取任何可视化工作室的DTE。

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

一旦你有这个dte创建宏

Once you have that dte create the macro.

这是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 的解决方案,那么我将能够做到:

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

这篇关于调试在visual studio宏中引用的自定义dll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆