C# CIMInstance中的铸造参数

C# CIMInstance中的铸造参数,c#,wmi,hyper-v,cim,C#,Wmi,Hyper V,Cim,我正在使用Hyper-V WMI接口,并尝试使用C#创建我的一个本地Hyper-V VM的快照。我正在尝试在不使用系统管理的情况下执行此操作。相反,我使用的是Microsoft.Management.Infrastructure。原因是.NETCore上支持它。此外,System.Management.Infrastructure似乎是System.Management的预期替代品 我无法将正确的参数传递给CIM_VirtualSystemSnapshotService类上的“CreateSna

我正在使用Hyper-V WMI接口,并尝试使用C#创建我的一个本地Hyper-V VM的快照。我正在尝试在不使用系统管理的情况下执行此操作。相反,我使用的是Microsoft.Management.Infrastructure。原因是.NETCore上支持它。此外,System.Management.Infrastructure似乎是System.Management的预期替代品

我无法将正确的参数传递给CIM_VirtualSystemSnapshotService类上的“CreateSnapshot”方法的正确参数

这里有记录:

输入参数如下所示:

uint32创建快照([in]CIM_ComputerSystem REF 受影响的系统,[in]字符串
快照设置,[in]uint16
快照类型,[in,out]CIM_VirtualSystemSettingData REF 结果快照,[out]CIM_ConcreteJob REF Job)

但是,这并没有指定哪些是必需的,是否可以传递空值,等等

我尝试使用的C#方法是:

    public static void CreateSnapshot()
    {
        const string hvNamespace = @"root\virtualization\v2";

        var sessionOptions = new DComSessionOptions
        {
            Timeout = TimeSpan.FromSeconds(30)
        };

        var cimSession = CimSession.Create("localhost", sessionOptions);

        var vmSnapshotService = new CimInstance(cimSession.GetClass(hvNamespace, "CIM_VirtualSystemSnapshotService"));

        // CimInstance of CIM_ComputerSystem. QueryInstances returns Msvm_ComputerSystem
        var vm = cimSession.QueryInstances(hvNamespace, "WQL", $"SELECT * FROM CIM_ComputerSystem WHERE ElementName = 'Android'").First();

        var snapshotSettingDataClass = cimSession.GetClass(hvNamespace, "CIM_VirtualSystemSettingData");
        var snapshotSettingData = new CimInstance(snapshotSettingDataClass);

        var snapshotParameters = new CimMethodParametersCollection();
        snapshotParameters.Add(CimMethodParameter.Create("AffectedSystem", vm, CimFlags.In));
        snapshotParameters.Add(CimMethodParameter.Create("SnapshotSettings", "", CimFlags.In));
        snapshotParameters.Add(CimMethodParameter.Create("SnapshotType", 2, CimFlags.In));
        snapshotParameters.Add(CimMethodParameter.Create("ResultingSnapshot", snapshotSettingData, CimFlags.Out));

        cimSession.InvokeMethod(namespaceName: hvNamespace, instance: vmSnapshotService, methodName: "CreateSnapshot", methodParameters: snapshotParameters);
//Microsoft.Management.Infrastructure.CimException: 'Invalid parameter '

        Console.WriteLine($"Snapshot created!");
    }
这将导致错误“参数无效”。不太具体

我尝试在Powershell中重建此功能:

$session = New-CimSession
$hvNamespace = "root\virtualization\v2"
$snapshotservice = Get-CimClass -ClassName "CIM_VirtualSystemSnapshotService" -Namespace $hvNamespace
$vm = Get-CimInstance -Namespace $hvNamespace -Query "SELECT * FROM CIM_ComputerSystem WHERE ElementName = 'Android'" -QueryDialect WQL
Invoke-CimMethod -ClassName "Msvm_VirtualSystemSnapshotService" -MethodName "CreateSnapshot" -Namespace $hvNamespace -Arguments @{ "AffectedSystem" = $vm ; "SnapshotSettings" = "" ; "SnapshotType" = 2 }
这会产生以下错误:

调用CimMethod:处参数“AffectedSystem”的类型不匹配 行:1字符:1 +调用CimMethod-类名“Msvm_VirtualSystemSnapshotService”-方法。。。 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +CategoryInfo:InvalidType:(根\virtualiza…快照服务:字符串)[调用CimMethod], CimException +FullyQualifiedErrorId:HRESULT 0x80041005,Microsoft.Management.Infrast
structure.CimCmdlets.InvokeCimMethodCommand

因此,该方法似乎需要一个CIM_计算机系统。然而,我正在通过一个Msvm_计算机系统。 从C#,它“只是”另一个CIMInstance。所以,我不能像对待“普通”类那样,从一个类转换到另一个类


我有没有办法将Msvm_计算机系统“转换”为CIM_计算机系统?或者,我是在追求一条大的红鲱鱼吗?

好吧,我花了一段时间才找到时间再做这件事

我终于解决了

CIM/WMI框架中有些东西的工作方式似乎与您预期的有所不同

最终,解决方案是“简单的”。在调用CimMethodParameter.Create时,可以指定CimType。将该值设置为正确的值,该方法将起作用。任何偏差将立即导致“无效参数”或“未找到”。例如,传递int而不是uint8会导致错误

此外,似乎没有必要预先定义输出变量。输出由从InvokeMethod返回的CimMethodResult对象返回

我已经包括了下面的完整程序。运行前,从Nuget安装Microsoft.Management.Infrastructure

using System;
using System.Linq;
using Microsoft.Management.Infrastructure;
using Microsoft.Management.Infrastructure.Options;

namespace TestApp
{
    class Program
    {
        public static void CreateSnapshot()
        {
            const string hvNamespace = @"root\virtualization\v2";

            var sessionOptions = new DComSessionOptions
            {
                Timeout = TimeSpan.FromSeconds(30)
            };

            var cimSession = CimSession.Create("localhost", sessionOptions);

            // Get an instance of the VM to snapshot
            var vm = cimSession.QueryInstances(hvNamespace, "WQL", $"SELECT * FROM CIM_ComputerSystem WHERE ElementName = 'MyTestVM'").First();

            // Get the instance of Msvm_VirtualSystemSnapshotService. There is only one.
            var vmSnapshotService = cimSession.EnumerateInstances(hvNamespace, "Msvm_VirtualSystemSnapshotService").First();

            // Set the snapshot parameters by creating a Msvm_VirtualSystemSnapshotSettingData
            var snapshotSettings = new CimInstance("Msvm_VirtualSystemSnapshotSettingData");
            snapshotSettings.CimInstanceProperties.Add(CimProperty.Create("ConsistencyLevel", 1, CimType.UInt8, CimFlags.ReadOnly));
            snapshotSettings.CimInstanceProperties.Add(CimProperty.Create("IgnoreNonSnapshottableDisks", true, CimFlags.ReadOnly));

            // Put all of these things into a CimMethodParametersCollection.
            // Note; no need to specify the "Out" parameters. They will be returned by the call to InvokeMethod.
            var methodParameters = new CimMethodParametersCollection
            {
                CimMethodParameter.Create("AffectedSystem", vm, CimType.Reference, CimFlags.In),
                CimMethodParameter.Create("SnapshotSettings", snapshotSettings.ToString(), CimType.String, CimFlags.In),
                CimMethodParameter.Create("SnapshotType", 2, CimType.UInt16, CimFlags.In),
            };

            cimSession.InvokeMethod(hvNamespace, vmSnapshotService, "CreateSnapshot", methodParameters);

            Console.WriteLine($"Snapshot created!");
        }

        static void Main(string[] args)
        {
            CreateSnapshot();
            Console.ReadLine();
        }
    }
}

嘿,谢谢你。您知道如何查询现有快照了吗?快照是与VM关联的实例。因此,要查询它们,您可以使用类似cimSession.EnumerateAssociatedInstances(hvNameSpace,vm,…)的东西,其中“vm”是保存您的vm的CimInstance。您找到设置快照名称的方法了吗?老实说,没有。我已经尝试过,但似乎不起作用。作为一种解决方法,您可以在创建快照后立即获取并重命名它。