c# - 如何在 C# 中跟踪 Powershell 进度和错误?

标签 c# wpf powershell vmware hyper-v

我目前正在编写一个允许用户转换的 WPF 应用程序

.vmdk (VMware vm file)

到一个

.vhdx (Hyper-V vm file).

我正在使用一个 cmdlet (ConvertTo-MvmcVirtualHardDisk),它驻留在 MvmcCmdlet.psd1 模块中,它与

Microsoft Virtual Machine Converter 3.0.0

我正在使用硬编码路径 atm 测试功能。

这是我当前的代码:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Threading;
using System.Windows;

namespace PowershellTestArea
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    private string output { get; set; }

    public MainWindow()
    {
        InitializeComponent();
    }

    private void Button_OnClick(object sender, RoutedEventArgs e)
    {
        new Thread(() =>
        {
            Runspace rs = RunspaceFactory.CreateRunspace();
            rs.ThreadOptions = PSThreadOptions.UseCurrentThread;
            rs.Open();

            PowerShell ps = PowerShell.Create();

            ps.Runspace = rs;

            ps.AddCommand("Import-Module", true).AddParameter("Name", @"C:\Program Files\Microsoft Virtual Machine Converter\MvmcCmdlet.psd1");
            ps.Invoke();

            Debug.WriteLine(ps.HadErrors);

            Thread.Sleep(3000);

            ps.AddCommand("ConvertTo-MvmcVirtualHardDisk")
            .AddParameter("–SourceLiteralPath", @"'C:\VM\Windows 7 x64.vmdk'")
            .AddParameter("-VhdFormat", "Vhdx");
            Debug.WriteLine(ps.HadErrors);
            ps.BeginInvoke();

            IAsyncResult asyncResult = ps.BeginInvoke<PSObject, PSObject>(null, output);

            while (!asyncResult.IsCompleted)
            {
                Debug.WriteLine("Running...");
            }

            Debug.WriteLine(ps.Streams.Error.ToString());

            rs.Close();

        }).Start();
    }
}
}

我在新线程 中执行 Powershell 代码的原因是,该模块已导入并且可以在运行时使用。我想确保它是在同一个 session 中导入的,可以这么说。 过程:

ps.AddCommand("ConvertTo-MvmcVirtualHardDisk")
            .AddParameter("–SourceLiteralPath", @"'C:\VM\Windows 7 x64.vmdk'")
            .AddParameter("-VhdFormat", "Vhdx");
            Debug.WriteLine(ps.HadErrors);
            ps.BeginInvoke();

完成速度非常快(HadErrors 返回 false),在 powershell 中运行时,大约需要 40 分钟才能完成。

谁能告诉我该怎么做,跟踪进度,以便完成/完成转换?

编辑:

不同于 this question是我的进程没有正确完成,我想知道如何给进程时间来完成。

最佳答案

Powershell 中的进度是一个流,就像错误、警告、调试等一样。所有流都可以通过 PSDataStreams 获得。类,通过 Powershell.Streams 公开属性(property)。

您可以通过订阅 DataAdded 事件来监听 Progress 流上的 Progress 事件,例如:

ps.Streams.Progress.DataAdded += (sender,args) => {
    var records = (PSDataCollection<ProgressRecord>)sender;
    var current=records[args.Index];
    Console.WriteLine("VM conversion is {0} percent complete", current.PercentComplete);
};

您可以用类似的方式收听其余的流,例如 Errors streamErrorRecord 的集合对象。您可以以相同的方式收听信息、详细信息、警告消息,以构建所发生事件的完整日志。

另一种选择是创建一个 Transcript Powershell session 。这会将 session 的所有命令和输出保存到文本文件中,从您调用 Start-Transcript 到调用 Stop-Transcript,例如:

Start-Transcript -OutputDirectory 'c:\mylogs' -noclobber -IncludeInvocationHeader

ConvertTo-MvmcVirtualHardDisk ...

Stop-Transcript

或使用 C# 的等效代码。

这是一种捕获所有问题以进行故障排除的快速而肮脏的方法

关于c# - 如何在 C# 中跟踪 Powershell 进度和错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41219718/

相关文章:

c# - Xamarin WCF BasicHttpBinding-未实现方法或操作

c# - 如何在按下按钮后刷新datagridview

windows - PowerShell boolean 表达式

c# - 卸载用户控件

wpf - 使用 MVVM 绑定(bind) ListBox CheckBox IsChecked

powershell - Invoke-Command脚本 block 中的变量存在问题

windows - 安排Powershell脚本每小时运行一次

c# - 'stream.ReadTimeout' 抛出 'System.InvalidOperationException' 类型的异常,将照片发送到 Telegram Bot

c# - 如何在 IIS 级别的 Asp.Net Core 中配置 MachineKey

WPF FlowDocument 缩放以适合页面