Detección del patrón de esquema
Servicios de dominio de Active Directory tener un sistema de actualización multimaestro; cada controlador de dominio contiene una copia grabable del directorio. Las actualizaciones de esquema se propagan a todos los dominios que pertenecen al mismo árbol o bosque. Dado que es difícil conciliar las actualizaciones en conflicto con el esquema, las actualizaciones de esquema solo se pueden realizar en un único servidor. El servidor con derecho a realizar actualizaciones puede cambiar, pero solo un servidor tendrá ese derecho en un momento dado. Este servidor se denomina maestro de esquema. El primer controlador de dominio instalado en una empresa es, de forma predeterminada, el patrón de esquema.
Los cambios de esquema solo se pueden realizar en el nivel de patrón de esquema. Para detectar qué controlador de dominio es el maestro de esquema, realice los pasos siguientes.
Detección del patrón de esquema de controlador de dominio
- Lea el atributo fsmoRoleOwner del contenedor de esquemas en cualquier controlador de dominio. El atributo fsmoRoleOwner devuelve el nombre distintivo (DN) del objeto nTDSDSA para el patrón de esquema.
- Enlace al objeto nTDSDSA cuyo DN acaba de recuperar. El elemento primario de este objeto es el objeto de servidor para el controlador de dominio que contiene el patrón de esquema.
- Obtenga ADsPath para el elemento primario del objeto nTDSDSA . El elemento primario es un objeto de servidor.
- Enlace al objeto de servidor.
- Obtenga el atributo dNSHostName del objeto de servidor. Este es el nombre DNS del controlador de dominio que contiene el patrón de esquema.
- Especifique el nombre DNS del patrón de esquema como el servidor y el DN como DN del contenedor de esquemas que se enlazarán al patrón de esquema. Por ejemplo, si el servidor era "dc1.fabrikam.com" y el DN del contenedor de esquemas era "cn=schema,cn=configuration,dc=fabrikam,dc=com", ADsPath sería el siguiente.
LDAP://dc1.fabrikam.com/cn=schema,cn=configuration,dc=fabrikam,dc=com
Se recomienda encontrar el patrón de esquema y enlazarlo para realizar cambios en el esquema. Sin embargo, puede mover el patrón de esquema a otro servidor.
Para que otro servidor sea el maestro de esquema, un usuario con privilegios adecuados puede hacer lo siguiente:
Use el complemento MMC del Administrador de esquemas.
Nota
El complemento MMC de esquema de Active Directory debe registrarse manualmente. Para registrar el complemento Esquema, debe ejecutar el siguiente comando desde el símbolo del sistema en el directorio Windows System32.
regsvr32.exe schmmgmt.dll
Use la utilidad de línea de comandos NTDSUTIL.
Use una aplicación de terceros (una aplicación que emite la escritura LDAP adecuada).
Para convertirse en el patrón de esquema mediante programación, una aplicación que se ejecuta en el contexto de un usuario con privilegios adecuados puede emitir una escritura LDAP del atributo operativo se convierte enSchemaMaster en el rootDSE de ese controlador de dominio. Esto inicia una transferencia atómica del patrón de esquema directamente desde el titular actual al controlador de dominio local.
En el ejemplo de código siguiente se busca el patrón de esquema. La siguiente función se enlaza al contenedor de esquemas del equipo que es el patrón de esquema.
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;
}
En el ejemplo de código siguiente se muestra el nombre DNS del equipo que es el maestro de esquema.
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