在 CIMInstance 中转换参数
Casting parameters inside CIMInstance
我正在尝试使用 Hyper-V WMI 界面,并尝试使用 C# 创建我的一个本地 Hyper-V VM 的快照。我试图在不使用 System.Management 的情况下执行此操作。相反,我使用 Microsoft.Management.Infrastructure。这样做的原因是它在 .NET Core 上受支持。此外,System.Management.Infrastructure 似乎是 System.Management.
的预期替代品
我无法将正确的参数传递给 CIM_VirtualSystemSnapshotService class.
上的 "CreateSnapshot" 方法的正确参数
输入参数列表:
uint32 CreateSnapshot( [in] CIM_ComputerSystem REF
AffectedSystem, [in] string
SnapshotSettings, [in] uint16
SnapshotType, [in, out] CIM_VirtualSystemSettingData REF
ResultingSnapshot, [out] CIM_ConcreteJob REF Job );
但是,这里并没有说明哪些是必须的,是否可以传递NULL值等等
我正在尝试使用的 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!");
}
这给出了错误 "Invalid parameter"。很难具体。
我已经尝试在 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 }
这给出了这个错误:
Invoke-CimMethod : Type mismatch for parameter "AffectedSystem" At
line:1 char:1
+ Invoke-CimMethod -ClassName "Msvm_VirtualSystemSnapshotService" -Meth ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (root\virtualiza...SnapshotService :String) [Invoke-CimMethod],
CimException
+ FullyQualifiedErrorId : HRESULT 0x80041005,Microsoft.Management.Infrast
ructure.CimCmdlets.InvokeCimMethodCommand
所以,看起来该方法需要 CIM_ComputerSystem。但是,我将它传递给 Msvm_ComputerSystem。
在 C# 中,它是 "just" 另一个 CIMInstance。所以,我不能从一个 class 转换到另一个,就像我可以使用 "normal" classes.
有什么方法可以让我 "cast" 把 Msvm_ComputerSystem 变成 CIM_ComputerSystem 吗?或者,我是在追大红鲱鱼吗?
好吧,我花了一段时间才找到时间再次处理这个问题。
终于解决了
CIM/WMI 框架中的某些功能似乎与您预期的有点不同。
最终的解决方案是"easy"。在对 CimMethodParameter.Create 的调用中,可以提供 CimType。将其设置为正确的值,该方法将起作用。任何偏差都会立即导致 "Invalid parameter" 或 "Not found"。例如,传递 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();
}
}
}
我正在尝试使用 Hyper-V WMI 界面,并尝试使用 C# 创建我的一个本地 Hyper-V VM 的快照。我试图在不使用 System.Management 的情况下执行此操作。相反,我使用 Microsoft.Management.Infrastructure。这样做的原因是它在 .NET Core 上受支持。此外,System.Management.Infrastructure 似乎是 System.Management.
的预期替代品我无法将正确的参数传递给 CIM_VirtualSystemSnapshotService class.
上的 "CreateSnapshot" 方法的正确参数输入参数列表:
uint32 CreateSnapshot( [in] CIM_ComputerSystem REF AffectedSystem, [in] string
SnapshotSettings, [in] uint16
SnapshotType, [in, out] CIM_VirtualSystemSettingData REF ResultingSnapshot, [out] CIM_ConcreteJob REF Job );
但是,这里并没有说明哪些是必须的,是否可以传递NULL值等等
我正在尝试使用的 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!");
}
这给出了错误 "Invalid parameter"。很难具体。
我已经尝试在 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 }
这给出了这个错误:
Invoke-CimMethod : Type mismatch for parameter "AffectedSystem" At line:1 char:1 + Invoke-CimMethod -ClassName "Msvm_VirtualSystemSnapshotService" -Meth ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidType: (root\virtualiza...SnapshotService :String) [Invoke-CimMethod], CimException + FullyQualifiedErrorId : HRESULT 0x80041005,Microsoft.Management.Infrast
ructure.CimCmdlets.InvokeCimMethodCommand
所以,看起来该方法需要 CIM_ComputerSystem。但是,我将它传递给 Msvm_ComputerSystem。 在 C# 中,它是 "just" 另一个 CIMInstance。所以,我不能从一个 class 转换到另一个,就像我可以使用 "normal" classes.
有什么方法可以让我 "cast" 把 Msvm_ComputerSystem 变成 CIM_ComputerSystem 吗?或者,我是在追大红鲱鱼吗?
好吧,我花了一段时间才找到时间再次处理这个问题。
终于解决了
CIM/WMI 框架中的某些功能似乎与您预期的有点不同。
最终的解决方案是"easy"。在对 CimMethodParameter.Create 的调用中,可以提供 CimType。将其设置为正确的值,该方法将起作用。任何偏差都会立即导致 "Invalid parameter" 或 "Not found"。例如,传递 int 而不是 uint8 会导致错误。
另外,似乎没有必要预先定义输出变量。输出由从 InvokeMethod 返回的 CimMethodResult 对象返回。
我在下面包含了完整的程序。在 运行.
之前从 Nuget 安装 Microsoft.Management.Infrastructureusing 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();
}
}
}