简体   繁体   中英

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

.vmdk (VMware vm file)

to a

.vhdx (Hyper-V vm file).

I am using a cmdlet ( ConvertTo-MvmcVirtualHardDisk ) which resides in the MvmcCmdlet.psd1 module, which comes with

Microsoft Virtual Machine Converter 3.0.0

I am testing the functionality with hardcoded paths 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. 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.

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.

You can listen for Progress events on the Progress stream by subscribing to the DataAdded event, eg:

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. 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. 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 -OutputDirectory 'c:\mylogs' -noclobber -IncludeInvocationHeader

ConvertTo-MvmcVirtualHardDisk ...

Stop-Transcript

or the equivalent code using C#.

This is a quick&dirty way to capture everything for troubleshooting

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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