如何从外部程序集中的 VS 断点操作访问自定义记录器

How to access a custom logger, from a VS breakpoint action, in an external assembly

背景

Visual studio 有一个非常酷的功能,它允许您在遇到断点时将消息记录到输出 window 中。更酷的是,您可以通过用大括号括起来来引用实时值。但是等等:还有更多;您甚至可以调用具有任意签名的方法(传递参数并返回值)。无论返回什么值,都会写入输出 window。太棒了。

在 VS 2013 中,这是 "When Hit" 功能 在 VS 2015(和 2017 RC)中,它被称为 "Action"。

动机

我想了解 WPF 源代码中发生了什么,所以我使用 "Action" 设置断点以输出跟踪信息。但是,因为 WPF 没有限制我感兴趣的值的类型(它们作为 object 传递,类型根据上下文推断),这些值经常被记录为错误,因为断点动作不知道这个上下文,因此不知道期望的类型。

我的处理计划是从断点操作调用自定义记录器并传递足够的参数以使记录器可以解析值的类型。
自定义记录器是我的 MainWindow 部分的成员 class。

概念验证

我通过在我的 MainWindow 局部 class 中设置一个断点操作来验证它是否有效,它引用记录器成员并毫无问题地传递参数。这适用于我的应用程序中的断点,但我想在其他程序集中的断点上使用它。

问题

如上所述,当断点在我自己的程序集中时,这工作正常,但对于第三方程序集中设置的断点(如 wpf 源代码)则失败。显然对象需要被限定以便调试器可以解析它。

如何限定它,如何引用 window 的实例以及我正在寻找的成员?
我想我可以将其设为静态单例,但我可能需要多个记录器。

我发现我可以引用我的记录器。例如,如果我的主要 window 部分 class 看起来像这样...

namespace EventSetterNull_SO_41604891_2670182
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window

...那我就可以这样引用了...

((EventSetterNull_SO_41604891_2670182.MainWindow)System.Windows.Application.Current.MainWindow)

所以,我的断点就像...

然后,我可以在 System.Windows.Markup.WpfXamlLoader.TransformNodes 中设置断点,将 xamlReader 传递给我的记录器,并注销解析器从 baml 生成的节点结构。

xaml

<Window x:Class="EventSetterNull_SO_41604891_2670182.BuildInXaml"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:EventSetterNull_SO_41604891_2670182"
        mc:Ignorable="d"
        Title="BuildInXaml" Height="350" Width="525">
    <Window.Resources>
        <SetterBaseCollection x:Key="ButtonStyleSetters">
            <Setter Property="FrameworkElement.Height" Value="30"></Setter>
        </SetterBaseCollection>
    </Window.Resources>

    <Button Name="Button1"
            local:Behaviours.StyleSetters="{StaticResource ButtonStyleSetters}" />

输出window

"Line:    6    NamespaceDeclaration    http://schemas.microsoft.com/winfx/2006/xaml/presentation"
"Line:    6    NamespaceDeclaration    http://schemas.microsoft.com/winfx/2006/xaml"
"Line:    6    NamespaceDeclaration    http://schemas.microsoft.com/expression/blend/2008"
"Line:    6    NamespaceDeclaration    http://schemas.openxmlformats.org/markup-compatibility/2006"
"Line:    6    NamespaceDeclaration    clr-namespace:EventSetterNull_SO_41604891_2670182;assembly=EventSetterNull-SO-41604891-2670182"
"Line:    6    StartObject    BuildInXaml" 
"Line:    6        StartMember    Title"
"Line:    6            Value    BuildInXaml"
"Line:    6        EndMember    "
"Line:    8        StartMember    Height"
"Line:    8            Value    System.Windows.Baml2006.TypeConverterMarkupExtension"
"Line:    8        EndMember    "
"Line:    8        StartMember    Width"
"Line:    8            Value    System.Windows.Baml2006.TypeConverterMarkupExtension"
"Line:    8        EndMember    "
"Line:    8        StartMember    Resources"
"Line:    9            GetObject    System.Windows.Baml2006.Baml2006SchemaContext"
"Line:    9                StartMember    DeferrableContent"
"Line:    9                    Value    System.IO.MemoryStream"
"Line:    9                EndMember    "
"Line:    9            EndObject    "
"Line:   15        EndMember    "
"Line:   17        StartMember    Content"
"Line:   17            StartObject    Button" 
"Line:   17                StartMember    ConnectionId"
"Line:   17                    Value    1"
"Line:   17                EndMember    "
"Line:    0                StartMember    Name"
"Line:    0                    Value    Button1"
"Line:    0                EndMember    "
"Line:   17                StartMember    StyleSetters"
"Line:   17                    Value    System.Windows.StaticResourceExtension"
"Line:   17                EndMember    "
"Line:   10                StartObject    SetterBaseCollection" 
"Line:   10                    StartMember    _Items"
"Line:   11                        StartObject    Setter" 
"Line:   11                            StartMember    Property"
"Line:   11                                Value    Height"
"Line:   11                            EndMember    "
"Line:   11                            StartMember    Value"
"Line:   11                                Value    30"
"Line:   11                            EndMember    "
"Line:   11                        EndObject    "
"Line:   11                    EndMember    "
"Line:   11                EndObject    "
"Line:   18            EndObject    "
"Line:   18        EndMember    "
"Line:   18    EndObject    "

所以,我可以确切地看到 wpf 如何看待 xaml,如果它搞砸了,这很方便...

xaml

<Window x:Class="EventSetterNull_SO_41604891_2670182.BuildInXaml"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:EventSetterNull_SO_41604891_2670182"
        mc:Ignorable="d"
        Title="BuildInXaml" Height="350" Width="525">
    <Window.Resources>
        <SetterBaseCollection x:Key="ButtonStyleSetters">
            <Setter Property="FrameworkElement.Height" Value="30"></Setter>
            <EventSetter Event="ButtonBase.Click"  Handler="StyleClick"
                          HandledEventsToo="False" />
        </SetterBaseCollection>
    </Window.Resources>

    <Button Name="Button1"
            local:Behaviours.StyleSetters="{StaticResource ButtonStyleSetters}" />

输出window

"Line:    6    NamespaceDeclaration    http://schemas.microsoft.com/winfx/2006/xaml/presentation"
"Line:    6    NamespaceDeclaration    http://schemas.microsoft.com/winfx/2006/xaml"
"Line:    6    NamespaceDeclaration    http://schemas.microsoft.com/expression/blend/2008"
"Line:    6    NamespaceDeclaration    http://schemas.openxmlformats.org/markup-compatibility/2006"
"Line:    6    NamespaceDeclaration    clr-namespace:EventSetterNull_SO_41604891_2670182;assembly=EventSetterNull-SO-41604891-2670182"
"Line:    6    StartObject    BuildInXaml" 
"Line:    6        StartMember    Title"
"Line:    6            Value    BuildInXaml"
"Line:    6        EndMember    "
"Line:    8        StartMember    Height"
"Line:    8            Value    System.Windows.Baml2006.TypeConverterMarkupExtension"
"Line:    8        EndMember    "
"Line:    8        StartMember    Width"
"Line:    8            Value    System.Windows.Baml2006.TypeConverterMarkupExtension"
"Line:    8        EndMember    "
"Line:    8        StartMember    Resources"
"Line:    9            GetObject    System.Windows.Baml2006.Baml2006SchemaContext"
"Line:    9                StartMember    DeferrableContent"
"Line:    9                    Value    System.IO.MemoryStream"
"Line:    9                EndMember    "
"Line:    9            EndObject    "
"Line:   15        EndMember    "
"Line:   17        StartMember    Content"
"Line:   17            StartObject    Button" 
"Line:   17                StartMember    ConnectionId"
"Line:   17                    Value    1"
"Line:   17                EndMember    "
"Line:    0                StartMember    Name"
"Line:    0                    Value    Button1"
"Line:    0                EndMember    "
"Line:   17                StartMember    StyleSetters"
"Line:   17                    Value    System.Windows.StaticResourceExtension"
"Line:   17                EndMember    "
"Line:   10                StartObject    SetterBaseCollection" 
"Line:   10                    StartMember    _Items"
"Line:   11                        StartObject    Setter" 
"Line:   11                            StartMember    Property"
"Line:   11                                Value    Height"
"Line:   11                            EndMember    "
"Line:   11                            StartMember    Value"
"Line:   11                                Value    30"
"Line:   11                            EndMember    "
"Line:   11                        EndObject    "
"Line:   12                        StartObject    EventSetter" 
"Line:   12                            StartMember    Event"
"Line:   12                                Value    System.Windows.Baml2006.TypeConverterMarkupExtension"
"Line:   12                            EndMember    "
"Line:   12                            StartMember    Event"
Exception thrown: 'System.Xaml.XamlDuplicateMemberException' in System.Xaml.dll

如您所见,wpf 变得困惑并在 EventSetter 对象中找到第二个 Event 成员,但该成员不存在并引发错误。

这是 wpf 中的错误。