Обнаружение главного образца схемы
домен Active Directory службы имеют систему обновления с несколькими узлами; каждый контроллер домена содержит записываемую копию каталога. Обновления схемы распространяются на все домены, принадлежащие одному дереву или лесу. Так как сложно сопоставить конфликтующие обновления схемы, обновления схемы могут выполняться только на одном сервере. Сервер с правом на выполнение обновлений может измениться, но только один сервер будет иметь это право в любое время. Этот сервер называется главной схемой. Первый контроллер домена, установленный в предприятии, по умолчанию — главный образец схемы.
Изменения схемы можно вносить только на главном уровне схемы. Чтобы определить, какой контроллер домена является главной схемой, выполните следующие действия.
Обнаружение главного образца схемы контроллера домена
- Чтение атрибута fsmoRoleOwner контейнера схемы на любом контроллере домена. Атрибут fsmoRoleOwner возвращает различающееся имя (DN) объекта nTDSDSA для образца схемы.
- Привязывайтесь к объекту nTDSDSA , dN которого вы только что получили. Родительским объектом этого объекта является серверный объект для контроллера домена, содержащего главную схему.
- Получите ADsPath для родительского объекта nTDSDSA . Родительский объект — это серверный объект.
- Привязка к объекту сервера.
- Получите атрибут dNSHostName объекта сервера. Это DNS-имя контроллера домена, содержащего главную схему.
- Укажите DNS-имя главного объекта схемы в качестве сервера и DN в качестве DN контейнера схемы, чтобы привязать его к главному объекту схемы. Например, если сервер был "dc1.fabrikam.com", а DN контейнера схемы был "cn=schema,cn=configuration,dc=fabrikam,dc=com", ADsPath будет следующим образом.
LDAP://dc1.fabrikam.com/cn=schema,cn=configuration,dc=fabrikam,dc=com
Рекомендуется найти главную схему и привязать к ней, чтобы внести изменения в схему. Однако эталон схемы можно переместить на другой сервер.
Чтобы сделать другой сервер главной схемой, подходящий привилегированный пользователь может:
Используйте оснастку MMC диспетчера схем.
Примечание.
Оснастка MMC схемы Active Directory должна быть зарегистрирована вручную. Чтобы зарегистрировать оснастку схемы, необходимо выполнить следующую команду из командной строки в каталоге Windows System32.
regsvr32.exe schmmgmt.dll
Используйте служебную программу командной строки NTDSUTIL.
Используйте стороннее приложение (приложение, которое выдает соответствующую запись LDAP).
Чтобы стать главной схемой программным способом, приложение, работающее в контексте подходящего привилегированного пользователя, может выдавать запись LDAP операционного атрибута статьSchemaMaster в rootDSE на этом контроллере домена. Это инициирует атомарную передачу главного элемента схемы от текущего владельца к локальному контроллеру домена.
В следующем примере кода находит главный образец схемы. Следующая функция привязывается к контейнеру схемы на компьютере, который является главным.
HRESULT BindToSchemaMaster(IADsContainer **ppSchemaMaster)
{
HRESULT hr = E_FAIL;
// Get rootDSE and the schema container DN.
IADs *pObject = NULL;
IADs *pTempSchema = NULL;
IADs *pNTDS = NULL;
IADs *pServer = NULL;
BSTR bstrParent;
LPOLESTR szPath = new OLECHAR[MAX_PATH];
VARIANT var, varRole,varComputer;
hr = ADsOpenObject(L"LDAP://rootDSE",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IADs,
(void**)&pObject);
if (hr == S_OK)
{
hr = pObject->Get(CComBSTR("schemaNamingContext"), &var);
if (hr == S_OK)
{
wcscpy_s(szPath,L"LDAP://");
wcscat_s(szPath,var.bstrVal);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IADs,
(void**)&pTempSchema);
if (hr == S_OK)
{
/*
Read the fsmoRoleOwner attribute to identify which server is
the schema master.
*/
hr = pTempSchema->Get(CComBSTR("fsmoRoleOwner"), &varRole);
if (hr == S_OK)
{
// The fsmoRoleOwner attribute returns the nTDSDSA object.
// The parent is the server object.
// Bind to NTDSDSA object and get parent.
wcscpy_s(szPath,L"LDAP://");
wcscat_s(szPath,varRole.bstrVal);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)&pNTDS);
if (hr == S_OK)
{
hr = pNTDS->get_Parent(&bstrParent);
if (hr == S_OK)
{
/*
Bind to server object and get the DNS name of
the server.
*/
wcscpy_s(szPath,bstrParent);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)&pServer);
if (hr == S_OK)
{
// Get the dns name of the server.
hr = pServer->Get(CComBSTR("dNSHostName"),
&varComputer);
if (hr == S_OK)
{
wcscpy_s(szPath,L"LDAP://");
wcscat_s(szPath,varComputer.bstrVal);
wcscat_s(szPath,L"/");
wcscat_s(szPath,var.bstrVal);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)ppSchemaMaster);
if (FAILED(hr))
{
if (*ppSchemaMaster)
{
(*ppSchemaMaster)->Release();
(*ppSchemaMaster) = NULL;
}
}
}
VariantClear(&varComputer);
}
if (pServer)
pServer->Release();
}
SysFreeString(bstrParent);
}
if (pNTDS)
pNTDS->Release();
}
VariantClear(&varRole);
}
if (pTempSchema)
pTempSchema->Release();
}
VariantClear(&var);
}
if (pObject)
pObject->Release();
return hr;
}
В следующем примере кода отображается DNS-имя компьютера, который является главной схемой.
On Error Resume Next
'''''''''''''''''''
' Bind to the rootDSE
''''''''''''''''''''
sPrefix = "LDAP://"
Set root= GetObject(sPrefix & "rootDSE")
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method"
End If
'''''''''''''''''''
' Get the DN for the schema
''''''''''''''''''''
sSchema = root.Get("schemaNamingContext")
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on Get method"
End If
'''''''''''''''''''
' Bind to the schema container
''''''''''''''''''''
Set Schema= GetObject(sPrefix & sSchema )
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method to bind to schema"
End If
''''''''''''''''''''
' Read the fsmoRoleOwner attribute to see which server is the
' schema master.
''''''''''''''''''''
sMaster = Schema.Get("fsmoRoleOwner")
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on IADs::Get method for fsmoRoleOwner"
End If
''''''''''''''''''''
' The fsmoRoleOwner attribute returns the nTDSDSA object.
' The parent is the server object.
' Bind to NTDSDSA object and get the parent object.
''''''''''''''''''''
Set NTDS = GetObject(sPrefix & sMaster)
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method for NTDS"
End If
sServer = NTDS.Parent
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on IADs::get_Parent method"
End If
''''''''''''''''''''
' Bind to server object
' and get the reference to the computer object.
''''''''''''''''''''
Set Server = GetObject(sServer)
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method for " & sServer
End If
sComputer = Server.Get("dNSHostName")
''''''''''''''''''''
' Display the DNS name for the computer.
''''''''''''''''''''
strText = "Schema master has the following DNS name: "& sComputer
WScript.echo strText
''''''''''''''''''''
' Display subroutines
''''''''''''''''''''
Sub BailOnFailure(ErrNum, ErrText)
strText = "Error 0x" & Hex(ErrNum) & " " & ErrText
MsgBox strText, vbInformation, "ADSI Error"
WScript.Quit
End Sub