Отладка пользовательской библиотеки dll, на которую ссылается макрос visual studio
я раньше спрашивал:добавить ссылку dll на макросы visual studio
идея создания макросов на моем языке (C#) упрощает создание макросов. проблема в том, что я не могу отладить dll
чтобы решить проблему, я пробовал:
Я поставил
myClassLibrary.pdb
рядом сmyClassLibrary.dll
надеясь, что я смогу отладить методы в 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
);
примечание. Я добавил следующие ссылки плюс onces, которые имеют макросы vba:
5 ответов
наконец, вот решение:
на следующих шагах я опишу, как можно будет отлаживать dll, которая будет выполняться макросом.
если вы хотите иметь возможность сделать что-то вроде:
(обратите внимание, что я отлаживаю макрос на c# в visual studio!!!)
создайте новое решение в 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 Add-in)
следуйте wizzard оставьте значения по умолчанию, кроме как на странице 4 Выберите:
продолжить выбор параметров по умолчанию в Мастере до создания проекта:
установите этот проект как проект запуска, чтобы при нажатии F5 запускался addin.
добавить ссылку из MyAddin1 в библиотеку классов
как только мы имеем эта ссылка мы должны иметь возможность выполнить макрос из addin. Для этого откройте
Connect.cs
перейдите к методуExec
добавитьClassLibrary1.Class1.Macro1(_applicationObject);
так выглядит:добавьте точку останова в начале метода Exec, чтобы мы могли ее отладить.
выполнить MyAddin1, нажав
F5
. Должен открыться новый экземпляр visual studio.на новом экземпляре visual studio откройте любое решение. В этом случай я снова открываю то же решение>
Got to tools затем нажмите на MyAddin1, но убедитесь, что документ открыт:
как только вы нажмете на мое добавление, вы должны попасть в точку останова!
15. Примечание! По какой-то причине мне пришлось прокомментировать строку ClassLibrary1.Class1.Macro1(_applicationObject);
поэтому я комментирую эту строку и на этой строке я разместил:
var textDoc = (TextDocument)(_applicationObject.ActiveDocument.Object(string.Empty));
textDoc.Selection.Insert("Hello world");
наконец, когда я нажмите на MyAddin1, расположенный на инструментах Hello world будет вставлен!
как только я узнаю, что макрос работает нормально, я мог бы экспортировать класс в библиотеку классов и вызвать метод макроса в dll вместо плагина.
у меня есть еще один ответ, который еще лучше!
единственная причина, по которой я создал addin, заключается в том, что мне нужна ссылка на DTE. Почему бы не ссылаться на dte, который мне нужен.
алгоритм выглядит следующим образом:
использовать класс
Ide
чтобы получить DTE любого экземпляра visual studio.после этого ООД создать макрос.
вот 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 runing, который содержит решение с именем ConsoleApp1
тогда я смогу сделать:
var dte = Ide.GetDte("ConsoleApp1");
dte.ActiveDocument.Selection.Insert("My macro is working!");
и текст My macro is working!
будет вставлен в активный документ. убедитесь, что есть активный документ, хотя
Тоно,
вы ссылались на свою dll для приложения wcf и сделали его отладочной версией?
From:http://msdn.microsoft.com/en-us/library/ms164704.aspx:
независимо от того, как вы начинаете отладку, убедитесь, что вы создаете отладку сначала версия DLL и убедитесь, что отладочная версия находится в место, где приложение ожидает найти его. Это может показаться очевидно, но если вы забудете этот шаг, приложение может найти другая версия DLL и загрузите ее. Затем программа продолжайте бежать, в то время как вы задаетесь вопросом, почему ваша точка останова никогда не была поражена. При отладке можно проверить, какие библиотеки DLL имеются в программе загружается путем открытия окна модулей отладчика. окно модуля список каждой DLL или EXE, загруженных в процессе отладки. Для дополнительные сведения см. В разделе Как использовать окно модули.
Если вы пытаетесь отлаживать ссылка на dll, эта статья SO может помочь здесь:как отладить ссылочную dll (имеющую pdb)
~JOL
использование DLL от других издателей легко. Но важно понимать код. Я использую IlSpy. Его бесплатно и использовать. Он декомпилирует dll для просмотра всех методов, классов и пространств имен.
способ отладки надстроек visual studio-открыть другой экземпляр visual studio и присоединить его к тому, который активирует надстройку. Это описано здесь. Также убедитесь, что надстройка построена на локальном компьютере, а pdbs доступны, иначе она не попадет в ваши точки останова.