0

我正在尝试重定向 dotnet-counter 的输出以显示到 Web 应用程序,但是抛出了无效异常,这是我的代码:

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();

当进程启动时,会从标准输出中读取一条错误消息:

未处理的异常:System.InvalidOperationException:当任一应用程序没有控制台或控制台输入已从文件重定向时,无法查看是否按下了键。试试 Console.In.Peek

似乎标准输出无法以这种方式重定向,有什么想法吗?

4

2 回答 2

1

除了重定向工具的输出之外,还有另一种方法。该dotnet-counters工具使用EventCounter引擎盖下的类(source)。这些值由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();
    }

上面的代码显示了原始输出:

有效负载:{名称:“cpu-usage”,DisplayName:“CPU使用率”,平均值:0,标准偏差:0,计数:1,最小值:0,最大值:0,IntervalSec:1.0001626,系列:“Interval = 1000”, CounterType:"Mean", Metadata:"", DisplayUnits:"%" }
Payload: { Name:"working-set", DisplayName:"Working Set", Mean:54, StandardDeviation:0, Count:1, Min:54 , Max:54, IntervalSec:1.0001626, Series:"Interval=1000", CounterType:"Mean", Metadata:"", DisplayUnits:"MB" }
Payload: { Name:"gc-heap-size", DisplayName:" GC 堆大小”,平均值:1,标准偏差:0,计数:1,最小值:1,最大值:1,IntervalSec:1.0001626,系列:“间隔 = 1000”,计数器类型:“平均值”,元数据:“”,显示单位: "MB" }
有效负载:{名称:“gen-0-gc-count”,DisplayName:“Gen 0 GC 计数”,DisplayRateTimeScale:“00:01:00”,增量:1,IntervalSec:1.0001626,元数据:“”,系列:“ Interval=1000", CounterType:"Sum", DisplayUnits:"" }
Payload: { Name:"gen-1-gc-count", DisplayName:"Gen 1 GC Count", DisplayRateTimeScale:"00:01:00", Increment:0, IntervalSec:1.0001626, Metadata:"", Series:"Interval=1000", CounterType:"Sum", DisplayUnits:"" }
Payload: { Name:"gen-2-gc-count", DisplayName:" Gen 2 GC 计数”,DisplayRateTimeScale:“00:01:00”,增量:0,IntervalSec:1.0001626,元数据:“”,系列:“Interval=1000”,CounterType:“Sum”,DisplayUnits:“”}

于 2021-08-27T21:15:36.027 回答
0

问题不在于您的代码,而在于您尝试启动的程序。显然它使用Console.ReadKey,当标准输入被重定向时这是不允许的。

从文档中:

例外

无效操作异常

In 属性是从控制台以外的某个流重定向的。

避免此错误的唯一方法是避免重定向输入。所以改变这个

RedirectStandardInput = true

对此

RedirectStandardInput = false
于 2021-08-27T19:04:56.747 回答