El Blog de Gualtrysoft

Windows 2000/2003/2008, Active Directory, VBScript, Hyper-V, PowerShell y todo aquello interesante a la hora de usar, configurar y administrar Windows Server. También tenemos longanizas…

Powershell: Cmdlet para cambiar la lista de servidores DNS

Posted by urpiano en Martes 30 \30\UTC noviembre \30\UTC 2010

Esta función cambia los servidores DNS de todas las conexiones de red que presenten como uno de sus servidores DNS el que se pasa como parámetro de búsqueda. La función recibe una lista de servidores y una lista con los nuevos servidores DNS que se deben configurar. El cambio es realizado a través de WMI, en concreto con el método SetDNSServerSearchOrder de la clase CIMv2 Win32_NetworkAdapterConfiguration. Por ello, es necesario que los equipos remotos tengan habilitada la excepción de administración remota en el caso de tener el firewall en estado activo.

El Cmdlet incluye ayuda, pego a continuación la ayuda con modificador -Detailed (esta ayuda se basa en la prestación de ayuda basada en comentarios de PowerShell 2.0 ¿Qué todavía tienes la versión 1.0 y no la 2.0? ¿A qué esperas para instalarla si es mucho mejor?):

NOMBRE
    Set-DNSServerSearchOrder
    
SINOPSIS
    Cambia los servidores DNS de las conexiones de red, que tengan uno en
    concreto configurado, de una lista de equipos
    
    
SINTAXIS
    Set-DNSServerSearchOrder [-DNSaBuscar]  [-FicheroServidores]  `
             [-FicheroDNSs]  [-FicheroSalida]  []
    
    
DESCRIPCIÓN
    Esta función cambia los servidores DNS de todas las conexiones de red que
    presenten como uno de sus servidores DNS el que se pasa como parámetro de
    búsqueda. La función recibe una lista de servidores y una lista con los
    nuevos servidores DNS que se deben configurar.
    El cambio es realizado a través de WMI, en concreto con el método
    SetDNSServerSearchOrder de la clase CIMv2 Win32_NetworkAdapterConfiguration.
    Por ello, es necesario que los equipos remotos tengan habilitada la
    excepción de administración remota en el caso de tener el firewall en estado
    activo.
    

PARÁMETROS
    -DNSaBuscar 
        Este parámetro consiste en una dirección IP. La función filtrará las
        conexiones de red de los equipos para tratar sólo con aquellas que en su
        lista de servidores DNS tengan esta IP como uno de ellos. Este parámetro
        se puede también invocar con los alias "Buscar" o "B".
        
    -FicheroServidores 
        Este parámetro recibe la ruta y nombre de un fichero de texto en el cuál
        están los nombres o IPs de los servidores a procesar, uno por línea. Este
        parámetro se puede también invocar con los alias "Servidores", "SRV" o "S".
        
    -FicheroDNSs 
        Este parámetro recibe la ruta y nombre de un fichero de texto en el cuál
        están las direcciones IP de los nuevos servidores DNS a configurar, uno 
        por línea. El órden en que quedarán configurados es el órden en el que se 
        encuentren en el fichero. Tenemos un fichero de DNSs con este contenido:
                    10.13.24.50
                    10.13.24.55
        En este caso, quedará 10.13.24.50 como servidor DNS primario y 10.13.24.55
        como servidor DNS secundario. Este parámetro tasmbién se puede invocar con
        los alias "Nuevos" o "N"
        
    -FicheroSalida 
        Este parámetro recibe la ruta y nombre del fichero que se generará con los
        resultados del procesamiento de la función. si el fichero ya existe será
        sobreescrito. Se trata de un fichero de valores separados por tabulador, 
        muy cómodo para ser abierto con Excel y separado en columnas. Las columnas
        que contiene son:
            - Servidor: nombre del servidor
            - Conexión: nombre de la conexión de red que se cambia. En equipos
                        Windows 2000 aparecerá en blanco, pues Windows 2000 no tiene
                        los nombres de las conexiones de red en WMI (en concreto, 
                        la clase Win32_NetworkAdpater no tiene la propiedad
                        NetConnectionID).
            - DNSaBuscar: IP que se buscaba entre los servidores DNS.
            - Anterior: Lista de DNSs que tenía el equipo antes de ser procesado.
            - Actual de DNSs que han quedado configurados tras la ejecución.
            - Devolución: Resultado obtenido al procesar el equipo.
        Este parámetro se puede invocar también con los alias "Salida", "O" o "F".
        
    
        Este cmdlet admite los parámetros comunes Verbose, Debug,
        ErrorAction, ErrorVariable, WarningAction, WarningVariable,
        OutBuffer y OutVariable. Para obtener más información, escriba:
        "get-help about_commonparameters".
    
    -------------------------- EJEMPLO 1 --------------------------
    
    C:\PS>Set-DNSServerSearchOrder 10.25.13.41 .\SRVs.txt .\DNSs.txt .\Out.txt
    
    En este ejemplo, se procesarán las conexiones de red, que tengan presente
    como uno de sus servidores DNSs a 10.25.13.41, de los servidores listados en
    el fichero SRVs.txt. Se establecerán los servidores DNSs listados en el
    fichero DNSs.txt y los resultados se almacenarán en el fichero Out.txt. Los
    tres ficheros mencionados están en la carpeta en la que se encuentra
    el inductor de PowerShell (Get-Location). Los parámetros se han pasado sin
    nombre, y por tanto se han pasado en el orden DNSaBuscar FicheroServidores
    FicheroDNSs FicheroSalida
     
    -------------------------- EJEMPLO 2 --------------------------
    
    C:\PS>Set-DNSServerSearchOrder -FicheroSalida .\Out.txt -FicheroDNSs.\DNSs.txt `
                                             -FicheroServidores .\SRVs.txt -DNSaBuscar 10.25.13.41
    
    Este ejemplo realiza la misma tarea que el anterior ejemplo. La diferencia
    es que se han pasado los parámetros con nombre y, por tanto, se ha podido
    alterar el orden de los mismos.
    
    -------------------------- EJEMPLO 3 --------------------------
    
    C:\PS>Set-DNSServerSearchOrder -O .\Out.txt -N.\DNSs.txt -SRV .\SRVs.txt -B 10.25.13.41
    
    Este ejemplo realiza la misma tarea que el anterior ejemplo. La diferencia
    es que se han pasado los parámetros con alias.
    
NOTAS
    Para ver los ejemplos, escriba: "get-help Set-DNSServerSearchOrder -examples".
    Para obtener más información, escriba: "get-help Set-DNSServerSearchOrder -detailed".
    Para obtener información técnica, escriba: "get-help Set-DNSServerSearchOrder -full".

Este es el código del Cmdlet:

Function Get-DevolucionSetDNSServerSearchOrder([parameter(Mandatory=$true)]
                                               [Int32]$Valor)
{
    Switch($Valor)
    {
        0{"0: Finalización satisfactoria, no necesita reiniciar"}
        1{"1: Finalización satisfactoria, necesita reiniciar"}
        64{"64: Método no compatible en esta plataforma"}
        65{"65: Error desconocido"}
        66{"66: Máscara de subred no válida"}
        67{"67: Error al procesar una instancia que se había devuelto"}
        68{"68: Parámetro de entrada no válido"}
        69{"69: Hay más de 5 puertas de enlace especificadas"}
        70{"70: Dirección IP no válida"}
        71{"71: Dirección de puerta de enlace IP no válida"}
        72{"72: Error al obtener acceso al Registro para la información solicitada"}
        73{"73: Nombre de dominio no válido"}
        74{"74: Nombre de host no válido"}
        75{"75: No hay servidores WINS primarios o secundarios definidos"}
        76{"76: Archivo no válido"}
        77{"77: Ruta de sistema no válida"}
        78{"78: No se pudo copiar el archivo"}
        79{"79: Parámetro de seguridad no válido"}
        80{"80: No se puede configurar el servicio TCP/IP"}
        81{"81: No se puede configurar el servicio DHCP"}
        82{"82: No se puede renovar la concesión DHCP"}
        83{"83: No se puede liberar la concesión DHCP"}
        84{"84: IP no habilitada en el adaptador"}
        85{"85: IPX no habilitada en el adaptador"}
        86{"86: Error en el número de enlaces de red/trama"}
        87{"87: Tipo de trama no válido"}
        88{"88: Número de red no válido"}
        89{"89: Número de red duplicado"}
        90{"90: Parámetros fuera de los enlaces"}
        91{"91: Acceso denegado"}
        92{"92: Memoria insuficiente"}
        93{"93: Ya existe"}
        94{"94: No se ha encontrado la ruta, el archivo o el objeto"}
        95{"95: No se puede notificar el servicio"}
        96{"96: No se puede notificar el servicio DNS"}
        97{"97: Interfaz no configurable"}
        98{"98: No se han podido liberar o renovar todas las concesiones DHCP"}
        100{"100: DHCP no está habilitado en el adaptador"}
       Default{"$Valor: consulte la documentación de códigos de error de Win32"}
    }
}

Function Set-DNSServerSearchOrder([parameter(Mandatory=$true,Position=0)]
                                      [string][ValidateNotNullOrEmpty()]
                                      [Alias("Buscar","B")]
                                      $DNSaBuscar, `
                                  [parameter(Mandatory=$true,Position=1)]
                                      [string][ValidateNotNullOrEmpty()]
                                      [Alias("Servidores","S","SRV")]
                                      $FicheroServidores, `
                                  [parameter(Mandatory=$true,Position=2)]
                                      [string][ValidateNotNullOrEmpty()]
                                      [Alias("Nuevos","N")]
                                      $FicheroDNSs, `
                                  [parameter(Mandatory=$true,Position=3)]
                                      [string][ValidateNotNullOrEmpty()]
                                      [Alias("Salida","O","F")]
                                      $FicheroSalida)
{
################## Comprobación de parámetros recibidos #######################
    
    # Comprobamos que existe el fichero con la lista de servidores a cambiar sus
    # DNSs
    $ExisteFicheroServidores = Test-Path $FicheroServidores
    
    # Comprobamos que existe el fichero con la lista de servidores DNS a
    # establecer en las conexiones de red
    $ExisteFicheroDNSs = Test-Path $FicheroDNSs
    
    # Comprobamos que existe la carpeta en la que ubicar el fichero con los
    # resultados
    $ExisteCarpetaSalida = Test-Path (Split-Path $FicheroSalida)
    
    # Si no se ha cumplido una o más de las condiciones revisadas antes
    If((`
            $ExisteFicheroServidores -and `
            $ExisteFicheroDNSs       -and `
            $ExisteCarpetaSalida `
        ) -eq $false)
    {
        # Comenzamos a montar el mensaje describiendo el problema
        $Mensaje = "No se puede ejecutar el script porque:`n`r`n`r`t"
        # Si se ha producido, mostramos la falta del fichero de servidores
        If($ExisteFicheroServidores -eq $false)
        {
            $Mensaje = "$Mensaje- No se ha encontrado el fichero con la " + `
                       "lista de servidores a actualizar " + `
                       "(parametro -FicheroServidores)`n`r`t"
        }
        # Si se ha producido, mostramos la falta del fichero de DNSs
        If($ExisteFicheroDNSs -eq $false)
        {
            $Mensaje = "$Mensaje- No se ha encontrado el fichero con la " + `
                        "lista de servidores DNS a configurar " + `
                        "(parametro -FicheroDNSs)`n`r`t"
        }
        # Si se ha producido, mostramos la inexistencia de la carpeta en la que
        # crear el fichero con la salida
        If($ExisteCarpetaSalida -eq $false)
        {
            $Mensaje = "$Mensaje- No existe la carpeta donde ubicar el " + `
                        "fichero de salida (parametro -FicheroSalida)n`r"
        }
        # Una vez montado el mensaje, lo mostramos
        Write-Host  -ForegroundColor Red -BackgroundColor Black $Mensaje
        # Salimos de la función
        Return
    }
############### Fin de la comprobación de parámetros recibidos #################

############################## Bloque de la función ############################
    
    # Pedimos al usuario las credenciales de ejecución
    $Credenciales = Get-Credential
    
    # Obtenemos la lista de servidores a procesar
    $Servidores = Get-Content $FicheroServidores
    
    # Obtenemos los Servidores DNS a establecer
    $DNSs = Get-Content $FicheroDNSs
    
    # Iniciamos la variable de  salida como array
    $Salida = @()
    
    # Ponemos los encabezados a la salida
    $Salida += "Servidor`tConexion`tDNSaBuscar`tAnterior`tActual`tDevolucion"
    
    # El comando Get-WMIObject genera errores que no interrumpen la ejecución,
    # por lo que no se pueden atrapar con Try o Trap. Para que sí provoquen
    # interrupción, debemos cambiar el valor de la variable 
    # $ErrorActionPreference, encargada de establecer el comportamiento de 
    # PowerShell con los errores que no provocan interrupción De forma 
    # predeterminada tiene el valor "Continue";  si queremos que los errores
    # que no interrumpen sí lo hagan, el valor lo debemos establecer en "Stop".
    # Vamos pues a almacenar el valor que tenga, para poder restituirlo y
    # así no dejar "rastros" tras la ejhecución de la función
    $AccionError = $ErrorActionPreference
    
    # Vaciamos el objeto $error, por si hubiera errores anteriores que no
    # interesan
    $Error.Clear()

    # Recorremos los servidores
    ForEach($Servidor In $Servidores)
    {
    
        # Cambiamos el comportamiento de PowerShell ante los errores que no
        # interrumpen para que sí lo hagan. Lo hacemos aquí para que este 
        # comportamiento sólo lo tenga en el siguiente comando
        $ErrorActionPreference = "Stop"
        
        # Recorremos las conexiones de red el servidor en las cuales se cumple
        # que esté presente el servidor DNS que utilizamos como localización
        # de conexiones a cambiar
        Try
        {
            ForEach($Conexion In
                            (Get-WmiObject Win32_NetworkAdapterConfiguration `
                                                -ComputerName $Servidor `
                                                -Credential $Credenciales `
                             | Where-Object {$_.DNSServerSearchOrder -contains `
                                                                   $DNSaBuscar}
                            )
                    )
            {
            
                # Restituimos el comportamiento de PoweShell ante los errores

                # que no interrumpen
                $ErrorActionPreference = $AccionError
            
                # Almacenamos la lista actual de servidores DNS configurados
                $Anterior = $Conexion.DNSServerSearchOrder
                
                # Obtenemos el nombre de la conexión de red. Este nombre sólo 
                # puede ser obtenido en sistemas post-Windows 2000, dado que la
                # clase WMI Win32_NetworkAdapter no incluye la propiedad
                # NetConnectionID en los sistemas Windows 2000. Por tanto,
                # $NombreConexion será nulo en equipos Windows 2000.
                $NombreConexion = ( `
                               Get-WmiObject Win32_NetworkAdapter `
                                             -ComputerName $Servidor `
                                             -Credential $Credenciales | `
                               Where-Object {$_.Caption -eq $Conexion.Caption} `
                                  ).NetConnectionID
                # Establecemos la nueva lista de servidores DNS
                $Devolucion = $Conexion.SetDNSServerSearchOrder($DNSs)
                $InformacionDevolucion = Get-DevolucionSetDNSServerSearchOrder( `
                                            $Devolucion.ReturnValue)
                # Obtenemos la nueva configuración
                $Nueva = ( `
                            Get-WmiObject Win32_NetworkAdapterConfiguration `
                                -ComputerName $Servidor `
                                -Credential $Credenciales `
                                -Filter "SettingID = '$($Conexion.SettingID)'" `
                         ).DNSServerSearchOrder
                # Montamos la información sobre el proceso
                $Informacion = "$Servidor`t$NombreConexion`t$DNSaBuscar`t" + `
                            "$($Anterior)`t$($Nueva)`t" + `
                            "$InformacionDevolucion"
                # Agregamos la información a la salida
                $Salida += $Informacion
                # Mostramos la información por consola
                Write-Host "$Servidor`t->`t$InformacionDevolucion"
            }
        }
        Catch
        {
            # No se ha podido contactar con el servicio WMI, ya sea por tratarse
            # de un equipo inexistente, inalcanzable (con fallo en la red) o
            # que su servicio WMI no esté accesible
            
            # Montamos la información del error
            $InformacionError = "$($Error[0].Exception.ErrorCode) " + 
                                "($($Error[0].Exception.Message)"
            
            # Montamos la información sobre el proceso
            $Informacion = "$Servidor`t`t$DNSaBuscar`t" + `
                           "`t`t$InformacionError"
                           
            # Agregamos la información a la salida
            $Salida += $Informacion
            
            
            # Mostramos la información por consola
            Write-Host "$Servidor`t->`t$InformacionError"
            
            # Vaciamos el objeto error
            $Error.Clear()
        }
    }
    # Guardamos los resultados en el fichero de salida
    Set-Content -Path $FicheroSalida -Value $Salida

#.SYNOPSIS
#   Cambia los servidores DNS de las conexiones de red, que tengan uno en
#   concreto configurado, de una lista de equipos
#.DESCRIPTION
#   Esta función cambia los servidores DNS de todas las conexiones de red que
#   presenten como uno de sus servidores DNS el que se pasa como parámetro de
#   búsqueda. La función recibe una lista de servidores y una lista con los
#   nuevos servidores DNS que se deben configurar.
#   El cambio es realizado a través de WMI, en concreto con el método
#   SetDNSServerSearchOrder de la clase CIMv2 Win32_NetworkAdapterConfiguration.
#   Por ello, es necesario que los equipos remotos tengan habilitada la
#   excepción de administración remota en el caso de tener el firewall en estado
#   activo.
#.PARAMETER DNSaBuscar
#   Este parámetro consiste en una dirección IP. La función filtrará las
#   conexiones de red de los equipos para tratar sólo con aquellas que en su
#   lista de servidores DNS tengan esta IP como uno de ellos. Este parámetro
#   se puede también invocar con los alias "Buscar" o "B".
#.PARAMETER FicheroServidores
#   Este parámetro recibe la ruta y nombre de un fichero de texto en el cuál
#   están los nombres o IPs de los servidores a procesar, uno por línea. Este
#   parámetro se puede también invocar con los alias "Servidores", "SRV" o "S".
#.PARAMETER FicheroDNSs
#   Este parámetro recibe la ruta y nombre de un fichero de texto en el cuál
#   están las direcciones IP de los nuevos servidores DNS a configurar, uno 
#   por línea. El órden en que quedarán configurados es el órden en el que se 
#   encuentren en el fichero. Tenemos un fichero de DNSs con este contenido:
#               10.13.24.50
#               10.13.24.55
#   En este caso, quedará 10.13.24.50 como servidor DNS primario y 10.13.24.55
#   como servidor DNS secundario. Este parámetro tasmbién se puede invocar con
#   los alias "Nuevos" o "N"
#.PARAMETER FicheroSalida
#   Este parámetro recibe la ruta y nombre del fichero que se generará con los
#   resultados del procesamiento de la función. si el fichero ya existe será
#   sobreescrito. Se trata de un fichero de valores separados por tabulador, 
#   muy cómodo para ser abierto con Excel y separado en columnas. Las columnas
#   que contiene son:
#       - Servidor: nombre del servidor
#       - Conexión: nombre de la conexión de red que se cambia. En equipos
#                   Windows 2000 aparecerá en blanco, pues Windows 2000 no tiene
#                   los nombres de las conexiones de red en WMI (en concreto, 
#                   la clase Win32_NetworkAdpater no tiene la propiedad
#                   NetConnectionID).
#       - DNSaBuscar: IP que se buscaba entre los servidores DNS.
#       - Anterior: Lista de DNSs que tenía el equipo antes de ser procesado.
#       - Actual de DNSs que han quedado configurados tras la ejecución.
#       - Devolución: Resultado obtenido al procesar el equipo.
#   Este parámetro se puede invocar también con los alias "Salida", "O" o "F".
#.EXAMPLE
#       Set-DNSServerSearchOrder 10.25.13.41 .\SRVs.txt .\DNSs.txt .\Out.txt
#   En este ejemplo, se procesarán las conexiones de red, que tengan presente
#   como uno de sus servidores DNSs a 10.25.13.41, de los servidores listados en
#   el fichero SRVs.txt. Se establecerán los servidores DNSs listados en el
#   fichero DNSs.txt y los resultados se almacenarán en el fichero Out.txt. Los
#   tres ficheros mencionados están en la carpeta en la que se encuentra
#   el inductor de PowerShell (Get-Location). Los parámetros se han pasado sin
#   nombre, y por tanto se han pasado en el orden DNSaBuscar FicheroServidores
#   FicheroDNSs FicheroSalida
#.EXAMPLE
#     Set-DNSServerSearchOrder -FicheroSalida .\Out.txt -FicheroDNSs.\DNSs.txt -FicheroServidores .\SRVs.txt -DNSaBuscar 10.25.13.41
#   Este ejemplo realiza la misma tarea que el anterior ejemplo. La diferencia
#   es que se han pasado los parámetros con nombre y, por tanto, se ha podido
#   alterar el orden de los mismos.
#.EXAMPLE
#     Set-DNSServerSearchOrder -O .\Out.txt -N.\DNSs.txt -SRV .\SRVs.txt -B 10.25.13.41
#   Este ejemplo realiza la misma tarea que el anterior ejemplo. La diferencia
#   es que se han pasado los parámetros con alias.
#.NOTES
#   Autor: Fernando Reyes López
#   Empresa: Unisys Consulting Spain
#   Fecha: 03/09/2010
    
}

2 comentarios to “Powershell: Cmdlet para cambiar la lista de servidores DNS”

  1. evil said

    buenos dias
    saludos,
    necesito cambiar la clave administrador para el sistema operativo W7 a un grupo de computadoras donde trabajo. como analista del dpto de soporte tecnico realizamos la migracion de Wxp a W7 y ahora necesitamos masificar una nueva contraceña
    por casualidad tienes un vbs que realice esta accion?

  2. I tend not to drop many responses, but i did a few searching
    and wound up here Powershell: Cmdlet para cambiar la lista de servidores DNS El Blog de Gualtrysoft.
    And I do have 2 questions for you if you tend not to mind.
    Is it only me or does it give the impression like some of these remarks come across like written by
    brain dead individuals? :-P And, if you are posting on additional social sites, I’d like to keep up with anything new you have to post. Would you make a list of every one of all your public sites like your linkedin profile, Facebook page or twitter feed?

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

 
A %d blogueros les gusta esto: