更改服务用户帐户上的密码 - Win32 apps

2025-10-30 08:09:57 1308

对于使用用户帐户(而不是 LocalSystem 帐户)登录的服务实例,主机上的服务控制管理器 (SCM) 会存储帐户密码,而该密码可用于在服务启动时登录到该服务。 与所有用户帐户一样,必须定期更改密码以保持安全性。 更改服务帐户的密码时,请更新 SCM 存储的密码。 以下代码示例演示了如何执行这两项操作。

代码示例使用 IADsUser.SetPassword 来设置帐户密码。 此方法使用帐户的可分辨名称。 然后,该示例会打开指定主机上的已安装服务的句柄,并使用 ChangeServiceConfig 函数来更新 SCM 缓存的密码。 此函数使用帐户的 SAM 名称(“<域>\<用户名>”)。

注意

此代码必须由域管理员执行。

对于每个副本使用不同登录帐户的可复制服务,可通过枚举服务实例来更新所有副本的密码。 有关详细信息和代码示例,请参阅枚举服务的副本。

DWORD UpdateAccountPassword(

LPTSTR szServerDNS, // DNS name of host computer

LPTSTR szAccountDN, // Distinguished name of service

// logon account

LPTSTR szServiceName, // Name of the service

LPTSTR szOldPassword, // Old password

LPTSTR szNewPassword // New password

)

{

SC_HANDLE schService = NULL;

SC_HANDLE schSCManager = NULL;

DWORD dwLen = MAX_PATH;

TCHAR szAccountPath[MAX_PATH];

IADsUser *pUser = NULL;

HRESULT hr;

DWORD dwStatus = 0;

SC_LOCK sclLock = NULL;

if( !szServerDNS ||

!szAccountDN ||

!szServiceName ||

!szOldPassword ||

!szNewPassword)

{

_tprintf(TEXT("Invalid parameter"));

goto cleanup;

}

// Set the password on the account.

// Use the distinguished name to bind to the account object.

_tcsncpy_s(szAccountPath, TEXT("LDAP://"), MAX_PATH);

_tcscat_s(szAccountPath,

MAX_PATH,

szAccountDN);

hr = CoInitialize(NULL);

if (FAILED(hr))

{

_tprintf(TEXT("Initializing COM failed - 0x%x\n"), dwStatus = hr);

goto cleanup;

}

hr = ADsGetObject(szAccountPath, IID_IADsUser, (void**)&pUser);

if (FAILED(hr))

{

_tprintf(TEXT("Get IADsUser failed - 0x%x\n"), dwStatus = hr);

goto cleanup;

}

// Set the password on the account.

hr = pUser->ChangePassword(CComBSTR(szOldPassword),

CComBSTR(szNewPassword));

if (FAILED(hr))

{

_tprintf(TEXT("ChangePassword failed - 0x%x\n"),

dwStatus = hr);

goto cleanup;

}

// Update the account and password in the SCM database.

// Open the Service Control Manager on the specified computer.

schSCManager = OpenSCManager(

szServerDNS, // DNS name of host computer

NULL, // database (NULL == default)

SC_MANAGER_ALL_ACCESS // access required

);

if (! schSCManager)

{

_tprintf(TEXT("OpenSCManager failed - %d\n"),

dwStatus = GetLastError());

goto cleanup;

}

// Open a handle to the service instance.

schService = OpenService(schSCManager,

szServiceName,

SERVICE_ALL_ACCESS);

if (! schService)

{

_tprintf(TEXT("OpenService failed - %d\n"),

dwStatus = GetLastError());

goto cleanup;

}

// Get the SCM database lock before changing the password.

sclLock = LockServiceDatabase(schSCManager);

if (sclLock == NULL) {

_tprintf(TEXT("LockServiceDatabase failed - %d\n"),

dwStatus = GetLastError());

goto cleanup;

}

// Set the account and password that the service uses at startup.

if (! ChangeServiceConfig(

schService, // Handle of service

SERVICE_NO_CHANGE, // Service type: no change

SERVICE_NO_CHANGE, // Change service start type

SERVICE_NO_CHANGE, // Error control: no change

NULL, // Binary path: no change

NULL, // Load order group: no change

NULL, // Tag ID: no change

NULL, // Dependencies: no change

NULL, // Account name: no change

szNewPassword, // New password

NULL) ) // Display name: no change

{

_tprintf(TEXT("ChangeServiceConfig failed - %d\n"),

dwStatus = GetLastError());

goto cleanup;

}

_tprintf(TEXT("Password changed for service instance on: %s\n"),

szServerDNS);

cleanup:

if (sclLock)

UnlockServiceDatabase(sclLock);

if (schService)

CloseServiceHandle(schService);

if (schSCManager)

CloseServiceHandle(schSCManager);

if (pUser)

pUser->Release();

return dwStatus;

}