2

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.

5
  • Progress is a pipeline stream, just like Error. Does ConvertTo-MvmcVirtualHardDisk display a progress bar? If yes, you can attach and read the Progress stream Commented Dec 19, 2016 at 9:48
  • Thanks for your answer. It does diplay a progress-bar when run in Powershell. Can you guide me on how to achieve this? Commented Dec 19, 2016 at 9:49
  • 1
    Check this question. It shows how to listen for events on the Property stream Commented Dec 19, 2016 at 9:53
  • You'll want to check HadErrors after invoking. Commented Dec 19, 2016 at 9:54
  • Oh yes, of course @MathiasR.Jessen - noob failure. Thanks. Commented Dec 19, 2016 at 10:01

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

1 Comment

Sorry for late response. This answer definetily solved my issue, just forgot to accept it. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.