4

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...?

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • The error does not seem to be related to Visual Studio or tracing inside Visual Studio, it seems related to the Python tools package itself. To debug this failure, you could debug VS with another VS and all exceptions turned on (ctrl-D + E, check 'Thrown'). – Simon Mourier May 18 '14 at 07:07
  • @SimonMourier: the Python Tools C# plugin just calls `System.Diagnostics.Debug.WriteLine` and `System.Diagnostics.Trace.WriteLine`, so I can't see how the issue can be "related to the Python tools package itself". As I just want to see the debug/trace somewhere, and not step through the code or intercept exception, I'm reluctant to attach another VS instance... it doesn't seem a productive approach to my development needs. – Tony Delroy May 19 '14 at 02:27
  • 'The `Python Tools Package' package id not load correctly.' means VS detects a problem with *this* package. The error could be anything including DLL reference problem for example. My debugging suggestion is just to find the cause of *this* issue, nothing more. – Simon Mourier May 19 '14 at 06:24
  • @SimonMourier: oh I see... yes - I can see output from some file appends I've added to the Python Tools DLL so I know it's loading and executing and I guess I've mentally forgotten there was even a warning about loading... I'll return to that and see if sorting it out lets VS process the trace listener config. Thank you indeed! – Tony Delroy May 19 '14 at 08:38
  • @SimonMourier: so - those errors only appear when I have the additional "best guess" `` tag lines in devenv.exe.config as listed above in the question - I guess the question is still what config would work without the errors.... – Tony Delroy May 19 '14 at 10:47
  • I still think it's an issue in this [Python Tools Package], apparently due to tracing :-). For example, it could be some trace initialization that fails in a static constructor. That would typically cause an 'Exception has been thrown by the target of an invocation.'. Have you turned on all thrown exceptions, including caught one, like I suggested initially? – Simon Mourier May 19 '14 at 12:44
  • @SimonMourier I don't have a full VS instance on the machine I'm trying to install on... just installing atop VS Shell, so I can't attach another VS instance there. Perhaps you're right, but I'm afraid I just don't have time to sort out another VS licence/install to confirm either way.... – Tony Delroy May 22 '14 at 02:35
  • You could try WinDbg (http://msdn.microsoft.com/en-us/windows/hardware/hh852365.aspx) then, it's a bit rough, but free and easy to install/uninstall. – Simon Mourier May 22 '14 at 06:06

1 Answers1

1

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

Philip Pittle
  • 11,821
  • 8
  • 59
  • 123
  • thank you for sharing your approach - it sounds good. I'm currently writing trace/logging to a text file and just looking at it in an independent viewer, but this could be far more convenient sometimes... I'll try it out when I've a chance. Cheers and +1. – Tony Delroy Jun 27 '14 at 08:11
  • When it's finally working, getting the log output from the Visual Studio Output id defiantly convenient. But pulling from a log file is certainly sufficient for during initial development. Good luck! – Philip Pittle Jul 01 '14 at 09:04