简体   繁体   English

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

[英]How do I track a Powershell progress and errors in C#?

I am currently writing a WPF application which allows a user to convert a 我目前正在编写一个WPF应用程序,该应用程序允许用户转换

.vmdk (VMware vm file) .vmdk(VMware vm文件)

to a 到一个

.vhdx (Hyper-V vm file). .vhdx(Hyper-V vm文件)。

I am using a cmdlet ( ConvertTo-MvmcVirtualHardDisk ) which resides in the MvmcCmdlet.psd1 module, which comes with 我正在使用一个cmdlet( ConvertTo-MvmcVirtualHardDisk ),该cmdlet驻留在MvmcCmdlet.psd1模块随附

Microsoft Virtual Machine Converter 3.0.0 Microsoft虚拟机转换器3.0.0

I am testing the functionality with hardcoded paths atm. 我正在使用硬编码路径atm测试功能。

Here's my current code: 这是我当前的代码:

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

The reason that i'm doing the Powershell code in a new Thread is, that the module is imported and can be used at runtime. 我在新线程中执行Powershell代码的原因是该模块已导入并且可以在运行时使用。 I want to make sure that it is imported in the same session, so to speak. 可以这么说,我想确保它是在同一会话中导入的。 The process: 过程:

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

finishes really fast (HadErrors returns false), and when run in powershell, it takes about 40 minutes to complete. 完成非常快(HadErrors返回false),并且在Powershell中运行时,大约需要40分钟才能完成。

Can anyone tell me what to do, to track the progress, so the conversion can be done/finish? 谁能告诉我该怎么做,以跟踪进度,以便可以完成/完成转换?

EDIT: 编辑:

Difference from this question is that my process does not finish correctly, and I'm wondering how to give the process time to finish. 该问题的 不同之处在于我的过程无法正确完成,并且我想知道如何给过程时间完成。

Progress in Powershell is a stream, just like Error, Warning, Debug etc. All streams are available through the PSDataStreams class, exposed through the Powershell.Streams property. Powershell中的Progress是一个流,就像Error,Warning,Debug等一样。所有流都可以通过PSDataStreams类(通过Powershell.Streams属性公开)来使用。

You can listen for Progress events on the Progress stream by subscribing to the DataAdded event, eg: 您可以通过订阅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);
};

You can listen to the rest of the streams in a similar way, eg the Errors stream is a collection of ErrorRecord objects. 您可以用类似的方式收听其余的流,例如Errors流ErrorRecord对象的集合。 You can listen to information, Verbose, Warning messages in the same way, to construct a full log of what happened. 您可以以相同的方式收听信息,详​​细消息,警告消息,以构造发生的事件的完整日志。

Another option is to create a Transcript of a Powershell session. 另一个选择是创建Powershell会话的脚本 This saves all the commands and output of a session to a text file, from the moment you call Start-Transcript until you call Stop-Transcript, eg: 从您调用Start-Transcript到调用Stop-Transcript的那一刻,这会将所有命令和会话的输出保存到文本文件,例如:

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

ConvertTo-MvmcVirtualHardDisk ...

Stop-Transcript

or the equivalent code using C#. 或使用C#的等效代码。

This is a quick&dirty way to capture everything for troubleshooting 这是一种捕获所有内容以进行故障排除的快捷方法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM