首页 > 解决方案 > 当我的计算机不是域的成员时,我作为非管理员如何使用 PowerShell 更改我的活动目录密码?

问题描述

我以非域用户身份登录笔记本电脑。

我使用 Open VPN 连接到远程网络,并且可以通过该 VPN 访问域资源,例如 CIFS 共享,方法是在出现提示时输入我的域凭据。

我想使用 PowerShell 在远程域上更改我的密码。

我将当前凭据存储为 $credentials,一个 System.Management.Automation.PSCredential 对象。

我将新密码存储为 $newPassword,一个安全字符串,

当我的计算机不是域的成员时,我作为非管理员如何使用 PowerShell 更改我的活动目录密码?

域的 FQDN d0-ad.domain.com 解析为域控制器 IP 地址。我已将 netbios 名称 NP-DOMAIN 添加到主机文件中,因此它也解析为域控制器。

这是我遇到问题的脚本部分:

Write-Verbose "Setting up DirectoryEntry object"
$DomainEntry = New-Object -TypeName System.DirectoryServices.DirectoryEntry "LDAP://$($netBiosName)" ,$credentials.UserName,$($credentials.GetNetworkCredential().password)

Write-Verbose "Setting up DirectorySearcher object"
$Searcher = New-Object -TypeName System.DirectoryServices.DirectorySearcher

$Searcher.SearchRoot = $DomainEntry

$userName = $($credentials.UserName).Replace("$($netBiosName)\","")
Write-Verbose "Username set as $($userName)"
$Searcher.Filter = "(samaccountname=$($userName))"

$user = $Searcher.FindOne()

$userObject = [ADSI]$user.Path

if ($userObject) {
    Write-Verbose "Changing password for user: $($user.Path)"
    $userObject.ChangePassword($credentials.GetNetworkCredential().password, [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($NewPassword)))
} else {
    Write-Verbose "User $($username) not found"
    throw "User $($username) not found"
}

问题发生在

$userObject = [ADSI]$user.Path

如果我尝试访问 $userObject 我收到错误:

格式默认:检索成员“distinguishedName”时发生以下异常:“发生本地错误。” + CategoryInfo:未指定:(:) [格式默认],ExtendedTypeSystemException + FullyQualifiedErrorId:CatchFromBaseGetMember,Microsoft.PowerShell.Commands.FormatDefaultCommand

我知道凭据是正确的,并且与目录的连接有效,因为 $Searcher.FindOne() 方法正确搜索、查找并返回正确的用户。

那么为什么我会收到“发生本地错误。”?

标签: powershellactive-directoryldapcredentialsldap-query

解决方案


该错误确实看起来很奇怪,但我认为这可能是因为您没有提供正确的凭据。[ADSI]类型加速器只是创建DirectoryEntry对象的简写。这[ADSI]$user.Path相当于DirectoryEntry在代码顶部创建一个类似的内容,除了没有用户名和密码。

这样你就可以:

  1. 像在文件顶部一样创建它:
$userObject = New-Object -TypeName System.DirectoryServices.DirectoryEntry $user.Path, $credentials.UserName, $($credentials.GetNetworkCredential().password)

或者,

  1. 调用. GetDirectoryEntry()_ SearchResult它返回的DirectoryEntry对象将具有与在其上设置的凭据相同的凭据SearchRoot
$userObject = $user.GetDirectoryEntry()

推荐阅读