Как захватить вывод консоли из службы С#?

У нас есть служба C#, развернутая в удаленной клиентской системе. Приложение записывает значительный объем «диагностической» информации в консоль (т. е. Console.WriteLine()). Служба не «делает то, что должна». Как мы можем захватить вывод консоли из службы в другом приложении?

Версия WinForm приложение может быть загружено на месте клиента. К сожалению, работает корректно.

Обновлять:

Мы можем изменить услугу, но в данный момент предпочли бы не вносить серьезных изменений.

Мы также регистрируемся в MSMQ, но только для «важных» событий. Эта служба взаимодействует с MSMQ для своей обычной работы. Или, по крайней мере, должен. Служба, похоже, не извлекает элементы из MSMQ, когда это делает версия WinForm. Таким образом, запись сообщений, которые отправляются на консоль, может быть проблематичной.


person Mike Chess    schedule 14.10.2008    source источник


Ответы (7)


Вы можете вообще изменить код услуги? Если это так, использование Console.SetOut для записи в файл вместо этого будет наиболее очевидным первым портом захода. Затем перейдите к использованию надлежащей библиотеки ведения журнала для следующего выпуска :)

person Jon Skeet    schedule 14.10.2008
comment
Использование Console.SetOut было достаточно минимальным изменением, которое дало достаточно информации для определения проблемы со службой. - person Mike Chess; 14.10.2008

Как правило, вам следует избегать записи диагностической информации непосредственно в консоль, журнал событий, MSMQ или куда-либо еще из кода вашего приложения. Вместо этого вызовите API ведения журнала и используйте конфигурацию для перенаправления вывода туда, куда вы хотите.

Например, вы можете заменить все Console.WriteLine на Trace.WriteLine (*). Затем вы можете перенаправить вывод на консоль, в файл или в другое место, изменив файл конфигурации приложения: например, для вывода на консоль используйте ConsoleTraceListener, что-то вроде:

<configuration>
  <system.diagnostics>
    <trace autoflush="false" indentsize="4">
      <listeners>
        <add name="configConsoleListener"
             type="System.Diagnostics.ConsoleTraceListener" />
      </listeners>
    </trace>
  </system.diagnostics>
 </configuration>

Во время отладки вы будете получать выходные данные на консоли — на сайте клиента вы настроите его для перенаправления вывода трассировки в файл, в журнал событий или что-то подобное.

Еще лучше использовать стороннюю структуру ведения журнала (я бы рекомендовал Log4Net), которая даст вам больше возможностей, чем System.Diagnostics.Trace.

(*) Trace.Write/Trace.WriteLine аналогичны Debug.Write/Debug.WriteLine, за исключением того, что последние компилируются, только если определен символ DEBUG. Поэтому предпочтите Trace to Debug, если вы хотите, чтобы выходные данные были доступны в сборках Release.

person Joe    schedule 14.10.2008

У вас есть куча вариантов; перенаправление вывода консоли в файл и использование надлежащей библиотеки ведения журнала, как уже упоминалось, являются двумя хорошими. Вот средний вариант: запись в журнал событий.

EventLog log;
string logsource = "MyService";

// execute once per invocation
if (!System.Diagnostics.EventLog.SourceExists(logsource))
{
    System.Diagnostics.EventLog.CreateEventSource(
        logsource, "Application");
}
log = new EventLog();
log.Source = logsource;
log.Log = "Application";

// replace console logging with this
log.WriteEntry(message, EventLogEntryType.Information);

Затем найдите записи в журнале событий приложений (Администрирование -> Средство просмотра событий), где Source = "MyService".

person Michael Petrotta    schedule 14.10.2008

Я бы вообще не использовал Console.WriteLine из службы Window. Вероятно, вам следует записывать эти ошибки в файл журнала.

Другой способ сделать это, чтобы несколько приложений могли использовать журналы, — отправить сообщения журнала в очередь MSMQ.

person Patrik Svensson    schedule 14.10.2008

использовать debug.writeline и использовать отладочное представление sysinternals?

person Danimal    schedule 14.10.2008
comment
или log4net в следующий раз и настройте место назначения. - person kenny; 14.10.2008

Я нашел этот пост на MSDN, который связывает вывод консоли с форматированным текстовым полем, работал у меня очень быстро и легко.

Он переопределяет WriteLine и может быть расширен для переопределения других методов.

person Marc    schedule 08.07.2009

Вот как я просмотрел консольный вывод службы, работающей под Windows 7. Это может помочь, если вы абсолютно не можете изменить исходный код службы для записи в файл.

  1. Запустите services.msc и отредактируйте свойства службы. На вкладке «Вход в систему» ​​установите флажок «Разрешить взаимодействие службы с рабочим столом».

  2. Используйте редактор реестра, чтобы изменить ImagePath вашей службы: перейдите в раздел HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\ [ваше имя службы] и отредактируйте ImagePath. Добавьте cmd.exe /c в начало строки ImagePath. Итак, если ваш исходный ImagePath равен c:\myService\myservice.exe, ваш новый ImagePath должен быть cmd.exe /c c:\myService\myservice.exe.

  3. Запустите свой сервис. Вы должны получить всплывающее окно под названием «Обнаружение интерактивных служб». Выберите «Просмотреть сообщение». Ваш экран должен переключать контексты и отображать окно консоли. Когда закончите, нажмите кнопку «Вернуть сейчас».

  4. По завершении отладки измените ImagePath обратно на исходное значение. Затем снимите флажок «Разрешить службе взаимодействовать с рабочим столом» в свойствах службы и перезапустите службу.

Предупреждение: я сделал это только с одной службой, и это сработало для меня. Я не знаю, будет ли это работать для какой-либо службы или приведет к неожиданным результатам, поэтому я настоятельно рекомендую вам делать это только в непроизводственной среде.

person Mike E    schedule 19.11.2015