MikeBaz - MSFT
MikeBaz - MSFT

Reputation: 3258

Applying a snapshot in Hyper-V WMI V2 from C#

I am trying to replicate the following PowerShell in C#:

# Details from here are not particularly important but needed for full sample
$vms = gwmi -namespace "root\virtualization\v2" Msvm_ComputerSystem
$vm = $vms[3]
$snapshot = ($vm.GetRelated("Msvm_VirtualSystemSettingData") | Where { $_.ElementName -eq "SnapshotName" })[0]
# end unimportant 

$VMSS = Get-WMiObject -class Msvm_VirtualSystemSnapshotService -namespace root\virtualization\v2
$VMSS.ApplySnapshot($snapshot, $null)

This code works fine - the snapshot applies as expected.

I have no problem getting the Msvm_VirtualSystemSettingData instance or a Msvm_VirtualSystemSnapshostService instance in C#. However, I can't seem to get the call to ApplySnapshot right - no matter what I give it I get an InvalidOperationException. I'm using generated WMI code from Visual Studio for the call:

public uint ApplySnapshot(ref System.Management.ManagementPath Job, System.Management.ManagementPath Snapshot) {
    if ((isEmbedded == false)) {
        System.Management.ManagementBaseObject inParams = null;
        inParams = PrivateLateBoundObject.GetMethodParameters("ApplySnapshot");
        // following line has been through variations as well with no change -
        // commenting it out, setting to null
        inParams["Job"] = ((System.Management.ManagementPath)(Job)).Path;
        inParams["Snapshot"] = ((System.Management.ManagementPath)(Snapshot)).Path;
        System.Management.ManagementBaseObject outParams = PrivateLateBoundObject.InvokeMethod("ApplySnapshot", inParams, null);
        Job = ((System.Management.ManagementPath)(outParams.Properties["Job"].Value));
        return System.Convert.ToUInt32(outParams.Properties["ReturnValue"].Value);
    }
    else {
        return System.Convert.ToUInt32(0);
    }
}

I'm not sure what to pass for the Job parameter either, since we get a job back - it's very unusual to have a ref for that instead of an out but I've tried a bunch of different variations around that (including setting the parameter to null and not setting it at all) with no luck. I've also tried setting inParams[Job] to null with no luck for that either.

What should I change to make this work?

Upvotes: 1

Views: 1639

Answers (1)

Joe
Joe

Reputation: 66

I believe your problem is that you are passing in the job to start with when it is an outbound parameter. That parameter will return from the invocation. Something like..

ManagementBaseObject inParams = null;

inParams = PrivateLateBoundObject.GetMethodParameters("ApplySnapshot");
inParams["Snapshot"] = ((System.Management.ManagementPath)(Snapshot)).Path;

ManagementBaseObject outParams = PrivateLateBoundObject.InvokeMethod("ApplySnapshot", inParams, null);

// i left this as i assume this is vs generated though this isn't how i would normally
// get my jobs back.
Job = ((ManagementPath)(outParams.Properties["Job"].Value));

return Convert.ToUInt32(outParams.Properties["ReturnValue"].Value);

Upvotes: 2

Related Questions