-->

这是在Visual Studio中的宏被引用调试自定义DLL(Debug custom dll th

2019-07-30 14:44发布

我以前问: dll引用添加到Visual Studio宏

在我的语言(C#)创建的宏的想法更容易创建的宏。 问题是,我不能调试DLL

为了解决我已经试过了问题:

  1. 我把myClassLibrary.pdb旁边myClassLibrary.dll希望我在那里将能够通过steping在他们调试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宏有onces:

Answer 1:

最后,这里是解决方案:

在下面的步骤,我将描述怎么会可以调试将由宏执行的DLL。

如果你希望能够做一些事情,如:

(注意:我调试运行上的Visual Studio C#宏!!!)

  1. Visual Studio创建一个新的解决方案

  2. 现在添加一个新的类库项目到解决方案。 (这是将执行宏类)

  3. 添加引用EnvDTE,EbvDTE100,EnvDTE80,EnvDTE90,EnvDTE90a。 基本相同的引用是Visual Studio中的宏有:

  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. 一旦我们有一个参考,我们应该能够从插件执行宏。 为了这样做开放Connect.cs并导航到方法Exec添加ClassLibrary1.Class1.Macro1(_applicationObject); 所以它看起来像:

  11. 在Exec方法的开始添加一个破发点,所以我们可以对其进行调试。

  12. 按执行MyAddin1 F5 。 Visual Studio中的一个新的实例应该打开。

  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世界,你好将被插入!


有一次,我知道宏运行良好,我可以在类导出到一个类库,并有宏调用中的DLL而不是在插件的方法。



Answer 2:

我还有另一个答案是再好不过了!

为什么我创建的插件的唯一原因是因为我所需要的DTE的参考。 为什么不能引用我需要的DTE。

该算法是如下:

  1. 使用类Ide要什么有什么的Visual Studio实例的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! 将活动文档中插入。 确保有一个活动文档,虽然



Answer 3:

远野,

你有没有引用您的WCF应用程序的DLL,并使它的调试版本?

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

不管你如何开始调试,确保您首先构建DLL的调试版本,并确保调试版本是在应用程序能够找到它的位置。 这似乎是显而易见的,但如果你忘了这一步,应用程序可能会发现不同版本的DLL并加载它。 然后程序将继续运行,而你想知道为什么你的断点从来没有击中。 当你调试,你可以验证它的DLL程序已经通过打开调试器的模块窗口中加载。 模块窗口列出了正在调试的进程中加载​​的每个DLL或EXE。 有关详细信息,请参阅如何使用的模块窗口。


如果您正试图调试参考DLL,该SO文章可能有所帮助在这里: 如何调试一个被引用的DLL(有PDB)

〜JOL



Answer 4:

使用DLL的其他出版商是很容易。 但要明白的代码是很重要的。 我用IlSpy。 它的自由和使用。 它反编译的dll查看所有methodes,类和命名空间。



Answer 5:

该办法调试的Visual Studio插件是打开另一个Visual Studio的实例,并连接到一个将激活您的加载项。 它被描述在这里 。 另外,还要确保加载项是建立在本地计算机上,PDBS可否则也不会打你的断点。



文章来源: Debug custom dll that is being referenced in visual studio macro