更新实例的一部分

有时,你可能只想更新实例的一部分。 例如,某些实例具有大量属性。 如果必须要更新大量这些实例,则可能会降低系统性能。 因此,可以选择仅更新实例的一部分,从而减少必须向 WMI 发送以及从中检索的信息量。 但是,WMI 不直接支持部分实例操作,大多数提供程序也不直接支持。 因此,如果编写使用部分实例操作的应用程序,请做好调用失败的准备,并出现 C++ 中的 WBEM_E_PROVIDER_NOT_CAPABLE 或 WBEM_E_NOT_SUPPORTED 错误代码。 在脚本语言中,错误代码为 wbemErrProviderNotCapable 或 wbemErrNotSupported。

在脚本编写中,仅当在企业上大量对象中更新一两个可写属性时,才有必要使用此操作来帮助提高性能。 否则,对 SWbemObject.Put_SWbemObject.PutAsync_ 进行正常的 VBScript 调用虽然看上去是写入整个对象,实际上只是更新提供程序已启用写入的属性。

以下过程介绍如何使用 PowerShell 请求部分实例更新。

使用 PowerShell 请求部分实例更新

  1. 检索要更新的对象的路径。

    可以手动描述路径,也可以查询对象,然后检索 __Path 属性。

    $myWMIDrivePath = (get-wmiObject Win32_LogicalDisk -filter "Name = 'C:'").__Path
    #or
    $myWmiDrivePath = \\myComputer\root\cimv2:Win32_LogicalDisk.DeviceID="C:"
    
  2. 设置一个列出要更新的属性的名称的哈希表,并在调用 Set-WmiInstance 中使用此哈希表。

    $newDriveName = @{VolumeName = "OSDisk"}
    Set-WmiInstance -Path $myWMIDrivePath -Arguments $newDriveName
    

以下过程介绍如何使用 C# 请求部分实例更新。

注意

System.Management 是用于访问 WMI 的原始 .NET 命名空间;但是,此命名空间中的 API 通常较慢,并且相对于其更新式的 Microsoft.Management.Infrastructure 对应项,它们无法缩放。

 

使用 C# 请求部分实例更新

  1. 创建新的 ManagementObject 对象,该对象表示要更新的特定实例。

    using System.Management;
    ...
    ManagementObject myDisk = new ManagementObject("Win32_LogicalDisk.DeviceID='C:'");
    
  2. 通过调用 ManagementObject.SetPropertyValue 设置属性值。

    myDisk.SetPropertyValue("VolumeName", "OSDisk");
    

以下过程介绍如何使用 VBScript 请求部分实例更新。

使用 VBScript 请求部分实例更新

  1. 创建 SWbemNamedValueSet 上下文对象。

    Set objwbemNamedValueSet = CreateObject ("WbemScripting.SWbemNamedValueSet")
    
  2. 使用 SWbemNamedValueSet.Add 方法将 Put 扩展值 "__PUT_EXTENSIONS" 和 "__PUT_EXT_CLIENT_REQUEST" 添加到上下文对象。

    objwbemNamedValueSet.Add "__PUT_EXTENSIONS", True
    objwbemNamedValueSet.Add "__PUT_EXT_CLIENT_REQUEST", True
    
  3. 设置一个列出要更新的属性的名称的数组,并将此数组添加到 Put 扩展值为 "__PUT_EXT_PROPERTIES" 的 SWbemNamedValueSet 上下文对象。

    arProperties = Array("propertyname1", "propertyname2") 
    objwbemNamedValueSet.Add "__PUT_EXT_PROPERTIES", arProperties
    
  4. SWbemObject.Put_ 调用的 iFlags 参数设置为 wbemChangeFlagUpdateOnly。 如果没有此标志,调用将失败并显示上下文无效。

  5. 将标志和上下文对象传递到 SWbemObject.Put_SWbemObject.PutAsync_ 的 objwbemNamedValueSet 参数中的提供程序。

    call objSystem.put_( wbemChangeFlagUpdateOnly, objwbemNamedValueSet)
    

以下过程介绍如何使用 C++ 请求部分实例更新。

使用 C++ 请求部分实例更新

  1. 通过调用 CoCreateInstance 创建 IWbemContext 对象。

    上下文对象是 WMI 用于将更多信息传递给 WMI 提供程序的对象。 在这种情况下,你将使用 IWbemContext 对象来指示提供程序接受部分实例更新。

  2. 通过调用 IWbemContext::SetValue 将 "__PUT_EXTENSIONS" 和 "__PUT_EXT_CLIENT_REQUEST" 命名值添加到 IWbemContext 对象。

    下表列出了 "__PUT_EXTENSIONS" 和 "__PUT_EXT_CLIENT_REQUEST" 的含义。

    命名值 说明
    "__PUT_EXTENSIONS" VT_BOOL 设置为 VARIANT_TRUE。 一个值,该值指示已指定一个或多个其他上下文值。 这允许在提供程序内快速检查上下文对象,以确定是否正在使用部分实例更新。
    "__PUT_EXT_CLIENT_REQUEST" VT_BOOL 设置为 VARIANT_TRUE。 在初始请求期间由客户端设置。 此值用于防止重新进入错误。

     

  3. 根据需要通过再一次调用 IWbemContext::SetValue 将 __PUT_EXT_STRICT_NULLS、__PUT_EXT_PROPERTIES 或 __PUT_EXT_ATOMIC 通过任意组合添加到 IWbemContext 对象。

    下表列出了命名值的含义。

    命名值 说明
    "__PUT_EXT_STRICT_NULLS" VT_BOOL 设置为 VARIANT_TRUE。 指示客户端已有意将属性设置为 VT_NULL,并期望写入操作成功。 如果提供程序无法将值设置为 NULL,应会报告一个错误。
    "__PUT_EXT_PROPERTIES" 包含要更新的属性名称列表的字符串的 SAFEARRAY。 可以独立使用,也可与 "__PUT_EXT_PROPERTIES" 组合使用。 值位于正在写入的实例中。
    "__PUT_EXT_ATOMIC" VT_BOOL 设置为 VARIANT_TRUE。 指示所有更新必须同时成功(原子语义)或提供程序必须还原回来。 不能有部分成功。 可以独立使用,也可与其他标志组合使用。

     

  4. 将 iFlags 参数设置为 WBEM_FLAG_UPDATE_ONLY。 如果没有此标志,调用将失败并显示上下文无效。

  5. IWbemContext 上下文对象传入到 pCtx 参数中的任何 IWbemServices::PutInstanceIWbemServices::PutInstanceAsync 调用。

    传递 IWbemContext 对象会指示提供程序允许部分实例更新。 在完整实例更新中,将 pCtx 设置为 NULL。

    如果调用中存在的上下文对象不包含 "__PUT_EXTENSIONS",则提供程序可以写入任何必要的属性。 如果上下文对象中存在 "__PUT_EXTENSIONS",则 WMI 要求提供程序严格遵循操作的语义,否则调用失败。 有关详细信息,请参阅处理提供程序中的访问被拒绝消息