我正在编写一个程序,该程序读取 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;
}
此类任务的技巧是确保 WPF 在数据更改时获取更改通知事件。
如果您创建
outputData
和 errorData
可观察集合,那么它们会在发生更改时通知 WPF。
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;
}