我以前问: dll引用添加到Visual Studio宏
在我的语言(C#)创建的宏的想法更容易创建的宏。 问题是,我不能调试DLL
为了解决我已经试过了问题:
我把myClassLibrary.pdb
旁边myClassLibrary.dll
希望我在那里将能够通过steping在他们调试DLL中的方法。
创建一个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:
最后,这里是解决方案:
在下面的步骤,我将描述怎么会可以调试将由宏执行的DLL。
如果你希望能够做一些事情,如:
(注意:我调试运行上的Visual Studio C#宏!!!)
Visual Studio创建一个新的解决方案
现在添加一个新的类库项目到解决方案。 (这是将执行宏类)
添加引用EnvDTE,EbvDTE100,EnvDTE80,EnvDTE90,EnvDTE90a。 基本相同的引用是Visual Studio中的宏有:
创建将执行您计划在类库使用宏的方法。
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!!!"); } } }
添加另一个项目(Visual Studio中加载项)
按照威泽德保留默认设置,除了4页的选择:
继续选择向导中的默认选项,直到创建项目:
设置项目作为这样当我们按下F5键插件运行的启动项目。
从MyAddin1添加一个引用到类库
一旦我们有一个参考,我们应该能够从插件执行宏。 为了这样做开放Connect.cs
并导航到方法Exec
添加ClassLibrary1.Class1.Macro1(_applicationObject);
所以它看起来像:
在Exec方法的开始添加一个破发点,所以我们可以对其进行调试。
按执行MyAddin1 F5
。 Visual Studio中的一个新的实例应该打开。
在Visual Studio中的新实例中打开的任何解决方案。 在这种情况下,我再次打开相同的解决方案>
该杀工具,然后单击MyAddin1但要确保文档已打开:
一旦你点击了我的插件,你应该命中断点!
15.注意! 出于某种原因,我不得不发表意见线ClassLibrary1.Class1.Macro1(_applicationObject);
所以我注释掉该行并在该行,我把:
var textDoc = (TextDocument)(_applicationObject.ActiveDocument.Object(string.Empty));
textDoc.Selection.Insert("Hello world");
最后当我点击位于工具MyAddin1世界,你好将被插入!
有一次,我知道宏运行良好,我可以在类导出到一个类库,并有宏调用中的DLL而不是在插件的方法。
我还有另一个答案是再好不过了!
为什么我创建的插件的唯一原因是因为我所需要的DTE的参考。 为什么不能引用我需要的DTE。
该算法是如下:
使用类Ide
要什么有什么的Visual Studio实例的DTE。
一旦你的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!
将活动文档中插入。 确保有一个活动文档,虽然
远野,
你有没有引用您的WCF应用程序的DLL,并使它的调试版本?
来源: http://msdn.microsoft.com/en-us/library/ms164704.aspx :
不管你如何开始调试,确保您首先构建DLL的调试版本,并确保调试版本是在应用程序能够找到它的位置。 这似乎是显而易见的,但如果你忘了这一步,应用程序可能会发现不同版本的DLL并加载它。 然后程序将继续运行,而你想知道为什么你的断点从来没有击中。 当你调试,你可以验证它的DLL程序已经通过打开调试器的模块窗口中加载。 模块窗口列出了正在调试的进程中加载的每个DLL或EXE。 有关详细信息,请参阅如何使用的模块窗口。
如果您正试图调试参考DLL,该SO文章可能有所帮助在这里: 如何调试一个被引用的DLL(有PDB)
〜JOL
使用DLL的其他出版商是很容易。 但要明白的代码是很重要的。 我用IlSpy。 它的自由和使用。 它反编译的dll查看所有methodes,类和命名空间。
该办法调试的Visual Studio插件是打开另一个Visual Studio的实例,并连接到一个将激活您的加载项。 它被描述在这里 。 另外,还要确保加载项是建立在本地计算机上,PDBS可否则也不会打你的断点。