Как перенаправить стандартный вывод инструмента dotnet-счетчик по системе.Диагностика.Процесс?

#c# #.net

Вопрос:

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

 var startinfo = new ProcessStartInfo( "dotnet-counters" )
{
     Arguments = $"monitor --process-id 1",
     CreateNoWindow = true,
     UseShellExecute = false,
     RedirectStandardOutput = true,
     RedirectStandardError = true,
     RedirectStandardInput = true,
};
var process = new Process { StartInfo = startinfo };
process.OutputDataReceived  = OnReceived;
process.ErrorDataReceived  = OnReceived;
process.Exited  = OnExist;

process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
 

При запуске процесса из стандартного вывода считывается сообщение об ошибке:

Необработанное исключение: Система.Исключение InvalidOperationException: Не удается увидеть, была ли нажата клавиша, когда в приложении нет консоли или когда ввод консоли был перенаправлен из файла. Попробуйте Console.In.Заглянуть

Похоже, что стандартный вывод не может перенаправить таким образом, есть идеи?

Комментарии:

1. вы спрашиваете о перенаправлении вывода ; но ошибка связана с вводом . Работает ли это, если вы удалите ReadLine() функции?

2. @Felix если строки BeginOutputReadLine и BeginErrorReadLine удалены,вывод больше недоступен

3. подождите — ваша переменная есть process , но вы вызываете функции в классе Process . разве вы не получаете ошибку компиляции? (Я так и делаю)

Ответ №1:

Существует альтернатива перенаправлению выходных данных из инструмента. dotnet-counters Инструмент использует EventCounter класс под колпаками (источник). Значения System.Runtime , в частности, передаются поставщиком событий.

Хорошо то, что эти счетчики можно считывать вне процесса, как это делает инструмент. Это означает, что вы можете написать свой собственный код для прослушивания этих счетчиков и отображения их на веб-странице с некоторым кодом, подобным этому:

     var processId = xxxx;
    var providers = new List<EventPipeProvider>()
    {
        new EventPipeProvider("System.Runtime",
            EventLevel.Informational, arguments: new Dictionary<string, string>
        {
            {"EventCounterIntervalSec", "1"}
        })
    };

    var client = new DiagnosticsClient(processId);
    using (var session = client.StartEventPipeSession(providers, false))
    {
        var source = new EventPipeEventSource(session.EventStream);

        source.Dynamic.All  = obj =>
        {
            if (obj.EventName == "EventCounters")
            {
                var payload = (IDictionary<string, object>)obj.PayloadValue(0);
                Console.WriteLine(string.Join(", ", payload.Select(p => $"{p.Key}: {p.Value}")));
            }
        };

        source.Process();
    }
 

Приведенный выше код показывает исходные данные:

Полезная нагрузка: { имя:»ЦП-использование», «отображаемое имя»:»ЦП», в смысле:0, StandardDeviation:0, посчитайте:1, минимум:0, максимум:0, IntervalSec:1.0001626, серия:»интервал=1000″, аналог инженерной:»значит», метаданные:»», DisplayUnits:»%» }
полезная нагрузка: { имя:»рабочего набора», «отображаемое имя»:»рабочий набор», значит:54, StandardDeviation:0, посчитайте:1, мин:54, Макс:54, IntervalSec:1.0001626, серия:»интервал=1000″, аналог инженерной:»значит», метаданные:»», DisplayUnits:»МБ» }
полезная нагрузка: { название:»ГК» кучи «размер», «отображаемое имя»:»ГК» кучи «размер», подразумеваем:1, StandardDeviation:0, посчитайте:1, мин:1, Макс:1, IntervalSec:1.0001626, серия:»интервал=1000″, аналог инженерной:»значит», метаданные:»», DisplayUnits:»МБ» }
полезная нагрузка: { имя:»поколения-0-ГК-граф», «отображаемое имя»:»поколения 0″, «ГК Граф», DisplayRateTimeScale:»00:01:00″, инкремент:1, IntervalSec:1.0001626, «метаданные»:»», серия:»интервал=1000″, аналог инженерной:»сумма», DisplayUnits:»» }
полезная нагрузка: { название:»ген-1-ГК-граф», «отображаемое имя»:»ген. 1 ГК Граф», DisplayRateTimeScale:»00:01:00″, инкремент:0, IntervalSec:1.0001626, «метаданные»:»», серия:»интервал=1000″, аналог инженерной:»сумма», DisplayUnits:»» }
полезная нагрузка: { имя:»ген-2-ГК-граф», «отображаемое имя»:»ген 2 ГК Граф», DisplayRateTimeScale:»00:01:00″, инкремент:0, IntervalSec:1.0001626, «метаданные»:»», серия:»интервал=1000″, аналог инженерной:»сумма», DisplayUnits:»» }

Ответ №2:

Проблема не в вашем коде, а в программе, которую вы пытаетесь запустить. Очевидно, он использует консоль.Ключ чтения, который не разрешен при перенаправлении стандартного ввода.

Из документации:

Исключения

Исключение недействительной операции

Свойство In перенаправляется из какого-либо потока, отличного от консоли.

Единственный способ избежать этой ошибки-избежать перенаправления ввода. Так что измените это

 RedirectStandardInput = true
 

к этому

 RedirectStandardInput = false
 

Комментарии:

1. тот же результат,вы могли бы попробовать