调试在visual studio宏中引用的自定义dll [英] Debug custom dll that is being referenced in visual studio macro
问题描述
我以前问过:将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
要解决我尝试过的问题:
-
我将
myClassLibrary.pdb
旁边的myClassLibrary.dll
希望我能够通过加入dll来调试方法。
I placed
myClassLibrary.pdb
next tomyClassLibrary.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.
该算法如下:
-
code> Ide 获取任何可视化工作室的DTE。
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屋!