【问题标题】:How to redirect the standard output of dotnet-counter tool by System.Diagnostics.Process?如何通过 System.Diagnostics.Process 重定向 dotnet-counter 工具的标准输出?
【发布时间】:2021-08-27 17:42:34
【问题描述】:

我正在尝试重定向 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

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

【问题讨论】:

  • 你问的是重定向输出;但错误是关于输入。去掉ReadLine()函数还能用吗?
  • @Felix 如果 BeginOutputReadLine 和 BeginErrorReadLine 被删除,输出不再可用
  • 等待 - 您的变量是 process,但您正在调用类 Process 上的函数。你不会得到编译错误吗? (我愿意)

标签: c# .net


【解决方案1】:

除了重定向工具的输出之外,还有另一种方法。 dotnet-counters 工具在后台使用 EventCounter 类 (source)。这些值由System.Runtimeevent 提供者在others 中发出。

好消息是这些计数器可以读取out-of-process,就像该工具一样。这意味着您可以编写自己的代码来监听这些计数器,并将它们显示在一个网页中,其中包含如下代码:

    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,间隔秒:1.0001626,系列:“间隔= 1000", CounterType:"Mean", Metadata:"", DisplayUnits:"%" }
有效负载:{名称:“工作集”,显示名称:“工作集”,平均值:54,标准偏差:0,计数:1,最小值:54,最大值:54,IntervalSec:1.0001626,系列:“Interval = 1000”, CounterType:"Mean", Metadata:"", DisplayUnits:"MB" }
有效负载:{名称:“gc-heap-size”,DisplayName:“GC堆大小”,平均值:1,StandardDeviation:0,Count:1,Min:1,Max:1,IntervalSec:1.0001626,系列:“Interval = 1000", CounterType:"Mean", Metadata:"", DisplayUnits:"MB" }
有效负载:{名称:“gen-0-gc-count”,DisplayName:“Gen 0 GC 计数”,DisplayRateTimeScale:“00:01:00”,增量:1,IntervalSec:1.0001626,元数据:“”,系列:“间隔=1000", CounterType:"Sum", DisplayUnits:"" }
有效负载:{名称:“gen-1-gc-count”,DisplayName:“Gen 1 GC 计数”,DisplayRateTimeScale:“00:01:00”,增量:0,IntervalSec:1.0001626,元数据:“”,系列:“间隔=1000", CounterType:"Sum", DisplayUnits:"" }
有效负载:{名称:“gen-2-gc-count”,DisplayName:“Gen 2 GC 计数”,DisplayRateTimeScale:“00:01:00”,增量:0,IntervalSec:1.0001626,元数据:“”,系列:“ Interval=1000", CounterType:"Sum", DisplayUnits:"" }

【讨论】:

    【解决方案2】:

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

    来自文档:

    例外情况

    InvalidOperationException

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

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

    RedirectStandardInput = true
    

    到这里

    RedirectStandardInput = false
    

    【讨论】:

    • 同样的结果,你可以试试
    猜你喜欢
    • 1970-01-01
    • 2014-10-11
    • 1970-01-01
    • 2011-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-20
    • 2011-12-08
    相关资源
    最近更新 更多