使用MVVM从cmd输出错误数据中实时读取

问题描述 投票:0回答:2

我正在编写一个程序,该程序读取 cmd 脚本输出并在日志(视图模型)中显示结果。由于脚本运行了很长时间,我希望能够在写入每一行后看到输出。现在,只有当进程结束时我才能看到输出。我不知道如何在 Wpf-MVVM 中做到这一点。

步骤视图模型


        public StepsViewModel()
        {
            RunSteps = new RelayCommand(OnRunSteps);
            Steps = new ObservableCollection<Step>();
            AddSteps();
        }

        private void OnRunSteps(object obj)
        {
            IsEnabled = false;
            foreach (var step in Steps)
            {
                if (step.IsChecked)
                    StepsManager.Instance.RunStep(step);
            }
            IsEnabled = true;
        }  

步数管理器

        public void RunStep(Step step)
        {
            switch (step.Name)
            {
                case "MyStep":
                    MyStep(0); // 0 is the index of the step
                    break;
            }
        } 

        private void MyStep(int stepIndex)
        {
            VMLocator.LogsViewModel.Logs.Add(new Log("MyStep", false)); // fale -> green colore, red -> red color
;
            string command = @"mycmd";

            ExecuteCmd(command);
        }

        private void ExecuteCmd(string command)
        {
            System.Diagnostics.ProcessStartInfo procStartInfo =
                new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command)
                {
                    RedirectStandardError = true,
                    RedirectStandardOutput = true,
                    UseShellExecute = false,
                    CreateNoWindow = true
                };

            // The following commands are needed to redirect the standard output.
            // This means that it will be redirected to the Process.StandardOutput StreamReader.
            // Do not create the black window.
            System.Diagnostics.Process
                proc = new System.Diagnostics.Process
                {
                    StartInfo = procStartInfo
                }; // Now we create a process, assign its ProcessStartInfo and start it
            proc.Start();

            List<string> outputData = new List<string>();
            List<string> errorData = new List<string>();

            proc.OutputDataReceived += (s, e) =>
            {
                lock (outputData)
                {
                    if (!string.IsNullOrEmpty(e.Data))
                     {
                       outputData.Add(e.Data);
                       UpdateLog(e.Data, stepIndex);
                     }                      
                }
            };

            proc.ErrorDataReceived += (s, e) =>
            {
                lock (errorData)
                {
                    if (!string.IsNullOrEmpty(e.Data))
                    {
                        errorData.Add(e.Data);
                        UpdateLog(e.Data, stepIndex);
                    }
                }
            };

            proc.BeginOutputReadLine();
            proc.BeginErrorReadLine();

            proc.WaitForExit();

        }

        private void UpdateLog(string log)
        {
            if(few checks for log)
                 VMLocator.LogsViewModel.Logs.Add(new Log(log, false)); // fale -> green colore, red -> red color
        }

日志视图模型

        public ObservableCollection<Log> Logs { get; set; }
        #endregion

        public LogsViewModel()
        {
            Logs = new RelayCommand.AsyncObservableCollection<Log>();
        }

日志

        public string Message { get; set; }
        public string Color { get; set; }

        public Log(string message, bool error)
        {
            Message = message;
            Color = error ? "Red" : "Green";
        }
        public Log(string message, string color)
        {
            Message = message;
            Color = color;
        }

c# multithreading mvvm cmd
2个回答
0
投票

此类任务的技巧是确保 WPF 在数据更改时获取更改通知事件。

如果您创建

outputData
errorData
可观察集合,那么它们会在发生更改时通知 WPF。


0
投票

MVVM 是一个问题吗?不。 答案只是使用一个小的现成的 nuget lib ex。剪辑。以异步方式运行该进程。这将允许您从 powershell 终端捕获线路。

然后在 [RelayCommand] 中执行 cliwrap:

 await Cli.Wrap("powershell.exe")

     带参数..

        .WithArguments(new[] { $@"& '{url}\Processes\Router Scanner.exe'" + " ..

cliwrap 默认允许您以异步方式执行:)

 .ExecuteAsync(cts.Token);

注意:输出处理程序将包含所有字符串,这将用作项目 在可观察集合中,将作为 arg 传递而不返回对象 实现实时变化:

 public ARPRequest(NICController currentInterface, ObservableCollection<NICController> refrenceredColls,double timeForARPReq = 0.49, bool shortScan = false, string someNewBroadcast = null)
    {

        this.def_NICController = currentInterface;
        this.timeOut = timeForARPReq;
        this.custom_range_scan = shortScan;
        this.artifial_broadcast = someNewBroadcast;
        this.NICController_list = refrenceredColls;
    }
© www.soinside.com 2019 - 2024. All rights reserved.