无法获取 WPF 绑定错误跟踪信息以写入代码中配置的日志文件
Cannot get WPF binding error trace information to write to log file configured in code
我正在尝试调试我认为仅在一台生产机器上发生的 WPF 绑定问题 -- 我无法在开发人员机器上重现。为了做到这一点,我一直在尝试获取绑定跟踪信息以输出到日志文件。按照答案 like this one,我已经能够通过在 App.config:
中配置它来输出到硬编码位置
<system.diagnostics>
<sources>
<source name="System.Windows.Data" switchName="SourceSwitch" >
<listeners>
<add name="textListener" />
</listeners>
</source>
</sources>
<switches>
<add name="SourceSwitch" value="All" />
</switches>
<sharedListeners>
<add name="textListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="c:\BindingErrors.log" />
</sharedListeners>
<trace autoflush="true" indentsize="4"/>
</system.diagnostics>
这在我的机器上运行良好,我对 c:\
驱动器具有管理权限。问题是我想将日志写在用户有权访问的地方,例如他们的 TEMP 文件夹。所以我想做这样的事情,使用 %TEMP%
环境变量:
initializeData="%TEMP%\BindingErrors.log"
虽然这不起作用,我想它不会起作用 -- ;因此,按照该答案中的建议,我尝试通过代码而不是 App.config 配置输出。到目前为止,这是我尝试过的:
var listener = new
TextWriterTraceListener(Environment.ExpandEnvironmentVariables(
@"%TEMP%\BindingErrors.log"), "myListener");
Trace.Listeners.Add(listener);
Trace.WriteLine("foo"); // just to see if it works at all.
Trace.Flush();
但这只会将 foo
写入 %TEMP%
文件夹中的日志文件。它不会写入绑定错误。我试图复制 App.config 的内容,但是没有 Sources
集合,所以当我实例化 TraceSource
时,像这样:
var source = new TraceSource("mySource", SourceLevels.Information);
我不知道如何处理它,也没有 Listeners
集合可以添加我的 listener
实例。
MSDN 似乎并没有为我将所有内容整合在一起,或者我遗漏了一些关键细节。有人可以帮我弄清楚我做错了什么吗?
…there's no Listeners collection to which I can add my listener instance.
其实有:PresentationTraceSources.DataBindingSource
.Listeners
属性 returns TraceSource
输出数据绑定消息时使用的对象。您可以向该源添加任何侦听器,例如您通过扩展 %TEMP%
环境变量并将其用作输出文件的目录在代码隐藏中创建的 TextWriterTraceListener
。
请注意,编程方法需要重新编译以更改输出位置,或者添加一些可以在 运行 时读取的其他配置值。另一种技术允许您在 app.config 文件中指定整个配置,方法是实现知道如何扩展环境变量的自定义 TraceListener
。
例如:
namespace TestSO39836570TraceListenerBindingErrors
{
class EnvironmentAwareTextWriterTraceListener : TextWriterTraceListener
{
public EnvironmentAwareTextWriterTraceListener(string path)
: base(Environment.ExpandEnvironmentVariables(path))
{ }
public EnvironmentAwareTextWriterTraceListener(string path, string name)
: base(Environment.ExpandEnvironmentVariables(path), name)
{ }
}
}
然后在app.config文件中,可以指定监听器:
<system.diagnostics>
<sources>
<source name="System.Windows.Data" switchName="SourceSwitch">
<listeners>
<add name="textListener"/>
</listeners>
</source>
</sources>
<switches>
<add name="SourceSwitch" value="All"/>
</switches>
<sharedListeners>
<add name="textListener"
type="TestSO39836570TraceListenerBindingErrors.EnvironmentAwareTextWriterTraceListener, TestSO39836570TraceListenerBindingErrors"
initializeData="%temp%\BindingErrors.log"/>
</sharedListeners>
<trace autoflush="true" indentsize="4"/>
</system.diagnostics>
请注意,当指定在您自己的程序程序集中找到的自定义 TraceListener
类型时,您需要在 type
属性中指定程序集名称,方法是在完全限定类型名称之后带逗号,然后是程序集名称(在上面的示例中,类型的命名空间与程序集名称相同,根据 Visual Studio 中创建的项目的默认值)。
您当然可以选择比我在这里使用的更短的命名空间和类型名称。 :)
我正在尝试调试我认为仅在一台生产机器上发生的 WPF 绑定问题 -- 我无法在开发人员机器上重现。为了做到这一点,我一直在尝试获取绑定跟踪信息以输出到日志文件。按照答案 like this one,我已经能够通过在 App.config:
中配置它来输出到硬编码位置<system.diagnostics>
<sources>
<source name="System.Windows.Data" switchName="SourceSwitch" >
<listeners>
<add name="textListener" />
</listeners>
</source>
</sources>
<switches>
<add name="SourceSwitch" value="All" />
</switches>
<sharedListeners>
<add name="textListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="c:\BindingErrors.log" />
</sharedListeners>
<trace autoflush="true" indentsize="4"/>
</system.diagnostics>
这在我的机器上运行良好,我对 c:\
驱动器具有管理权限。问题是我想将日志写在用户有权访问的地方,例如他们的 TEMP 文件夹。所以我想做这样的事情,使用 %TEMP%
环境变量:
initializeData="%TEMP%\BindingErrors.log"
虽然这不起作用,我想它不会起作用 --
var listener = new
TextWriterTraceListener(Environment.ExpandEnvironmentVariables(
@"%TEMP%\BindingErrors.log"), "myListener");
Trace.Listeners.Add(listener);
Trace.WriteLine("foo"); // just to see if it works at all.
Trace.Flush();
但这只会将 foo
写入 %TEMP%
文件夹中的日志文件。它不会写入绑定错误。我试图复制 App.config 的内容,但是没有 Sources
集合,所以当我实例化 TraceSource
时,像这样:
var source = new TraceSource("mySource", SourceLevels.Information);
我不知道如何处理它,也没有 Listeners
集合可以添加我的 listener
实例。
MSDN 似乎并没有为我将所有内容整合在一起,或者我遗漏了一些关键细节。有人可以帮我弄清楚我做错了什么吗?
…there's no Listeners collection to which I can add my listener instance.
其实有:PresentationTraceSources.DataBindingSource
.Listeners
属性 returns TraceSource
输出数据绑定消息时使用的对象。您可以向该源添加任何侦听器,例如您通过扩展 %TEMP%
环境变量并将其用作输出文件的目录在代码隐藏中创建的 TextWriterTraceListener
。
请注意,编程方法需要重新编译以更改输出位置,或者添加一些可以在 运行 时读取的其他配置值。另一种技术允许您在 app.config 文件中指定整个配置,方法是实现知道如何扩展环境变量的自定义 TraceListener
。
例如:
namespace TestSO39836570TraceListenerBindingErrors
{
class EnvironmentAwareTextWriterTraceListener : TextWriterTraceListener
{
public EnvironmentAwareTextWriterTraceListener(string path)
: base(Environment.ExpandEnvironmentVariables(path))
{ }
public EnvironmentAwareTextWriterTraceListener(string path, string name)
: base(Environment.ExpandEnvironmentVariables(path), name)
{ }
}
}
然后在app.config文件中,可以指定监听器:
<system.diagnostics>
<sources>
<source name="System.Windows.Data" switchName="SourceSwitch">
<listeners>
<add name="textListener"/>
</listeners>
</source>
</sources>
<switches>
<add name="SourceSwitch" value="All"/>
</switches>
<sharedListeners>
<add name="textListener"
type="TestSO39836570TraceListenerBindingErrors.EnvironmentAwareTextWriterTraceListener, TestSO39836570TraceListenerBindingErrors"
initializeData="%temp%\BindingErrors.log"/>
</sharedListeners>
<trace autoflush="true" indentsize="4"/>
</system.diagnostics>
请注意,当指定在您自己的程序程序集中找到的自定义 TraceListener
类型时,您需要在 type
属性中指定程序集名称,方法是在完全限定类型名称之后带逗号,然后是程序集名称(在上面的示例中,类型的命名空间与程序集名称相同,根据 Visual Studio 中创建的项目的默认值)。
您当然可以选择比我在这里使用的更短的命名空间和类型名称。 :)