0

i am trying to pass the VM object of that powershell command:

Start-Vm -Vm <VirtualMachine>

I would like to do this by c# code. So i create a remote runspace and so on:

class RemotePowershell
{
    private const string SHELL_URI = "http://schemas.microsoft.com/powershell/Microsoft.PowerShell";
    private WSManConnectionInfo connectionInfo = null;

    public RemotePowershell(string hostname, string username, string livepassword)
    {

        SecureString password = new SecureString();
        foreach (char c in livepassword.ToCharArray()) { password.AppendChar(c); }
        password.MakeReadOnly();

        PSCredential creds = new PSCredential(string.Format("{0}\\{1}", hostname, username), password);

        var targetWsMan = new Uri(string.Format("http://{0}:5985/wsman", hostname));
        connectionInfo = new WSManConnectionInfo(targetWsMan, SHELL_URI, creds);
        connectionInfo.OperationTimeout = 4 * 60 * 1000; // 4 minutes.
        connectionInfo.OpenTimeout = 1 * 60 * 1000; // 1 minute.
        connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Negotiate;       
    }


    public void RunScript(string scriptText, Collection<CommandParameter> parametters)
    {
        using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
        {
            runspace.Open();

            using (PowerShell ps = PowerShell.Create())
            {
                ps.Runspace = runspace;
                ps.AddCommand(scriptText);
                ps.AddParameters(parametters);


                Collection<PSObject> results = ps.Invoke();    
            }
            runspace.Close();
        }

I run this with an extention method like this:

public static class PowershellExtentionMethods
{
    private static RemotePowershell powerShellSession = new RemotePowershell("HOSTNAME", "USERNAME", "PASSWORD");


    public static void PowershellExec(this string commands, Collection<CommandParameter> parameters)
    {
        powerShellSession.RunScript(commands, parameters);
    }
}

var cmd = "Start-VM";
Collection<CommandParameter> cpc = new Collection<CommandParameter>();
cpc.Add(new CommandParameter("Vm",this.vm));
cmd.PowershellExec(cpc);

And nothing append the vm don't start and code run without exception.

So i would like to know if i use the right technique to pass object to cmdlet...

If someone as an idea, he's welcome ;)

Paca
  • 95
  • 2
  • 10

1 Answers1

0

A couple of thoughts.. Your example looks ok, but what type of virtualization are you using? I'm guessing based on the example that you are using Hyper-V.

Things to check:

  • Server OS, if 2008 or 2008 R2, where is the command coming from System Center or a third party library? In either case, I didn't see a call to load the module with the Start-VM command. Make sure the cmdlet or function is available before you call it. If it is Server 2012, autoloading should handle loading the command, but you'll want to make sure the Hyper-V module is available on the box and loads into the session.
  • What is the type of "this.VM" that you are passing to Start-VM? Depending on which module you are using to manage VMs, the type of the object will matter.
  • What is the VM storage like? Is it local or on an SMB share? If it is on an SMB share, is the correct credential delegation in place?
Steven Murawski
  • 10,959
  • 41
  • 53