Si eres uno de esos administradores de sistemas que, como yo, intentas que todos los campos en Active Directory estén lo mejor cumplimentados posible (especialmente si usas algún software de inventario basado en Active Directory), te habrás topado alguna vez con este pequeño inconveniente del que os voy a hablar.
Se trata de la discrepancia entre el campo "Descripción" de la cuenta de equipo en Active Directory y el campo local "Descripción" del propio equipo en sí. Cuando hacemos un "net view" o simplemente examinamos la red desde una estación de trabajo cualquiera, junto al nombre de cada host aparece la descripción del propio equipo.
Cambiar dicha descripción (local o remotamente) en cada PC es un trabajo de chinos. Hay que ir uno a uno, o bien hacer un script o archivo de lotes de comandos. Pero esto tendría el inconveniente de que tienen que estar todos encendidos, y además no se actualizarían automáticamente.
Si por otro lado, también queremos tener la descripción detallada en Active Directory... ¿por qué no hacer que la descripción de AD se vuelque automáticamente sobre cada estación? De esta manera tenemos todos los equipos actualizados de manera asíncrona (no los tenemos que encender), sólo tenemos una descripción por lo que no crearemos incongruencias y además tendremos la comodidad de cambiar las descripciones desde la página principal de administración de "Usuarios y equipos de Active Directory".
La automatización
Haremos un script que se ejecutará en cada PC durante su arranque, y el propio equipo preguntará a Active Directory por su descripción para a continuación auto-asignársela.
Para lanzar el script la manera más eficiente es utilizar la opción de scripts de inicio/apagado de las directivas de grupo del dominio. Para ello creamos un nuevo objeto de directiva (GPO) o bien editamos alguno que esté siendo aplicado a la unidad organizativa donde estén nuestros PCs.
Digamos que hemos llamado al script con el nombre pc_description.vbs. Sólo tenemos que agregarlo a la directiva según se ve en esta imagen:
El script se ejecutará cada vez que el equipo arranque. Si lo preferís, puede hacerse que se ejecute al apagarse el equipo.
El script
En verdad es un trozo de código bastante sencillo. Los pasos que haremos en este caso son:
- Obtener el nombre del host que está ejecutando el script
- Comprobar la conectividad con algún servidor de la red. Esto es necesario para que el script no retrase el arranque del PC en caso de que el equipo esté offline y no tenga conexión al dominio (por ejemplo, un portátil en itinerancia).
- En caso afirmativo, obtenemos el "distinguished name" (DN) de nuestro equipo, y con él interrogamos mediante LDAP al AD para leer el campo "Description" de la cuenta del equipo.
- Modifica la descripción local del PC con los datos obtenidos en el paso anterior.
- Salir del script
Un ejemplo del código necesario para hacer el script es el que publicamos a continuación:
'-------------------------------------- ' ' PC Description ' The Debug Machine ' http://www.debugmachine.com ' ' ' Copyright 2013 José Ángel Morente ' Licensed under the Apache License, Version 2.0 (the "License"); ' you may not use this file except in compliance with the License. ' You may obtain a copy of the License at ' http://www.apache.org/licenses/LICENSE-2.0 ' Unless required by applicable law or agreed to in writing, software ' distributed under the License is distributed on an "AS IS" BASIS, ' WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ' See the License for the specific language governing permissions and ' limitations under the License. ' '-------------------------------------- On Error Resume Next Const ADS_SCOPE_SUBTREE = 2 Dim strComputer, strDescription, strLogonServer Dim objShell Set objShell = CreateObject("WScript.Shell") strComputer = objShell.ExpandEnvironmentStrings("%COMPUTERNAME%") strLogonServer = "dc-01.debugmachine.com" 'Comprueba si el equipo %logonserver% tiene conectividad If isAlive(strLogonServer,1,500) Then '1 ping, espera 500ms strDescription = getComputerDescription ("LDAP://" & GetDN(strComputer)) setPCDescription ".",strDescription Else WScript.Quit 0 End If Function getComputerDescription (ldapPath) 'Busca en Active Directory mediante LDAP el campo "Description" de la cuenta 'del equipo Dim objComputer, objProperty 'valor por defecto getComputerDescription = Null Set objComputer = GetObject (ldapPath) If Not IsNull(objComputer) Then objProperty = objComputer.Get("Description") If Not IsNull(objProperty) Then getComputerDescription = objProperty objProperty = Null End If objComputer = Null End If End Function Function GetDN(computerName) 'Obtiene el DN (distinguished name) del equipo Dim objRootDSE, objConnection, objCommand, objRecordSet Set objRootDSE = GetObject("LDAP://rootDSE") Set objConnection = CreateObject("ADODB.Connection") objConnection.Open "Provider=ADsDSOObject;" Set objCommand = CreateObject("ADODB.Command") objCommand.ActiveConnection = objConnection queryStr = "'LDAP://" & objRootDSE.get("defaultNamingContext") & "'" objCommand.CommandText = "Select Name, distinguishedName from " & queryStr & " where objectClass='computer'" objCommand.Properties("Page Size") = 1000 objCommand.Properties("Timeout") = 30 objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE objCommand.Properties("Cache Results") = False Set objRecordSet = objCommand.Execute objRecordSet.MoveFirst Do Until objRecordSet.EOF If lcase(objRecordSet.Fields("Name").Value) = lcase(computerName) Then GetDN = objRecordSet.Fields("distinguishedName") End If objRecordSet.MoveNext Loop End Function Sub setPCDescription (computerName,description) 'Configura la desctripción del equipo con la descripción dada Dim objOS Set objOS = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & computerName & "\root\cimv2").ExecQuery("Select * FROM Win32_OperatingSystem") For Each object In objOS object.Description = description object.Put_ Next End Sub Function isAlive(strHost, pingsNo, msWait) Dim objFile, objFSO, strDummy, strTempFile Set objFSO = CreateObject("Scripting.FileSystemObject") strTempFile = objFSO.GetTempName 'valores por defecto If msWait = "" Then msWait = 750 If pingsNo = "" Then pingsNo = 2 Const OpenAsDefault = -2 Const FailIfNotExist = 0 Const ReadMode = 1 objShell.Run "%comspec% /c ping -n " & pingsNo & " -w " & msWait _ & " " & strHost & ">" & strTempFile, 0, True Set objFile = objFSO.OpenTextFile(strTempFile, ReadMode, _ FailIfNotExist, OpenAsDefault) strDummy = objFile.ReadAll objFile.Close objFSO.DeleteFile(strTempFile) Select Case InStr(strDummy, "TTL=") Case 0 isAlive = False Case Else isAlive = True End Select End Function
No hay comentarios:
Publicar un comentario