65.9K
CodeProject 正在变化。 阅读更多。
Home

如何在远程计算机上更改用户密码

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.48/5 (8投票s)

2006年5月29日

CPOL

2分钟阅读

viewsIcon

87365

downloadIcon

4789

密码更改器 - 用于远程更改用户密码的可重用工具。

Password Changer screenshot

引言

这是我在 CodeProject 上的第一篇文章。所以请不要期望太高。 ;-)

给定的场景

一台运行 Windows 2000 的旧工作站充当 "文件服务器"。用户可以通过使用用户名和密码连接来访问网络上的共享文件夹。不幸的是,在工作组环境中,没有内置的方法可以从远程计算机更改这些本地用户的密码。

要解决的任务

描述的问题可以分为三个主要部分

  1. 如何获取我们工作组中所有计算机的列表?
  2. 如何获取特定计算机上所有用户的列表?
  3. 如何在远程计算机上更改用户密码?

API 是您的朋友

在 MSDN 中提到了三个相应的网络管理功能。它们的使用得到了很好的解释,所以我不会重复 MSDN 的内容。

  1. NetServerEnum
  2. NetQueryDisplayInformation (参见:如何从服务器获取用户列表)
  3. NetUserChangePassword

但是简单的 NetUserChangePassword 函数原型应该是不言自明的。

DWORD NetUserChangePassword(
  LPCWSTR domainname,
  LPCWSTR username,
  LPCWSTR oldpassword,
  LPCWSTR newpassword
);

命名约定

不同的字符串(例如,用户名、密码)被限制为一定数量的字符。 似乎这些限制是 NT LAN Manager 的遗留物。

名称 长度
域/工作组 15
服务器 15
用户 20
密码 14

安全问题

NetQueryDisplayInformation 需要对远程机器的 匿名访问。此外,需要建立 NULL 会话 连接 (例如,到 $IPC)。

使用代码

服务器和用户枚举被封装在几个类中。

Enumeration classes

遍历结果列表应该不是什么大问题。

NetObjectEnumerator *noe = 
   new [ NetServerEnumerator(Domain) | NetUserEnumerator(Server) ] ;
if(noe->GetError() == ERROR_SUCCESS){
  while(noe->HasNext()){
    NetObject *no = noe->GetNext();
    ... = no->name; // process the current server/user name...

  }
}
else
  ... = NetObjectEnumerator::GetErrorMessage(noe->GetError());
  // process the occurred error...

错误代码和消息字符串

FormatMessage 函数将错误代码映射到消息。对于网络管理错误,使用 netmsg.dll 模块来查找指定的错误。

CString GetErrorMessage(DWORD dwLastError){
  HMODULE hModule = NULL;
  DWORD dwFormatFlags = FORMAT_MESSAGE_ALLOCATE_BUFFER | 
        FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM;
  LPTSTR lpMessageBuffer = NULL;
  if((dwLastError >= NERR_BASE) && (dwLastError <= MAX_NERR)){
    hModule = LoadLibraryEx(_T("netmsg.dll"), NULL, LOAD_LIBRARY_AS_DATAFILE);
    if(hModule != NULL)
      dwFormatFlags |= FORMAT_MESSAGE_FROM_HMODULE;
  }
  FormatMessage(
    dwFormatFlags,
    hModule,
    dwLastError,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
    (LPTSTR)&lpMessageBuffer,
    0,
    NULL);
  CString szMessage;
  szMessage.Format(_T("%s (%u)"), lpMessageBuffer, dwLastError);
  LocalFree(lpMessageBuffer);
  if(hModule != NULL)
    FreeLibrary(hModule);
  return szMessage;
}

致谢

感谢 Chris Maunder 提供的他的伟大 超链接静态控件

Notice

该应用程序尚未在域环境中进行测试。 有志愿者吗?

请随时通过电子邮件向我发送您的反馈。 错误报告、拼写更正、意见和评论将不胜感激。

历史

  • 05/16/2006:
    • 发表原创文章。
    • 版本 1.0.0.1 发布

最新的 密码更改器 版本也可以在我的 网站 上找到。

© . All rights reserved.