如何使用 PowerShell 通过 WMI 更新 "ds_computer" class 上的 LDAP 属性
How can I update LDAP attributes on the "ds_computer" class through WMI using PowerShell
我无法在 root\directory\ldap[=37 中更新 ds_computer WMI class 的实例=] 命名空间 使用 PowerShell.
但是我是能够使用C#更新同一个实例。这是我的 工作 C# 代码:
string computerName = Environment.GetEnvironmentVariable("ComputerName");
var connectionOptions = new ConnectionOptions();
connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
connectionOptions.Authentication = AuthenticationLevel.PacketPrivacy;
connectionOptions.EnablePrivileges = true;
connectionOptions.Timeout = new TimeSpan(0, 0, 0, 5, 0);
var managementScope = new ManagementScope();
managementScope.Path.Server = computerName;
managementScope.Path.NamespacePath = @"\ROOT\directory\LDAP";
managementScope.Options = connectionOptions;
managementScope.Options.Context.Add("__ProviderArchitecture", 64);
managementScope.Connect();
var context = new ManagementNamedValueCollection();
context.Add("__PUT_EXT_PROPERTIES", new string[] {"DS_displayName"});
context.Add("__PUT_EXTENSIONS", true);
context.Add("__PUT_EXT_CLIENT_REQUEST", true);
var putOptions = new PutOptions();
putOptions.Context = context;
putOptions.UseAmendedQualifiers = false;
putOptions.Type = PutType.UpdateOnly;
string commandText = string.Format("SELECT * FROM ds_computer WHERE DS_name='{0}'", computerName);
var managementObjectSearcher = new ManagementObjectSearcher(managementScope, new ObjectQuery(commandText));
var managementObjectCollection = managementObjectSearcher.Get();
var managementObject = managementObjectCollection.Cast<ManagementObject>().FirstOrDefault();
managementObject.SetPropertyValue("DS_displayName", "cs-test");
managementObject.Put(putOptions);
将此代码转换为 PowerShell 会产生以下结果:
PS > $computerName = $env:COMPUTERNAME
PS > $connectionOptions = [System.Management.ConnectionOptions]::New()
PS > $connectionOptions.Impersonation = [System.Management.ImpersonationLevel]::Impersonate
PS > $connectionOptions.Authentication = [System.Management.AuthenticationLevel]::PacketPrivacy
PS > $connectionOptions.EnablePrivileges = $true
PS > $connectionOptions.Timeout = [System.TimeSpan]::New(0, 0, 0, 5, 0)
PS > $managementScope = [System.Management.ManagementScope]::New()
PS > $managementScope.Path.Server = $computerName
PS > $managementScope.Path.NamespacePath = "\ROOT\directory\LDAP"
PS > $managementScope.Options = $connectionOptions
PS > $managementScope.Options.Context.Add("__ProviderArchitecture", 64)
PS > $managementScope.Connect()
PS > $context = [System.Management.ManagementNamedValueCollection]::New()
PS > $context.Add("__PUT_EXT_PROPERTIES", @("DS_displayName"))
PS > $context.Add("__PUT_EXTENSIONS", $true)
PS > $context.Add("__PUT_EXT_CLIENT_REQUEST", $true)
PS > $putOptions = [System.Management.PutOptions]::New()
PS > $putOptions.Context = $context
PS > $putOptions.UseAmendedQualifiers = $false
PS > $putOptions.Type = [System.Management.PutType]::UpdateOnly
PS > $commandText = "SELECT * FROM ds_computer WHERE DS_name='$computerName'"
PS > $managementObjectSearcher = [System.Management.ManagementObjectSearcher]::New($managementScope, [System.Management.ObjectQuery]::New($commandText))
PS > $managementObjectCollection = $managementObjectSearcher.Get()
PS > $managementObject = [Linq.Enumerable]::FirstOrDefault([System.Management.ManagementObject[]]$managementObjectCollection)
PS > $managementObject.SetPropertyValue("DS_displayName", "ps-test")
PS > $managementObject.Put($putOptions)
Exception calling "Put" with "1" argument(s): "Value cannot be null.
Parameter name: pUnk"
At line:1 char:1
+ $managementObject.Put($putOptions)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
当然我宁愿能够简单地使用提供的 cmdlets Get-WmiObject/Set-WmiInstance,但不幸的是这也是失败,结果如下:
PS > $managementObject = Get-WmiObject -Namespace "root\directory\ldap" -Class "ds_computer" -Authentication PacketPrivacy -Impersonation Impersonate -EnableAllPrivileges -Filter "DS_name='$env:COMPUTERNAME'"
PS > Set-WmiInstance -InputObject $managementObject -PutType UpdateOnly -Arguments @{DS_displayName="cmdlet1-test"}
Set-WmiInstance : Generic failure
At line:1 char:1
+ Set-WmiInstance -InputObject $x -PutType UpdateOnly
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Set-WmiInstance], ManagementException
+ FullyQualifiedErrorId : SetWMIManagementException,Microsoft.PowerShell.Commands.SetWmiInstance
我也尝试使用 Get-CimInstance/Set-CimInstance cmdlet 并得到同样非常有用的 "Generic Failure" 消息:
PS > $cimInstance = Get-CimInstance -Namespace "ROOT\directory\LDAP" -ClassName "ds_computer" -Filter "DS_name='$env:COMPUTERNAME'"
PS > Set-CimInstance -InputObject $cimInstance -Property @{DS_displayName="cmdlet2-test"}
Set-CimInstance : Generic failure
At line:1 char:1
+ Set-CimInstance -InputObject $x -Property @{DS_displayName="cmdlet2-test"} -P ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (ds_computer (AD...tyDomainPCG...):CimInstance) [Set-CimInstance], CimException
+ FullyQualifiedErrorId : HRESULT 0x80041001,Microsoft.Management.Infrastructure.CimCmdlets.SetCimInstanceCommand
我明白了。问题出在我存储在 $context["__PUT_EXT_PROPERTIES"]
中的数组语法上
这不起作用:
$context.Add("__PUT_EXT_PROPERTIES", @("DS_displayName"))
虽然这有效:
$context.Add("__PUT_EXT_PROPERTIES", [string[]]("DS_displayName"))
因此,对于可能遇到此问题的任何其他人来说,这是一个完整的示例:
$context = [System.Management.ManagementNamedValueCollection]::New()
$context.Add("__PUT_EXT_PROPERTIES", [string[]]("DS_displayName"))
$context.Add("__PUT_EXTENSIONS", $true)
$context.Add("__PUT_EXT_CLIENT_REQUEST", $true)
$putOptions = [System.Management.PutOptions]::New()
$putOptions.Context = $context
$putOptions.UseAmendedQualifiers = $false
$putOptions.Type = [System.Management.PutType]::UpdateOnly
$managementObject = Get-WmiObject -Namespace "root\directory\ldap" -Class "ds_computer" -Filter "DS_name='$env:COMPUTERNAME'"
$managementObject.DS_displayName = "cmdlet-test"
$managementObject.Put($putOptions)
我无法在 root\directory\ldap[=37 中更新 ds_computer WMI class 的实例=] 命名空间 使用 PowerShell.
但是我是能够使用C#更新同一个实例。这是我的 工作 C# 代码:
string computerName = Environment.GetEnvironmentVariable("ComputerName");
var connectionOptions = new ConnectionOptions();
connectionOptions.Impersonation = ImpersonationLevel.Impersonate;
connectionOptions.Authentication = AuthenticationLevel.PacketPrivacy;
connectionOptions.EnablePrivileges = true;
connectionOptions.Timeout = new TimeSpan(0, 0, 0, 5, 0);
var managementScope = new ManagementScope();
managementScope.Path.Server = computerName;
managementScope.Path.NamespacePath = @"\ROOT\directory\LDAP";
managementScope.Options = connectionOptions;
managementScope.Options.Context.Add("__ProviderArchitecture", 64);
managementScope.Connect();
var context = new ManagementNamedValueCollection();
context.Add("__PUT_EXT_PROPERTIES", new string[] {"DS_displayName"});
context.Add("__PUT_EXTENSIONS", true);
context.Add("__PUT_EXT_CLIENT_REQUEST", true);
var putOptions = new PutOptions();
putOptions.Context = context;
putOptions.UseAmendedQualifiers = false;
putOptions.Type = PutType.UpdateOnly;
string commandText = string.Format("SELECT * FROM ds_computer WHERE DS_name='{0}'", computerName);
var managementObjectSearcher = new ManagementObjectSearcher(managementScope, new ObjectQuery(commandText));
var managementObjectCollection = managementObjectSearcher.Get();
var managementObject = managementObjectCollection.Cast<ManagementObject>().FirstOrDefault();
managementObject.SetPropertyValue("DS_displayName", "cs-test");
managementObject.Put(putOptions);
将此代码转换为 PowerShell 会产生以下结果:
PS > $computerName = $env:COMPUTERNAME
PS > $connectionOptions = [System.Management.ConnectionOptions]::New()
PS > $connectionOptions.Impersonation = [System.Management.ImpersonationLevel]::Impersonate
PS > $connectionOptions.Authentication = [System.Management.AuthenticationLevel]::PacketPrivacy
PS > $connectionOptions.EnablePrivileges = $true
PS > $connectionOptions.Timeout = [System.TimeSpan]::New(0, 0, 0, 5, 0)
PS > $managementScope = [System.Management.ManagementScope]::New()
PS > $managementScope.Path.Server = $computerName
PS > $managementScope.Path.NamespacePath = "\ROOT\directory\LDAP"
PS > $managementScope.Options = $connectionOptions
PS > $managementScope.Options.Context.Add("__ProviderArchitecture", 64)
PS > $managementScope.Connect()
PS > $context = [System.Management.ManagementNamedValueCollection]::New()
PS > $context.Add("__PUT_EXT_PROPERTIES", @("DS_displayName"))
PS > $context.Add("__PUT_EXTENSIONS", $true)
PS > $context.Add("__PUT_EXT_CLIENT_REQUEST", $true)
PS > $putOptions = [System.Management.PutOptions]::New()
PS > $putOptions.Context = $context
PS > $putOptions.UseAmendedQualifiers = $false
PS > $putOptions.Type = [System.Management.PutType]::UpdateOnly
PS > $commandText = "SELECT * FROM ds_computer WHERE DS_name='$computerName'"
PS > $managementObjectSearcher = [System.Management.ManagementObjectSearcher]::New($managementScope, [System.Management.ObjectQuery]::New($commandText))
PS > $managementObjectCollection = $managementObjectSearcher.Get()
PS > $managementObject = [Linq.Enumerable]::FirstOrDefault([System.Management.ManagementObject[]]$managementObjectCollection)
PS > $managementObject.SetPropertyValue("DS_displayName", "ps-test")
PS > $managementObject.Put($putOptions)
Exception calling "Put" with "1" argument(s): "Value cannot be null.
Parameter name: pUnk"
At line:1 char:1
+ $managementObject.Put($putOptions)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
当然我宁愿能够简单地使用提供的 cmdlets Get-WmiObject/Set-WmiInstance,但不幸的是这也是失败,结果如下:
PS > $managementObject = Get-WmiObject -Namespace "root\directory\ldap" -Class "ds_computer" -Authentication PacketPrivacy -Impersonation Impersonate -EnableAllPrivileges -Filter "DS_name='$env:COMPUTERNAME'"
PS > Set-WmiInstance -InputObject $managementObject -PutType UpdateOnly -Arguments @{DS_displayName="cmdlet1-test"}
Set-WmiInstance : Generic failure
At line:1 char:1
+ Set-WmiInstance -InputObject $x -PutType UpdateOnly
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Set-WmiInstance], ManagementException
+ FullyQualifiedErrorId : SetWMIManagementException,Microsoft.PowerShell.Commands.SetWmiInstance
我也尝试使用 Get-CimInstance/Set-CimInstance cmdlet 并得到同样非常有用的 "Generic Failure" 消息:
PS > $cimInstance = Get-CimInstance -Namespace "ROOT\directory\LDAP" -ClassName "ds_computer" -Filter "DS_name='$env:COMPUTERNAME'"
PS > Set-CimInstance -InputObject $cimInstance -Property @{DS_displayName="cmdlet2-test"}
Set-CimInstance : Generic failure
At line:1 char:1
+ Set-CimInstance -InputObject $x -Property @{DS_displayName="cmdlet2-test"} -P ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (ds_computer (AD...tyDomainPCG...):CimInstance) [Set-CimInstance], CimException
+ FullyQualifiedErrorId : HRESULT 0x80041001,Microsoft.Management.Infrastructure.CimCmdlets.SetCimInstanceCommand
我明白了。问题出在我存储在 $context["__PUT_EXT_PROPERTIES"]
这不起作用:
$context.Add("__PUT_EXT_PROPERTIES", @("DS_displayName"))
虽然这有效:
$context.Add("__PUT_EXT_PROPERTIES", [string[]]("DS_displayName"))
因此,对于可能遇到此问题的任何其他人来说,这是一个完整的示例:
$context = [System.Management.ManagementNamedValueCollection]::New()
$context.Add("__PUT_EXT_PROPERTIES", [string[]]("DS_displayName"))
$context.Add("__PUT_EXTENSIONS", $true)
$context.Add("__PUT_EXT_CLIENT_REQUEST", $true)
$putOptions = [System.Management.PutOptions]::New()
$putOptions.Context = $context
$putOptions.UseAmendedQualifiers = $false
$putOptions.Type = [System.Management.PutType]::UpdateOnly
$managementObject = Get-WmiObject -Namespace "root\directory\ldap" -Class "ds_computer" -Filter "DS_name='$env:COMPUTERNAME'"
$managementObject.DS_displayName = "cmdlet-test"
$managementObject.Put($putOptions)