I've modified a C# plugin that's part of Python Tools for Visual Studio 2.0, and want to see the output from Debug.WriteLine and Trace.WriteLine statements in the code. Note that the plugin is used in Visual Studio 2013 itself, modifying debugging of python processes....
I'm hoping I can add a trace listener in devenv.exe.config
as suggested by pminaev on the PTVS discussion forum here (attaching another VS to VS itself seems clumsy so I'm hoping to avoid that).
What I believe to be correct config for other .NET applications doesn't seem to work for VS2013 itself. My efforts are documented below.
If anyone's managed to redirect plugin debug/trace output to the Visual Studio Console (or anywhere else more convenient than another attached VS instance), tips greatly appreciated....
My Google-fu turned up a couple examples, based on which I've tried adding...
<system.diagnostics>
<trace autoflush="true" />
<listeners>
<add name="myConsoleTraceListener" type="System.Diagnostics.ConsoleTraceListener" />
</listeners>
</trace>
</system.diagnostics>
...and...
<system.diagnostics>
<source name="System.ServiceModel.MessageLogging" switchValue="Verbose, ActivityTracing">
<listeners>
<add name="myTraceListener" />
</listeners>
</source>
<sharedListeners>
<add name="myTraceListener" type="System.Diagnostics.ConsoleTraceListener" />
</sharedListeners>
</system.diagnostics>
Starting PTVS afterwards, nothing's usable. With either config I get a popup:
The `Python Tools Package' package id not load correctly.
The problem may have been caused by a configuration change or by
the installation of another extension. You can get more information by
examining the file
'C:\Users\XXX\AppData\Roaming\Microsoft\VisualStudio\12.0\Acti
vityLog.xml'.
The ActivityLog doesn't mean much to me:
<entry>
<record>41</record>
<time>2014/05/12 07:52:47.851</time>
<type>Error</type>
<source>VisualStudio</source>
<description>CreateInstance failed for package [Python Tools Package]</description>
<guid>{6DBD7C1E-1F1B-496D-AC7C-C55DAE66C783}</guid>
<hr>80131604</hr>
<errorinfo>Exception has been thrown by the target of an invocation.</errorinfo>
</entry>
<entry>
<record>42</record>
<time>2014/05/12 07:52:47.851</time>
<type>Error</type>
<source>VisualStudio</source>
<description>End package load [Python Tools Package]</description>
<guid>{6DBD7C1E-1F1B-496D-AC7C-C55DAE66C783}</guid>
<hr>80004005 - E_FAIL</hr>
<errorinfo>Exception has been thrown by the target of an invocation.</errorinfo>
</entry>
When I try to attach to the remote python process I get another popup:
Unable to connect to 'secret@server'. Operation not supported.
Unknown error: 0x80131902.
Google-foo suggests this is some failure to load a .NET version...?
I wanted to do something similar for a plugin I wrote: pMixins. I used log4net instead of System.Diagnostics, but wanted to route log messages to the Visual Studio Output window.
I never got a config based approach to work and ended up doing the wiring programmatically. Additionally, I had to create a custom log writer to write to the Visual Studio Output Window.
In my Package file (https://github.com/ppittle/pMixins/blob/master/pMixins.VSPackage/pMixinsVisualStudioCodeGenerateInitializer.cs):
protected override void Initialize()
{
//Create a Visual Studio Writer
_visualStudioWriter = new VisualStudioWriter(dte, this);
//Initialize Logging
Log4NetInitializer.Initialize(_visualStudioWriter, this);
}
VisualStudioWriter (summary) (https://github.com/ppittle/pMixins/blob/master/pMixins.VSPackage/Infrastructure/VisualStudioWriter.cs):
public class VisualStudioWriter : IVisualStudioWriter
{
private EnvDTE.OutputWindowPane _outputWindowPane;
public VisualStudioWriter(DTE dte, System.IServiceProvider serviceProvider)
{
_outputWindowPane = LoadOutputWindowPane(dte);
}
private EnvDTE.OutputWindowPane LoadOutputWindowPane(DTE dte)
{
const string windowName = "pMixins Code Generator";
EnvDTE.OutputWindowPane pane = null;
EnvDTE.Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);
if (window != null)
{
EnvDTE.OutputWindow output = window.Object as EnvDTE.OutputWindow;
if (output != null)
{
pane = output.ActivePane;
if (pane == null || pane.Name != windowName)
{
for (int ix = output.OutputWindowPanes.Count; ix > 0; ix--)
{
pane = output.OutputWindowPanes.Item(ix);
if (pane.Name == windowName)
break;
}
if (pane == null || pane.Name != windowName)
pane = output.OutputWindowPanes.Add(windowName);
if (pane != null)
pane.Activate();
}
}
}
return pane;
}
public void OutputString(string s)
{
_outputWindowPane.OutputString(s);
}
}
Log4NetInitializer (Summary) https://github.com/ppittle/pMixins/blob/master/CopaceticSoftware.CodeGenerator.StarterKit/Logging/Log4NetInitializer.cs
public static class Log4NetInitializer
{
public static void Initialize(IVisualStudioWriter visualStudioWriter,
IServiceProvider serviceProvider)
{
//http://stackoverflow.com/questions/650694/changing-the-log-level-programmaticaly-in-log4net
var outputWindowAppender =
new VisualStudioOutputWindowAppender(visualStudioWriter)
{
Layout =
new PatternLayout(@"%date{HH:mm:ss,fff} %thread% %-5level [%logger{2}] %message%newline"),
Threshold =
#if DEBUG
Level.Debug
#else
Level.Info
#endif
};
log4net.Config.BasicConfigurator.Configure(
outputWindowAppender);
}
}
Finally, VisualStudioOutputWindowAppender (https://github.com/ppittle/pMixins/blob/master/CopaceticSoftware.CodeGenerator.StarterKit/Logging/VisualStudioOutputWindowAppender.cs)
public class VisualStudioOutputWindowAppender : AppenderSkeleton
{
public IVisualStudioWriter OutputWindow { get; set; }
public VisualStudioOutputWindowAppender(IVisualStudioWriter outputWindow)
{
OutputWindow = outputWindow;
Layout = new PatternLayout("%-5level %logger - %message%newline");
}
protected override void Append(LoggingEvent loggingEvent)
{
if (null == OutputWindow)
return;
if (null == loggingEvent)
return;
OutputWindow.OutputString(RenderLoggingEvent(loggingEvent));
}
}
Hope That Helps
User contributions licensed under CC BY-SA 3.0