Как захватить вывод консоли из службы C#?
Вопрос
У нас есть служба C#, которая развернута в системе удаленного клиента.Приложение записывает на консоль значительный объем «диагностической» информации (т.Консоль.WriteLine()).Сервис не «делать то, что должно». Как мы можем захватить выход консоли от Сервиса в другом приложении?
В версии WinForm приложение можно загрузить по месту нахождения клиента.К сожалению, он работает корректно.
Обновлять:
Мы можем внести изменения в услугу, но предпочли бы не вносить серьезных изменений на данный момент.
Мы также регистрируемся в MSMQ, но только для «важных» событий.Эта служба взаимодействует с MSMQ при нормальной работе.Или, по крайней мере, так должно быть.Похоже, что служба не извлекает элементы из MSMQ, в то время как версия WinForm это делает.Поэтому написание сообщений, отправляемых на консоль, может оказаться проблематичным.
Решение
Можно ли изменить сервисный код совсем?Если это так, то использование Console.SetOut для записи в файл будет наиболее очевидным первым портом захода.Затем перейдите к использованию правильной библиотеки журналирования для следующего выпуска :)
Другие советы
В общем, вам следует избегать записи диагностической информации непосредственно в консоль, журнал событий, 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 вместо Debug, если вы хотите, чтобы выходные данные были доступны в сборках Release.
У вас есть множество вариантов;перенаправление вывода консоли в файл и использование правильной библиотеки журналирования, как уже упоминалось, — два хороших варианта.Вот средний вариант:запись в журнал событий.
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».
Я бы вообще не использовал Console.WriteLine из службы Windows.Вероятно, вам следует записать эти ошибки в файл журнала.
Другой способ сделать это, чтобы несколько приложений могли использовать журналы, — разместить сообщения журнала в очереди MSMQ.
использовать debug.writeline и использовать debugview sysinternals?
я нашел эта почта на MSDN, который связывает вывод консоли с форматированным текстовым полем, сработал для меня очень быстро и легко.
Он переопределяет WriteLine и может быть расширен для переопределения других методов.
Вот как я просмотрел консольный вывод службы, работающей под Windows 7.Это может помочь, если вы абсолютно не можете изменить исходный код службы для входа в файл.
Запустите Services.msc и отредактируйте свойства службы.На вкладке «Вход» установите флажок «Разрешить службе взаимодействовать с рабочим столом».
Используйте редактор реестра, чтобы изменить ImagePath вашей службы:Перейдите в HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\services\ [имя вашей службы] и отредактируйте ImagePath.Добавить
cmd.exe /c
в начало строки ImagePath.Итак, если ваш исходный ImagePathc:\myService\myservice.exe
ваш новый ImagePath должен бытьcmd.exe /c c:\myService\myservice.exe
.Запустите свой сервис.Вы должны получить всплывающее окно под названием «Обнаружение интерактивных служб».Выберите «Просмотреть сообщение».Ваш экран должен переключить контекст и отобразить окно консоли.По завершении нажмите кнопку «Вернуться сейчас».
По завершении отладки измените ImagePath обратно на исходное значение.Затем снимите флажок «Разрешить службе взаимодействовать с рабочим столом» в свойствах службы и перезапустите службу.
Предупреждение:Я сделал это только с одним сервисом, и у меня это сработало.Я не знаю, будет ли это работать для какой-либо службы или приведет к каким-либо неожиданным результатам, поэтому я настоятельно рекомендую вам делать это только в непроизводственной среде.