如何使用 WMI 设置 Hyper-V 虚拟机的网络配置?

问题描述 投票:0回答:1

我正在使用Delphi开发WMI,目标是使用WMI设置VM IP。但 PUT 上出了点问题。

ConnectServer 功能正在以管理员身份连接到本地 Hyper-V 主机。

已经使用以下代码成功使用 powershell:

    Invoke-Command -ComputerName $VMhost -ArgumentList $IPaddress, $Mask, $Gatew, $VMname  -ScriptBlock {

        [string]$VMname = $args[3]

        $VMManServ =  Get-WmiObject -Namespace root\virtualization\v2 -Class Msvm_VirtualSystemManagementService

        $vm = Get-WmiObject -Namespace 'root\virtualization\v2' -Class 'Msvm_ComputerSystem' | Where-Object { $_.ElementName -eq $VMname }

        $vmSettings = $vm.GetRelated('Msvm_VirtualSystemSettingData') | Where-Object { $_.VirtualSystemType -eq 'Microsoft:Hyper-V:System:Realized' } 

        $nwAdapters = $vmSettings.GetRelated('Msvm_SyntheticEthernetPortSettingData') 

        $ipstuff = $nwAdapters.getrelated('Msvm_GuestNetworkAdapterConfiguration')

        $ipstuff.DHCPEnabled = $false
        $ipstuff.DNSServers = $args[2]
        $ipstuff.IPAddresses = $args[0]
        $ipstuff.Subnets = $args[1]
        $ipstuff.DefaultGateways = $args[2]

        $VMManServ.SetGuestNetworkAdapterConfiguration($VM, $ipstuff.GetText(1))
    }

现在我正在研究一个与delphi应用程序集成的解决方案。 运行后,应用程序显示成功,但虚拟机没有任何反应

procedure TForm2.SetNetworkAdapterConfiguration;
var
  FSWbemLocator: ISWbemLocator;
  FWMIService: ISWbemServices;
  FWbemObjectSet: ISWbemObjectSet;
  NetworkAdapterConfig: ISWbemObject;
  ReturnValue: ISWbemObjectPath;
begin
  try
    FSWbemLocator := CoSWbemLocator.Create;
    FWMIService := FSWbemLocator.ConnectServer('', 'root\virtualization\v2', '', '', '', '', 0, nil);

    FWbemObjectSet := FWMIService.ExecQuery('SELECT * FROM Msvm_GuestNetworkAdapterConfiguration WHERE InstanceID = "Microsoft:GuestNetwork\\CE89678D-73B0-4957-B7BF-73A42ABEDB52\\4FC2700C-A2F3-438A-80FB-078FDB33E67D"', 'WQL', 0, nil);

    if not Assigned(FWbemObjectSet) or (FWbemObjectSet.Count = 0) then
    begin
      ShowMessage('Config not found.');
      Exit;
    end;


    NetworkAdapterConfig := FWbemObjectSet.ItemIndex(0) as ISWBemObject;
     Log1(FWbemObjectSet.ItemIndex(0).GetObjectText_(1));

    NetworkAdapterConfig.Properties_.Item('DHCPEnabled', 0).Set_Value(OleVariant(False));
    NetworkAdapterConfig.Properties_.Item('DNSServers', 0).Set_Value(VarArrayOf(['8.8.8.8']));
    NetworkAdapterConfig.Properties_.Item('IPAddresses', 0).Set_Value(VarArrayOf(['192.168.0.199']));
    NetworkAdapterConfig.Properties_.Item('Subnets', 0).Set_Value(VarArrayOf(['255.255.255.0']));
    NetworkAdapterConfig.Properties_.Item('DefaultGateways', 0).Set_Value(VarArrayOf(['192.168.0.1']));

    Log2(NetworkAdapterConfig.GetObjectText_(1));

    ReturnValue := NetworkAdapterConfig.Put_(1, nil);
    ShowMessage('Success.');
    Log3(ISWbemObjectPathVarDump(ReturnValue));
  except
    on E: Exception do
      ShowMessage('Error: ' + E.Message);
  end;
end;

日志结果:

Log1;

instance of Msvm_GuestNetworkAdapterConfiguration
{
    DefaultGateways = {"192.168.0.1"};
    DHCPEnabled = TRUE;
    DNSServers = {"192.168.0.15"};
    InstanceID = "Microsoft:GuestNetwork\\CE89678D-73B0-4957-B7BF-73A42ABEDB52\\4FC2700C-A2F3-438A-80FB-078FDB33E67D";
    IPAddresses = {"192.168.0.162"};
    IPAddressOrigins = {1};
    ProtocolIFType = 4096;
    Subnets = {"255.255.255.0"};
};


Log2;

instance of Msvm_GuestNetworkAdapterConfiguration
{
    DefaultGateways = {"192.168.0.1"};
    DHCPEnabled = FALSE;
    DNSServers = {"8.8.8.8"};
    InstanceID = "Microsoft:GuestNetwork\\CE89678D-73B0-4957-B7BF-73A42ABEDB52\\4FC2700C-A2F3-438A-80FB-078FDB33E67D";
    IPAddresses = {"192.168.0.199"};
    IPAddressOrigins = {1};
    ProtocolIFType = 4096;
    Subnets = {"255.255.255.0"};
};

Log3 Put_ result as ISWbemObjectPath;
\\.\root\virtualization\v2:Msvm_GuestNetworkAdapterConfiguration.InstanceID="Microsoft:GuestNetwork\\CE89678D-73B0-4957-B7BF-73A42ABEDB52\\4FC2700C-A2F3-438A-80FB-078FDB33E67D"
RelPath : Msvm_GuestNetworkAdapterConfiguration.InstanceID="Microsoft:GuestNetwork\\CE89678D-73B0-4957-B7BF-73A42ABEDB52\\4FC2700C-A2F3-438A-80FB-078FDB33E67D"
Server : .
Namespace : root\virtualization\v2
ParentNamespace : root\virtualization
DisplayName : WINMGMTS:{authenticationLevel=pktPrivacy,impersonationLevel=impersonate}!\\.\root\virtualization\v2:Msvm_GuestNetworkAdapterConfiguration.InstanceID="Microsoft:GuestNetwork\\CE89678D-73B0-4957-B7BF-73A42ABEDB52\\4FC2700C-A2F3-438A-80FB-078FDB33E67D"
Class_ : Msvm_GuestNetworkAdapterConfiguration
Locale : 
Authority : 

编辑:DHCP 不是一个选项,我必须在没有 dhcp 服务器的情况下动态指定现有计算机的 ip 和 vlan。

编辑2:https://learn.microsoft.com/en-us/windows/win32/wmisdk/swbemobject-put-

objObjectPath = .Put_( _
  [ ByVal iFlags ], _
  [ ByVal objwbemNamedValueSet ] _
)

查看文档,发现一些关于put_的参数:

wbemChangeFlagUpdateOnly(1(0x1))

  • 导致此调用更新。类或实例必须存在才能调用成功。

objwbemNamedValueSet [输入,可选]

  • 通常,这是未定义的。否则,这是一个 SWbemObjectPath 对象,其元素表示可由为请求提供服务的提供者使用的上下文信息。支持或需要此类信息的提供者必须记录可识别的值名称、值的数据类型、允许的值和语义。

返回值objObjectPath 如果调用成功,则返回 SWbemObjectPath 对象。该对象包含已成功提交到 WMI 的实例或类的对象路径。

通过var dump put_返回的对象,他返回了一个完全限定的SWbemObjectPath,查看上面的Log3;

不幸的是仍然没有应用到虚拟机

编辑4

通过跟踪WMI-Activity,我可以看到Hyper-V服务器上正在执行put事件Start IWbemServices::PutInstance

    - <Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
- <System>
  <Provider Name="Microsoft-Windows-WMI-Activity" Guid="{1418ef04-b0b4-4623-bf7e-d74ab47bbdaa}" /> 
  <EventID>11</EventID> 
  <Version>0</Version> 
  <Level>4</Level> 
  <Task>0</Task> 
  <Opcode>0</Opcode> 
  <Keywords>0x8000000000000000</Keywords> 
  <TimeCreated SystemTime="2024-05-02T23:35:42.7638600Z" /> 
  <EventRecordID>65</EventRecordID> 
  <Correlation ActivityID="{1420ec18-2615-476a-bf58-c7fae612f136}" /> 
  <Execution ProcessID="1748" ThreadID="3556" /> 
  <Channel>Microsoft-Windows-WMI-Activity/Trace</Channel> 
  <Computer>HP006-SRV.MY_FQDN.com</Computer> 
  <Security /> 
  </System>
- <UserData>
- <Operation_New xmlns="http://manifests.microsoft.com/win/2006/windows/WMI">
  <CorrelationId>{00000000-0000-0000-0000-000000000000}</CorrelationId> 
  <GroupOperationId>335934</GroupOperationId> 
  <OperationId>335952</OperationId> 
  <Operation>Start IWbemServices::PutInstance - root\virtualization\v2 : Msvm_GuestNetworkAdapterConfiguration.InstanceID="Microsoft:GuestNetwork\\CE89678D-73B0-4957-B7BF-73A42ABEDB52\\4FC2700C-A2F3-438A-80FB-078FDB33E67D"</Operation> 
  <ClientMachine>NOTEHP-SRV</ClientMachine> 
  <ClientMachineFQDN>HP006-SRV.MY_FQDN.com</ClientMachineFQDN> 
  <User>MYDOMAIN\MY_USERNAME</User> 
  <ClientProcessId>3852</ClientProcessId> 
  <ClientProcessCreationTime>133591663144112869</ClientProcessCreationTime> 
  <NamespaceName>\\.\root\virtualization\v2</NamespaceName> 
  <IsLocal>true</IsLocal> 
  </Operation_New>
  </UserData>
  </Event>
powershell delphi wmi
1个回答
0
投票

解决方案是遵循 powershell 脚本的流程,并使用 ISWbemObjectEx 对象。

FSWbemLocator := CoSWbemLocator.Create;
FWMIService := FSWbemLocator.ConnectServer('', nameSpace.text, '', '', '', '', 0, nil)   ;


FWbemObjectSet := FWMIService.ExecQuery('SELECT * FROM Msvm_VirtualSystemManagementService', 'WQL', 0, nil);
FWbemObjectSet2 := FWMIService.ExecQuery('SELECT * FROM Msvm_GuestNetworkAdapterConfiguration WHERE InstanceID LIKE "'+NetworkID.text+'"', 'WQL', 0, nil);
FWbemObjectSet3 := FWMIService.ExecQuery('SELECT * FROM Msvm_ComputerSystem WHERE ElementName LIKE "'+vmName.Text+'"', 'WQL', 0, nil);

VSMS        := FWbemObjectSet.ItemIndex(0)  as ISWbemObject;
NetAdapter  := FWbemObjectSet2.ItemIndex(0) as ISWbemObjectEx;
VM          := FWbemObjectSet3.ItemIndex(0) as ISWbemObject;

NetAdapter.Properties_.Item('IPAddresses', 0).Set_Value(VarArrayOf([IPAddress.Text]));

NetworkConfigurationArray := VarArrayCreate([0, 0], varOleStr);
NetworkConfigurationArray[0] := NetAdapter.GetText_(1,0,nil);

InParameters := VSMS.Methods_.Item('SetGuestNetworkAdapterConfiguration',0).InParameters.SpawnInstance_(0);
InParameters.Properties_.Item('ComputerSystem', 0).Set_Value(VM.Path_.Path);
InParameters.Properties_.Item('NetworkConfiguration',0).Set_Value(NetworkConfigurationArray);

VSMS.ExecMethod_('SetGuestNetworkAdapterConfiguration', InParameters, 0, nil);
© www.soinside.com 2019 - 2024. All rights reserved.