Назад | Перейти на главную страницу

Как обычный пользователь Windows может изменить свой пароль из командной строки?

В Windows Server 2008 R2 у меня есть стандартный (не администраторский) локальный пользователь (не учетная запись Active Directory, хотя сервер находится в домене), который имеет доступ к серверу только через PowerShell Remoting. Пользователь не может войти через RDP.

Я бы хотел, чтобы этот пользователь мог изменить свой пароль. Команда net user требует прав администратора, даже если пользователь пытается изменить свой пароль.

Как обычный пользователь может изменить свой пароль из командной строки?

Вот некоторый код PowerShell, чтобы делать то, что вы ищете, с учетными записями домена:

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$ADSystemInfo = New-Object -ComObject ADSystemInfo
$type = $ADSystemInfo.GetType()
$user = [ADSI] "LDAP://$($type.InvokeMember('UserName', 'GetProperty', $null, $ADSystemInfo, $null))"
$user.ChangePassword( $oldPassword, $newPassword)

Провайдер ASDI также поддерживает синтаксис WinNT://computername/username для ChangePassword() метод. В ADSystemInfo объект, однако, не будет работать для локальных учетных записей компьютера, поэтому просто модифицируйте приведенный выше код с помощью WinNT://... синтаксис не работает.

(Кто-нибудь хочет предложить редактирование с кодом, чтобы различать локальные и доменные учетные записи?)

Совершенно иначе, старый NetUserChangePassword API также будет работать с локальными (и доменными, если вы укажете доменное имя в синтаксисе NetBIOS):

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$MethodDefinition = @'
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
public static extern bool NetUserChangePassword(string domainname, string username, string oldPassword, string newPassword);
'@

$NetAPI32 = Add-Type -MemberDefinition $MethodDefinition -Name 'NetAPI32' -Namespace 'Win32' -PassThru

$NetAPI32::NetUserChangePassword('.', $env:username, $oldPassword, $newPassword)

Этот код предполагает, что вы меняете пароль на локальном компьютере («.»).

На самом деле в PowerShell это довольно просто:

([ADSI]'LDAP://CN=User,CN=Users,DC=domain').ChangePassword('currentpassword','newpassword')

Я безрезультатно попробовал оба приведенных выше ответа для изменения пароля локального администратора, который не присоединен к домену. Однако поиск комментариев дал то, что мне было нужно.

Для второй части принятого в настоящее время ответа вы хотите обновить подпись, чтобы использовать long вместо того bool возвращаемое значение, и их можно устранить на коды системных ошибок документы. Итак, вы получите:

param (
    [string]$oldPassword = $( Read-Host "Old password"),
    [string]$newPassword = $( Read-Host "New password")
)

$MethodDefinition = @'
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
public static extern **long** NetUserChangePassword(string domainname, string username, string oldPassword, string newPassword);
'@

$NetAPI32 = Add-Type -MemberDefinition $MethodDefinition -Name 'NetAPI32' -Namespace 'Win32' -PassThru

$NetAPI32::NetUserChangePassword('.', $env:username, $oldPassword, $newPassword)

Однако это не сработало для меня. Коды ошибок менялись от 86 до 2221, в зависимости от того, как я настроил параметры. Собирался сдаться и копаться в комментариях, и, наконец, добился успеха:

([ADSI]'WinNT://./USERNAME').ChangePassword("OLDPASS‌​", "NEWPASS")

Совершенно нелепо, что простая СМЕНА пароля локального администратора настолько сложна в Powershell. Если вы вообще храните защищенные строки в своей системе, то обновление пароля должно производиться с использованием старого пароля, иначе вы рискуете потерять возможность правильно расшифровать эти защищенные строки!