雖然 Windows 2000 內建完善的 MMC 管理工具,但在實際專案(如終端機管理軟體、自助服務入口網站)中,往往需要將使用者管理功能(建立/刪除帳號、重設密碼、群組成員維護)整合至自有應用程式中,方便非技術人員操作。本文提供基於 ADSI(Active Directory Service Interfaces)與 WinNT/LDAP 提供者的 C++ 程式碼範例,展示核心使用者管理操作的實作邏輯。
IADsContainer:容器介面,支援 Create、Delete 物件。IADs:通用目錄物件介面,支援 Put、Get、SetInfo 屬性操作。IADsUser:使用者專用介面,提供 SetPassword、ChangePassword、Groups 等方法。ADsGetObject:依 ADsPath 繫結至目錄物件的進入點函式。環境假設: 本機電腦管理(WinNT:// 提供者),公寓執行緒模型,錯誤處理簡化為回傳 BOOL。
BOOL __stdcall DeleteUser(char *username) {
HRESULT hr;
IADsContainer *pContainer = NULL;
_bstr_t bstr;
DWORD dwLen = 255;
char szComputer[255];
::GetComputerName(szComputer, &dwLen);
// 繫結本機 WinNT 提供者
bstr = "WinNT://" + _bstr_t(szComputer) + ",computer";
hr = CoInitialize(NULL);
hr = ADsGetObject(bstr, IID_IADsContainer, (void**)&pContainer);
if (FAILED(hr)) { CoUninitialize(); return FALSE; }
// 刪除使用者物件
hr = pContainer->Delete(L"user", _bstr_t(username));
pContainer->Release();
CoUninitialize();
return SUCCEEDED(hr);
}
BOOL __stdcall AddUser(char *username, char *fullname, char *description) {
HRESULT hr;
IADsContainer *pContainer = NULL;
IADs *pADs = NULL;
IDispatch *pDisp = NULL;
_bstr_t bstr;
DWORD dwLen = 255;
char szComputer[255];
::GetComputerName(szComputer, &dwLen);
bstr = "WinNT://" + _bstr_t(szComputer) + ",computer";
hr = CoInitialize(NULL);
hr = ADsGetObject(bstr, IID_IADsContainer, (void**)&pContainer);
if (FAILED(hr)) { CoUninitialize(); return FALSE; }
// 建立使用者物件
hr = pContainer->Create(L"user", _bstr_t(username), &pDisp);
pContainer->Release();
if (FAILED(hr)) { CoUninitialize(); return FALSE; }
// 取得 IADs 介面設定屬性
hr = pDisp->QueryInterface(IID_IADs, (void**)&pADs);
pDisp->Release();
if (FAILED(hr)) { CoUninitialize(); return FALSE; }
VARIANT var; VariantInit(&var);
var.vt = VT_BSTR; var.bstrVal = _bstr_t(fullname);
pADs->Put(L"FullName", var); VariantClear(&var);
var.vt = VT_BSTR; var.bstrVal = _bstr_t(description);
pADs->Put(L"Description", var); VariantClear(&var);
hr = pADs->SetInfo(); // 送交寫入
pADs->Release();
CoUninitialize();
return SUCCEEDED(hr);
}
BOOL __stdcall SetUserPwd(char *username, char *pwd) {
HRESULT hr;
IADsUser *pUser = NULL;
_bstr_t bstr;
DWORD dwLen = 255;
char szComputer[255];
::GetComputerName(szComputer, &dwLen);
// WinNT 路徑格式:WinNT:///,user
bstr = "WinNT://" + _bstr_t(szComputer) + "/" + _bstr_t(username) + ",user";
hr = CoInitialize(NULL);
hr = ADsGetObject(bstr, IID_IADsUser, (void**)&pUser);
if (SUCCEEDED(hr)) {
hr = pUser->SetPassword(_bstr_t(pwd));
pUser->Release();
CoUninitialize();
return SUCCEEDED(hr);
}
CoUninitialize();
return FALSE;
}
| 面向 | 說明 |
|---|---|
| 提供者選擇 | 範例使用 WinNT:// 管理本機 SAM 資料庫;管理網域帳號請改用 LDAP:// 提供者,路徑格式為 LDAP://cn=user,ou=OU,dc=domain,dc=com。 |
| 執行緒模型 | ADSI 預設需單執行緒公寓 (STA),CoInitialize(NULL) 滿足需求;多執行緒環境請使用 CoInitializeEx(NULL, COINIT_APARTMENTTHREADED)。 |
| 錯誤處理 | 生產環境必須檢查每個 HRESULT,並透過 IErrorInfo 取得詳細錯誤訊息;範例為簡化省略。 |
| 權限需求 | 呼叫端需具備目標容器的「建立/刪除使用者物件」與「重設密碼」權限;建議使用委派帳號而非 Domain Admin 執行服務。 |
| 密碼原則 | SetPassword 為管理員重設行為,繞過密碼歷程/複雜度/最短壽命檢查;若需使用者自助變更,請改用 IADsUser::ChangePassword(需提供舊密碼)。 |
| Unicode 支援 | ADSI 內部使用 Unicode,範例使用 _bstr_t 自動處理 ANSI/Unicode 轉換;建議專案統一使用 Unicode 建置。 |
IADsGroup::Add/Remove 操作 member 屬性。IADsContainer::_NewEnum 迭代容器下所有物件,篩選 Class == "user"。IDirectorySearch (LDAP 提供者) 執行高效能分頁查詢。透過 ADSI 的標準化介面,開發人員可輕鬆將 Active Directory 的強大身分管理能力內嵌至自有應用系統。本文提供的三個核心函式(刪除、新增、設定密碼)涵蓋了使用者生命週期的基礎操作,搭配適當的錯誤處理、權限規劃與提供者選擇,即可構建穩健的整合式管理方案。
Windows 2000/Server 2003 時間服務在 Proxy 伺服器後無法同步解決方案
Windows 2000 檔案類型關聯設定:新增、修改、進階選項、開啟方式變更
Windows 2000 磁碟配額管理完整教學:啟用、設定、監控與報表
Windows 2000 Services.exe CPU 飆升 100% 導致系統停止回應:Esent.dll 修補程式解決方案
Windows Server 2003 內建 ADSL 撥號連線設定教學
Windows「最近一次正確配置」功能完整指南:驅動程式更新失敗後的急救鑰匙