Не удается получить информацию о трассировке ошибок привязки WPF для записи в файл журнала, настроенный в коде

Я пытаюсь отладить то, что, по моему мнению, является проблемой привязки WPF, которая происходит только на одной рабочей машине - я не могу воспроизвести на машине разработчика. Чтобы сделать это, я пытался получить информацию о трассировке привязки для вывода в файл журнала. Следуя ответам подобным этому, я смог заставить его выводиться в жестко закодированное местоположение, настроив его в 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, кажется, не объединяет все это для меня, или я упускаю некоторые важные детали. Может кто-нибудь, пожалуйста, помогите мне понять, что я делаю неправильно?


person rory.ap    schedule 03.10.2016    source источник


Ответы (1)


нет коллекции Listeners, в которую я могу добавить свой экземпляр слушателя.

На самом деле есть: PresentationTraceSources.DataBindingSource .Listeners

Свойство возвращает объект TraceSource, который используется при выводе сообщений привязки данных. Вы можете добавить к этому источнику любого прослушивателя, например TextWriterTraceListener, который вы создали в отделенном коде, расширив переменную среды %TEMP% и используя ее в качестве каталога для вашего выходного файла.

Обратите внимание, что программный подход требует перекомпиляции для изменения выходного местоположения или добавления некоторого другого значения конфигурации, которое можно прочитать во время выполнения. Другой метод позволяет вам указать всю конфигурацию в файле 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).

Конечно, вы можете выбрать более короткое пространство имен и имена типов, чем те, которые я использовал здесь. :)

person Peter Duniho    schedule 03.10.2016