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: Cmdlets para cambiar el caso en atributos de usuario de Active Directory

Posted by urpiano en sábado 5 \05\+01:00 May \05\+01:00 2012

¿No te gusta cómo están dados de alta los usuarios en Active Directory, en concreto que estén en mayúsculas y los quieres en minúsculas, o viceversa? ¿O te gustaría que estuviesen En Plan Títulos? ¿Quieres poder cambiar esto de un plumazo? Estos Cmdlets que presento aquí te pueden servir de ayuda.

En concreto se trata de tres Cmdlets, uno de ellos de apoyo a los otros dos. A los modos de formatear el texto los llamaremos Casos (del Inglés Case), y los tres Cmdlets reciben un parámetro -Case que es el tipo de caso que queremos establecer. Los valores que se le pueden pasar al parámetro -Case son:

  • ToLower: todo minúsculas («este es un ejemplo»).
  • ToUpper: todo mayúsculas («ESTE ES UN EJEMPLO»).
  • ToTitle: primera letra de cada palabra en mayúscula, el resto en minúsculas («Este Es Un Ejemplo»).

Los Cmdlets son:

  • Set-Case: este Cmdlet es llamado desde los otros dos y se encarga de obtener el caso deseado de la cadena que se le pase. Por tanto, es necesario que se incluya este Cmdlet para poder usar los otros dos.
  • Set-AdUserNameCase: este Cmdlet se encarga de cambiar el nombre del usuario al caso deseado. Cambiar el nombre de un usuario implica cambiar su RDN (RelativeDistinguishedName), que es la parte que queda al nombre distinguido del usuario si le quitamos la parte del nombre distinguido del contenedor que le alberga (el RDN de «CN=Pi, Filemón,OU=Agentes,DC=tia,DC=org» es «CN=Pi, Filemón»); por tanto, al cambiar el RDN estamos cambiando el nombre distinguido del usuario y esto por tanto no es el cambio de un atributo sin más, si no que es mover la cuenta del usuario, por ello se debe usar el método MoveTo del contenedor que alberga la cuenta de usuario, no establecer el cambio en el propio objeto del usuario. Al usar el Cmdlet Set-Case, es requerido que éste esté presente.
  • Set-AdUserAttributeCase: este Cmdlet es el de más alto nivel de todos, de hecho puede ser perfectamente el único que invoquemos, debido a que llama tanto a Set-Case como a Set-AdUserName (en este último caso lo llama cuando se pasa el modificador -RDN o el modificador -All, debido a que implican cambiar el caso del nombre del usuario y por tanto su RDN y eso precísamente es lo que hace Set-AdUserNameCase). Esto quiere decir que es requerido que ambos Cmdlets estén presentes para poder ejecutar Set-AdUserAttributeCase. Los atributos del objeto usuario que puede cambiar este Cmdlet son:

    • RDN: RelativeDistinguishedName, nombre del objeto usuario en Active Diretory (no confundir con el nombre propio del usuario; éste es un atributo, aquel un identificador).
    • Pestaña General
      • givenName: nombre propio.
      • initials: iniciales.
      • sn: apellidos.
      • displayName: nombre para mostrar.
      • Description: descripción.
      • physicalDeliveryOfficeName: oficina.
    • Pestaña Address
      • streetAddress: dirección.
      • postOfficeBox: apartado postal.
      • l: ciudad.
      • st: estado o provincia.
      • postalCode: código postal.
    • Pestaña Organization
      • title: cargo.
      • department: departamento.
      • company: empresa.

  • He mostrado la anterior lista clasificada por pestaña debido a que se puede indicar al Cmdlet que se cambien los atributos de una esas pestañas de las propiedades del usuario en Active Directory Users and Computers, sin que esto sea exclusivo (sólo se pueda poner una pestaña), pues es acumulativo, lo que permite especificar más de una. Por último, si se pasa el modificador -All se cambiarán todos los atributos y el RDN.

Los Cmdlets incluyen ayuda, pego a continuación la ayuda de cada uno de ellos con el 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?):

Cmdlet Ayuda
Set-Case
NOMBRE
    Set-Case

SINOPSIS
    Devuelve la cadena recibida modificada al caso establecido.


SINTAXIS
    Set-Case [[-Value] ] [[-Case] ] []


DESCRIPCIÓN
    Esta función recibe una cadena y devuelve la misma cadena con el caso
    establecido en el parámetro "Case". Los casos posibles son:

        - ToLower: todo minúsculas ("este es un ejemplo").
        - ToUpper: todo mayúsculas ("ESTE ES UN EJEMPLO").
        - ToTitle (predeterminado): Primera letra de cada palabra en
                                    mayúscula, el resto en minúsculas ("Este
                                    Es Un Ejemplo").


PARÁMETROS
    -Value 
        Cadena a ser cambiada.

    -Case 
        Caso a establecer. Los valores admitidos son "ToLower", "ToTitle" y
        "ToUpper" (predeterminado "ToTitle").

    
        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 --------------------------

    PS C:\>Set-Case "esto es un ejemplo"

    Esto Es Un Ejemplo

    Pone en caso titular la cadena "esto es un ejemplo".

    -------------------------- EJEMPLO 2 --------------------------

    PS C:\>Set-Case "esto es un ejemplo" -Case ToUpper

    ESTO ES UN EJEMPLO

    Pone en mayúsculas la cadena "esto es un ejemplo".

    -------------------------- EJEMPLO 3 --------------------------

    PS C:\>Set-Case "ESTO ES UN EJEMPLO" -Case ToLower

    esto es un ejemplo

    Pone en minúsculas la cadena "ESTO ES UN EJEMPLO".

NOTAS
    Para ver los ejemplos, escriba: "get-help Set-Case -examples".
    Para obtener más información, escriba: "get-help Set-Case -detailed".
    Para obtener información técnica, escriba: "get-help Set-Case -full".
Set-AdUserNameCase
NOMBRE
    Set-AdUserNameCase

SINOPSIS
    Cambia el caso del nombre de un usuario.


SINTAXIS
    Set-AdUserNameCase [-User]  [[-Case] ] [-Info] [-NoBoolean] []


DESCRIPCIÓN
    Esta función permite cambiar el nombre (RelativeDistinguishedName o RDN)
          de un  usuario de active directory para que cumpla con el caso recibido
          como parámetro. Los casos posibles son:

              - ToLower: todo minúsculas ("pi, filemon").
              - ToUpper: todo mayúsculas ("PI, FILEMON").
              - ToTitle (predeterminado): Primera letra de cada palabra mayúscula,
                                          el resto en minúsculas ("Pi, Filemon").

          La función permite canalización, lo que hace que se puedan procesar en
          bloque varios usuarios. Además permite varios tipos de objeto para el
          parámetro de usuario (cadena, DirectoryEntry y SearchResult) lo junto
          con la canalización permite redireccionar, por ejemplo,  un fichero de
          texto con los nombres distinguidos de los usuarios, uno por línea, a ser
          cambiados, o los resultados obtenidos con un objeto DirectorySearcher de
          una búsqueda LDAP de usuarios.


PARÁMETROS
    -User 
        Usuario al que se cambiará el nombre. Puede recibir tres tipos de
              objeto:
              - Cadena: en este caso se debe tratar del nombre distinguido de un
                        usuario.
              - DirectoryEntry: en este caso se tratará de un objeto usuario
                                directamente.
              - SearchResult: en este caso se trata de un objeto obtenido al realizar,
                              con un objeto DirectorySearcher, una consulta LDAP de
                              usuarios.
              Este parámetro permite canalización y los alias "U", "Usr" y "Usuario".

    -Case 
        Caso que se establecerá en el nombre del usuario; los tipos son:

                  - ToUpper: cambiará el nombre a todo mayúsculas.
                  - ToLower: cambiará el nombre a todo minúsculas.
                  - ToTitle: cambiará el nombre de forma que la primera letra de cada
                             palabra sea mayúscula y las restantes minúsculas. Este
                             es el caso predeterminado.

    -Info []
        Presenta mensajes y resumen de ejecución. Este parámetro admite los
        alias "R" y "Resumen".

    -NoBoolean []
        Evita la devolución booleana de la función. Este parámetro admite el
        alias "NB".

    
        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 --------------------------

    PS C:\>Set-AdUserNameCase "cn=filemón pi,ou=Agentes,dc=tia,dc=org"

    True

    En este ejemplo se cambia "filemón pi" a "Filemón Pi".

    -------------------------- EJEMPLO 2 --------------------------

    PS C:\>Set-AdUserNameCase "cn=filemón pi,ou=Agentes,dc=tia,dc=org" ToUpper

    True

    En este ejemplo se cambia "filemón pi" a "FILEMÓN PI".

    -------------------------- EJEMPLO 3 --------------------------

    PS C:\>Set-AdUserNameCase -User "cn=filemón pi,ou=Agentes,dc=tia,dc=org" -Case ToUpper

    True

    En este ejemplo se cambia "filemón pi" a "FILEMÓN PI".

    -------------------------- EJEMPLO 4 --------------------------

    PS C:\>Get-Content c:\listados\usrs_a_cambiar.txt | Set-AdUserNameCase

    En este ejemplo se cambia a título los nombres de los usuarios cuyos
          nombres distinguidos están contenidos, uno por línea, en el fichero de
          texto c:\listados\usrs_a_cambiar.txt. Se devolverá True en los éxitos y
          False en los fracasos.

    -------------------------- EJEMPLO 5 --------------------------

    PS C:\>$OU = [ADSI] "LDAP://ou=Agentes,dc=tia,dc=org"

    PS C:\>$Busc = [System.DirectoryServices.DirectorySearcher]$OU
    PS C:\>$Busc.Filter = "(&(objectClass=user)(objectCategory=person))"
    PS C:\>$Busc.SearchScope = "Subtree"
    PS C:\>$Busc.FindAll()| Set-AdUserNameCase -Info -NB

    Cambia a título los nombres de los usuarios obtenidos al realizar una
    búsqueda de usuarios en la unidad organizativa ou=Agentes,dc=tia,dc=org
    y todas las contenidas en la misma. Se mostrará un resumen por pantalla
    y se omitirá la devolución Booleana.

NOTAS
    Para ver los ejemplos, escriba: "get-help Set-AdUserNameCase -examples".
    Para obtener más información, escriba: "get-help Set-AdUserNameCase -detailed".
    Para obtener información técnica, escriba: "get-help Set-AdUserNameCase -full".
Set-AdUserAttributeCase
NOMBRE
    Set-AdUserAttributeCase

SINOPSIS
    Cambia el caso de atributos de un usuario de Active Directory.


SINTAXIS
    Set-AdUserAttributeCase [-User]  [[-Case] ] [-All] [-RDN] [-General] [-givenName] [-initials] [-sn]
     [-DisplayName] [-Description] [-physicalDeliveryOfficeName] [-Address] [-streetAddress] [-postOfficeBox] [-City] [
    -State] [-postalCode] [-Organization] [-Title] [-Department] [-Company] []


DESCRIPCIÓN
    Esta función permite cambiar el caso de determinados atributos de Active
    Directory. Un conjunto de switches permiten establecer qué cambios se
    producirán. Estos Switches permiten establecer que se cambien todos los
    atributos, sólo los de determinada pestaña de las propiedades del
    usuario o sólo un atributo en concreto. No son excluyentes uno de otro,
    si no al contrario, son acumulativos, lo que permite establecer con
    exactitud qué atributos se cambiarán. Las pestañas de las propiedades
    del usuario que se pueden establecer y sus atributos correspondientes
    son:

          - General: Nombre propio, iniciales, apellidos, nombre para
                     mostrar, descripción y oficina.
          - Address: Dirección (calle), apartado de correos, ciudad, estado
                     y código postal.
          - Organization: Cargo, departamento y compañía.

    Aparte de los anteriores atributos, se puede también cambiar el nombre
    del objeto usuario (esto es moverlo, pues cambia su RDN y por tanto su
    nombre distinguido) con el switch -RDN.

    La función permite tres tipos de objetos de entrada:

          - String: en este caso se está recibiendo una cadena con el nombre
                    distinguido del usuario.
          - DirectoryEntry: en este caso se está recibiendo el objeto
                            usuario directamente.
          - SearchResult: en este caso se está recibiendo el resultado de
                          una búsqueda realizada con un objeto
                          DirectorySearcher.

    La función admite canalización, lo que permite redireccionar un array de
    cadenas (cada elemento del array es el nombre distinguido de un
    usuario), un fichero de texto (leído con Get-Content) con un nombre
    distinguido por línea, una colección de objetos DirectoryEntry de
    usuario o la devolución del método FindAll de un objeto
    DirectorySearcher, procesándose todos los usuarios implicados.


PARÁMETROS
    -User 
        Nombre distinguido, objeto DirectoryEntry de usuario u objeto
        SearchResult de usuario del usuario a ser cambiado. Este parámetro
        admite los alias "U" y "Usuario".

    -Case 
        Caso que se establecerá. Puede ser ToUpper (todo mayúsculas), ToLower
        (todo minúsculas) o ToTitle (primera letra de cada palabra mayúscula y
        el resto minúsculas). Si se omite se asume ToTitle.

    -All []
        Si se pasa este modificador, todos los atributos son cambiados, así
        como el RDN del usuario. Este parámetro admite los alias "A" y "Todo".

    -RDN []
        Si se pasa este modificador, se cambia el RDN del usuario (esto implica
        mover el usuario, pues cambia su nombre distinguido). Este parámetro
        admite los alias "CN" y "Mover".

    -General []
        Si se pasa este modificador, todos los atributos de la pestaña General
        de las propiedades del usuario son cambiados. Este parámetro admite el
        alias "G". Los atributos afectados son Nombre propio, Iniciales,
        Apellidos, Nombre para mostrar, Descripción y Oficina.

    -givenName []
        Si se pasa este modificador, se cambia el nombre propio del usuario.
        Este parámetro admite los alias "Nombre", "FirstName" y "FN".

    -initials []
        Si se pasa este modificador, se cambian las iniciales del usuario. Este
        parámetro admite los alias "I", "MN" e "Iniciales".

    -sn []
        Si se pasa este modificador, se cambian los apellidos del usuario. Este
        parámetro admite los alias "Apellidos" y "LastName".

    -DisplayName []
        Si se pasa este modificador, se cambia el nombre para mostrar del
        usuario. Este parámetro admite los alias "MostrarComo" y "DN".

    -Description []
        Si se pasa este modificador, se cambia la descripción del usuario. Este
        parámetro admite los alias "D" y "Descripcion".

    -physicalDeliveryOfficeName []
        Si se pasa este modificador, se cambia la oficina del usuario. Este
        parámetro admite los alias "Office", "Oficina" y "Off".

    -Address []
        Si se pasa este modificador, todos los atributos de la pestaña Address
        de las propiedades del usuario son cambiados. Este parámetro admite los
        alias "Direccion" y "Add". Los atributos implicados son Calle, Apartado
        de correos, Ciudad, Estado/Provincia y Código postal

    -streetAddress []
        Si se pasa este modificador, se cambia la dirección del usuario. Este
        parámetro admite los alias "Calle" y "Street".

    -postOfficeBox []
        Si se pasa este modificador, se cambia el apartado de correos del
        usuario. Este parámetro admite el alias "AppPostal".

    -City []
        Si se pasa este modificador, se cambia la ciudad del usuario. Este
        parámetro admite los alias "Ciudad" y "Locality".

    -State []
        Si se pasa este modificador, se cambia la provincia del usuario. Este
        parámetro admite los alias "Province" y "Provincia".

    -postalCode []
        Si se pasa este modificador, se cambia el código postal del usuario.
        Este parámetro admite los alias "ZIP" y "CodigoPostal".

    -Organization []
        Si se pasa este modificador, todos los atributos de la pestaña
        Organization de las propiedades del usuario son cambiados. Este
        parámetro admite los alias "Org" y "Organizacion". Los atributos
        implicados son: cargo, departamento y compañía.

    -Title []
        Si se pasa este modificador, se cambia el cargo del usuario. Este
        parámetro admite los alias "Titulo" y "Cargo".

    -Department []
        Si se pasa este modificador, se cambia el departamento del usuario.
        Este parámetro admite el alias "Departamento".

    -Company []
        Si se pasa este modificador, se cambia la compañía del usuario.

    
        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 --------------------------

    PS C:\>$DN = 'cn=Mortadelo,ou=Agentes,dc=tia,dc=org'

    PS C:\>Set-AdUserAttributeCase -User $DN -All

    Cambia todos los atributos del usuario a caso tipo título.

    -------------------------- EJEMPLO 2 --------------------------

    PS C:\>$DN = 'cn=Mortadelo,ou=Agentes,dc=tia,dc=org'

    PS C:\>Set-AdUserAttributeCase -User $DN -General -Case ToLower

    Cambia todos los atributos de la pestaña General del usuario a
    minúsculas.

    -------------------------- EJEMPLO 3 --------------------------

    PS C:\>$Lista = 'c:\listados\usuarioscambiar.txt'

    PS C:\>Get-Content $Lista | Set-AdUserAttributeCase -General -Case ToLower

    Cambia a minúsculas todos los atributos de la pestaña General de los
    usuarios cuyos nombres distinguidos están contenidos en el fichero
    c:\listados\usuarioscambiar.txt, uno por línea.

    -------------------------- EJEMPLO 4 --------------------------

    PS C:\>$OU = [ADSI] "LDAP://ou=Agentes,dc=tia,dc=org"

    PS C:\>$Busc = [System.DirectoryServices.DirectorySearcher]$OU
    PS C:\>$Busc.Filter = "(&(objectClass=user)(objectCategory=person))"
    PS C:\>$Busc.SearchScope = "Subtree"
    PS C:\>$Busc.FindAll()| Set-AdUserAttributeCase -G -Org

    Cambia a título todos los atributos de las pestañas General y
    Organization de los usuarios obtenidos al realizar una búsqueda de
    usuarios en la unidad organizativa ou=Agentes,dc=tia,dc=org y todas las
    contenidas en la misma.

NOTAS
    Para ver los ejemplos, escriba: "get-help Set-AdUserAttributeCase -examples".
    Para obtener más información, escriba: "get-help Set-AdUserAttributeCase -detailed".
    Para obtener información técnica, escriba: "get-help Set-AdUserAttributeCase -full".

Este es el código de los Cmdlets:

Function Set-Case([Parameter(Position=0,HelpMessage="Cadena a ser cambiada")]
                  [System.String]
                  $Value,
                  [Parameter(Position=1, `
                  HelpMessage="Caso a establecer (predeterminado `"ToTitle`")")]
                  [ValidateSet("ToLower", "ToTitle", "ToUpper")]
                  [System.String]
                  $Case = "ToTitle")
{
    # Si no se recibe una cadena vacía o un nulo.
    If([string]::IsNullOrEmpty($Value) -eq $false)
    {
        # La devolución de la función depende del caso.
        Switch($Case)
        {
            # Si el caso es ToLower, pasamos a minúsculas el texto.
            "ToLower"{$Value.ToLower()}
            # Si el caso es ToTitle, pasamos a titular el texto.
            "ToTitle"{(Get-Culture).TextInfo.ToTitleCase($Value.ToLower())}
            # Si el caso es ToUpper, pasamos a mayúsculas el texto.
            "ToUpper"{$Value.ToUpper()}
        }
    }
    # Si el texto recibido es nulo o cadena vacía la función devuelve el
    # texto intacto
    Else
    {
        $Value
    }
<#
    .SYNOPSIS
        Devuelve la cadena recibida modificada al caso establecido.

    .DESCRIPTION
        Esta función recibe una cadena y devuelve la misma cadena con el caso
        establecido en el parámetro "Case". Los casos posibles son:
        
            - ToLower: todo minúsculas ("este es un ejemplo").
            - ToUpper: todo mayúsculas ("ESTE ES UN EJEMPLO").
            - ToTitle (predeterminado): Primera letra de cada palabra en
                                        mayúscula, el resto en minúsculas ("Este
                                        Es Un Ejemplo").

    .PARAMETER Value
        Cadena a ser cambiada.

    .PARAMETER Case
        Caso a establecer. Los valores admitidos son "ToLower", "ToTitle" y
        "ToUpper" (predeterminado "ToTitle").
        
    .EXAMPLE
        PS C:\> Set-Case "esto es un ejemplo"
        Esto Es Un Ejemplo
        
        Pone en caso titular la cadena "esto es un ejemplo".

    .EXAMPLE
        PS C:\> Set-Case "esto es un ejemplo" -Case ToUpper
        ESTO ES UN EJEMPLO
        
        Pone en mayúsculas la cadena "esto es un ejemplo".

    .EXAMPLE
        PS C:\> Set-Case "ESTO ES UN EJEMPLO" -Case ToLower
        esto es un ejemplo
        
        Pone en minúsculas la cadena "ESTO ES UN EJEMPLO".

    .INPUTS
        System.String

    .OUTPUTS
        System.String

    .LINK
        https://urpiano.wordpress.com

    .LINK
        http://freyes.svetlian.com

    .NOTES
        Author: Fernando Reyes López MS-MVP
        © Mayo de 2012

#>

}

Function Set-AdUserNameCase
{
    [CmdletBinding()]
    param
        (
            [Parameter(Position=0, Mandatory=$true,ValueFromPipeLine=$true,`
                       HelpMessage="Usuario a ser cambiado.")]
            [Alias("U","Usr","Usuario")]
               $User,
            [Parameter(Position=1, `
                  HelpMessage="Caso a establecer (predeterminado `"ToTitle`")")]
            [ValidateSet("ToLower", "ToTitle", "ToUpper")]
            [System.String]
            $Case = "ToTitle" ,
            [Parameter(HelpMessage="Presenta mensajes y resumen de ejecución")]
            [Alias("R","Resumen")]
            [Switch]
            $Info,
           [Parameter(HelpMessage="Evita la devolución booleana de la función")]
            [Alias("NB")]
            [Switch]
            $NoBoolean
            
        )
    Begin
    {
        # Almacenamos la configuración del comportamiento ante errores que no
        # interrumpen y la establecemos para que sí interrumpan; esto nos
        # permitirá el uso de Try/Catch con este tipo de errores.
        $Accion = $ErrorActionPreference
        $ErrorActionPreference = "Stop"
        
        # Iniciamos contadores
        $Procesados = 0
        $Exitos = 0
        $Fracasos = 0
        $NoEncontrados = 0
    }
    Process
    {
        # Obtenemos el tipo de dato recibido como parámetro User
        $Tipo = $User.PsBase.GetType()
        # Revisaremos el tipo para obrar en consecuencia
        Switch($Tipo.Name)
        {
            # Si el tipo es String, se trata de un nombre distinguido que
            # utilizaremos para obtener el objeto del usuario en AD, si es un objeto
            # SearchResult su propiedad Rath contiene la URI LDAP del usuario, que
            # utilizaremos para obtenerlo.
            {$Tipo.Name -eq "String" -or $Tipo.Name -eq "SearchResult"}
            {
                # Si es una cadena, es necesario preceder con el identificador de
                # protocolo al nombre distinguido.
                If($Tipo.Name -eq "String")
                {
                    # Evitaremos las líneas vacías del fichero
                    If([String]::IsNullOrEmpty($User.Trim(' ')) -eq $True)
                    {
                        Return
                    }
                    Else
                    {
                        $Ruta = "LDAP://$User"
                    }
                }
                # Si es un objeto SearchResult, la propiedad Path permite
                # obtener el usuario usándola como URI LDAP 
                Else
                {
                    $Ruta = $User.Path
                }
                # Incrementamos el contador de procesados.
                $Procesados++
                # Intentamos obtener el usuario.
                $Usuario = New-Object `
                            System.DirectoryServices.DirectoryEntry($Ruta)
                
                # Si el nombre es nulo, significa que no se ha podido obtener el
                # usuario
                If($Usuario.Name -eq $null)
                {
                    # Si hay que mostrar información, mostramos el error.
                    If($Info)
                    {
                        Write-Host -ForegroundColor Red -BackgroundColor Black `
     "No se ha podido obtener el usuario $($Ruta.SubString(7,$Ruta.Length - 7))"
                    }
                    # Incrementamos el contador de no encontrados.
                    $NoEcontrados++
                    # Si hay que omitir la devolución booleana la omitimos.
                    If($NoBoolean)
                    {
                        $Return
                    }
                    Else
                    {
                        Return $false
                    }
                }
            }
            # Si el tipo de usuario es DirectoryEntry lo asignamos directamente, ya
            # que es el tipo que utiliza la función para realizar el cambio de
            # nombre
            "DirectoryEntry"
            {
                $Usuario = $User
                $Procesados++
            }
            # Si se ha recibido otro tipo distinto de los tres anteriores se sale
            # de la función con false y se muestra un mensaje indicando que no está
            # soportado
            Default
            {
                # Incrementamos los contadores de procesados y de fracasos.
                $Procesados++
                $Fracasos++
                # Si hay que mostrar información, mostramos el error.
                If($Info)
                {
                    Write-Host -ForegroundColor Red -BackgroundColor Black `
                   "El tipo $($Tipo.FullName) no está soportado como parámetro User"
                }
                # Si hay que omitir la devolución booleana la omitimos.
                If($NoBoolean)
                {
                    $Return
                }
                Else
                {
                    Return $false
                }
            }
        }
        # Intentamos obtener el contenedor en el que está el usuario
        Try
        {
            $OU = $Usuario.PsBase.Get_Parent()
        }
        # Si no se ha podido obtener el contenedor, se sale de la función
        Catch
        {
            # Si hay que mostrar información, mostramos el error.
            If($Info)
            {
                Write-Host -ForegroundColor Red -BackgroundColor Black `
                  "Error al obtener el contenedor de $($User.distinguishedName)"
            }
            # Incrementamos el contador de no encontrados.
            $NoEncontrados++
            # Si hay que omitir la devolución booleana la omitimos.
            If($NoBoolean)
            {
                $Return
            }
            Else
            {
                Return $false
            }
        }
        # Una vez tenemos el usuario vamos a obtener el resultado de aplicar el caso
        # a su nombre
        Switch($Case)
        {
            # Mayúsculas
            "ToUpper"
            {
                $Nombre = ([string]$Usuario.Name).ToUpper()
            }
            # Minúsculas
            "ToLower"
            {
                $Nombre = ([string]$Usuario.Name).ToLower()
            }
            # Titular
            "ToTitle"
            {
                $Nombre = (Get-Culture).TextInfo.ToTitleCase(`
                                                  ([string]$Usuario.Name).ToLower())
            }
        }
        # Intentamos renombrar al usuario (realmente esto implica moverlo, dado que
        # está cambiando el RDN).
        Try
        {
            $Usuario.PsBase.MoveTo($OU,"CN=$Nombre")
        }
        # Si se produce error se sale de la función devolviendo False.
        Catch
        {
            # Incrementamos el contador de fracasos.
            $Fracasos++
            # Si hay que mostrar información, mostramos el error.
            If($Info)
            {
                Write-Host -ForegroundColor Red -BackgroundColor Black `
                     "Error al intentar renombrar $($Usuario.Name) como $Nombre"
                Write-Host $Error[0]
            }
            # Si hay que omitir la devolución booleana la omitimos.
            If($NoBoolean)
            {
                $Return
            }
            Else
            {
                Return $false
            }
        }
        # Restauramos el comportamiento ante errores que no interrumpen.
        $Exitos++
        # Si hay que mostrar información, mostramos el éxito.
        If($Info)
        {
            Write-Host -ForegroundColor Green -BackgroundColor DarkBlue `
                 "$($Usuario.Name)`: Cambiado con éxito"
        }
        # Todo ha ido bien, la función devuelve True.
        # Si hay que omitir la devolución booleana la omitimos.
        If($NoBoolean)
        {
            $Return
        }
        Else
        {
            Return $true
        }
    }
    End
    {
        # Restauramos el comportamiento ante errores que no interrumpen
        $ErrorActionPreference = $Accion
        # Si hay que mostrar información, mostramos el resumen.
        If($Info)
        {
            Write-Host
            Write-Host "Usuarios procesados                :   $Procesados"
            Write-Host "Usuarios no encontrados            :   $NoEncontrados"
            Write-Host "Usuarios cambiados con éxito       :   $Exitos"
            Write-Host "Usuarios que no se pudieron cambiar:   $Fracasos"
        }
    }
<#
    .SYNOPSIS
        Cambia el caso del nombre de un usuario.

    .DESCRIPTION
        Esta función permite cambiar el nombre (RelativeDistinguishedName o RDN)
        de un  usuario de active directory para que cumpla con el caso recibido
        como parámetro. Los casos posibles son:
        
            - ToLower: todo minúsculas ("pi, filemon").
            - ToUpper: todo mayúsculas ("PI, FILEMON").
            - ToTitle (predeterminado): Primera letra de cada palabra mayúscula,
                                        el resto en minúsculas ("Pi, Filemon").

        La función permite canalización, lo que hace que se puedan procesar en
        bloque varios usuarios. Además permite varios tipos de objeto para el
        parámetro de usuario (cadena, DirectoryEntry y SearchResult) lo junto
        con la canalización permite redireccionar, por ejemplo,  un fichero de
        texto con los nombres distinguidos de los usuarios, uno por línea, a ser
        cambiados, o los resultados obtenidos con un objeto DirectorySearcher de
        una búsqueda LDAP de usuarios.
        

    .PARAMETER  User
        Usuario al que se cambiará el nombre. Puede recibir tres tipos de
        objeto:
        - Cadena: en este caso se debe tratar del nombre distinguido de un
                  usuario.
        - DirectoryEntry: en este caso se tratará de un objeto usuario
                          directamente.
        - SearchResult: en este caso se trata de un objeto obtenido al realizar,
                        con un objeto DirectorySearcher, una consulta LDAP de
                        usuarios.
        Este parámetro permite canalización y los alias "U", "Usr" y "Usuario".

    .PARAMETER  Case
        Caso que se establecerá en el nombre del usuario; los tipos son:
        
            - ToUpper: cambiará el nombre a todo mayúsculas.
            - ToLower: cambiará el nombre a todo minúsculas.
            - ToTitle: cambiará el nombre de forma que la primera letra de cada
                       palabra sea mayúscula y las restantes minúsculas. Este
                       es el caso predeterminado.

    .PARAMETER Info
        Presenta mensajes y resumen de ejecución. Este parámetro admite los
        alias "R" y "Resumen".

    .PARAMETER NoBoolean
        Evita la devolución booleana de la función. Este parámetro admite el
        alias "NB".

    .EXAMPLE
        PS C:\> Set-AdUserNameCase "cn=filemón pi,ou=Agentes,dc=tia,dc=org"
        True
        
        En este ejemplo se cambia "filemón pi" a "Filemón Pi".

    .EXAMPLE
        PS C:\> Set-AdUserNameCase "cn=filemón pi,ou=Agentes,dc=tia,dc=org" ToUpper
        True
        
        En este ejemplo se cambia "filemón pi" a "FILEMÓN PI".

    .EXAMPLE
        PS C:\> Set-AdUserNameCase -User "cn=filemón pi,ou=Agentes,dc=tia,dc=org" -Case ToUpper
        True
        
        En este ejemplo se cambia "filemón pi" a "FILEMÓN PI".

    .EXAMPLE
        PS C:\> Get-Content c:\listados\usrs_a_cambiar.txt | Set-AdUserNameCase
        En este ejemplo se cambia a título los nombres de los usuarios cuyos
        nombres distinguidos están contenidos, uno por línea, en el fichero de
        texto c:\listados\usrs_a_cambiar.txt. Se devolverá True en los éxitos y
        False en los fracasos.

    .EXAMPLE
        PS C:\>$OU = [ADSI] "LDAP://ou=Agentes,dc=tia,dc=org"
        PS C:\>$Busc = [System.DirectoryServices.DirectorySearcher]$OU
        PS C:\>$Busc.Filter = "(&(objectClass=user)(objectCategory=person))"
        PS C:\>$Busc.SearchScope = "Subtree"
        PS C:\>$Busc.FindAll()| Set-AdUserNameCase -Info -NB
        
        Cambia a título los nombres de los usuarios obtenidos al realizar una
        búsqueda de usuarios en la unidad organizativa ou=Agentes,dc=tia,dc=org
        y todas las contenidas en la misma. Se mostrará un resumen por pantalla
        y se omitirá la devolución Booleana.

    .INPUTS
        System.String, System.DirectoryServices.DirectoryEntry,
        System.DirectoryServices.SearchResult

    .OUTPUTS
        System.Boolean

    .LINK
        https://urpiano.wordpress.com

    .LINK
        http://freyes.svetlian.com

    .NOTES
        Author: Fernando Reyes López MS-MVP
        © Mayo de 2012

#>
}

Function Set-AdUserAttributeCase {
    [CmdletBinding()]
    param(
        [Parameter(Position=0, Mandatory=$true,ValueFromPipeLine=$true,`
                   HelpMessage="Usuario a ser cambiado.")]
        [Alias("U","Usuario")]
        $User,
        [Parameter(Position=1,`
           HelpMessage="Caso que se establecerá (ToUpper, ToLower o ToTitle).")]
        [ValidateSet("ToLower", "ToTitle", "ToUpper")]
        [System.String]
        $Case = "ToTitle",
        [parameter(`
        HelpMessage="Cambia todos los atributos del usuario, incluído el RDN.")]
        [Alias("A","Todo")]
        [Switch]
        $All,
        [parameter(HelpMessage="Cambia el RDN del usuario.")]
        [Alias("CN","Mover")]
        [Switch]
        $RDN,
        [parameter(`
        HelpMessage="Cambia todos los atributos de la pestaña General del usuario.")]
        [Alias("G")]
        [Switch]
        $General,
        [parameter(HelpMessage="Cambia el nombre propio del usuario.")]
        [Alias("Nombre","FirstName","FN")]
        [Switch]
        $givenName,
        [parameter(HelpMessage="Cambia las iniciales del usuario.")]
        [Alias("I","MN","Iniciales")]
        [Switch]
        $initials,    
        [parameter(HelpMessage="Cambia los apellidos del usuario.")]
        [Alias("Apellidos","LastName")]
        [Switch]
        $sn,
        [parameter(HelpMessage="Cambia el nombre para mostrar del usuario.")]
        [Alias("MostrarComo","DN")]
        [Switch]
        $DisplayName,    
        [parameter(HelpMessage="Cambia la descripción del usuario.")]
        [Alias("D","Descripcion")]
        [Switch]
        $Description,
        [parameter( HelpMessage="Cambia la oficina del usuario.")]
        [Alias("Office","Oficina","Off")]
        [Switch]
        $physicalDeliveryOfficeName,
        [parameter(`
   HelpMessage="Cambia todos los atributos de la pestaña Address del usuario.")]
        [Alias("Direccion","Add")]
        [Switch]
        $Address,
        [parameter(HelpMessage="Cambia la dirección del usuario.")]
        [Alias("Calle","Street")]
        [Switch]
        $streetAddress,
        [parameter(HelpMessage="Cambia el apartado de correos del usuario.")]
        [Alias("AppPostal")]
        [Switch]
        $postOfficeBox,
        [parameter(HelpMessage="Cambia la ciudad del usuario.")]
        [Alias("Ciudad","Locality")]
        [Switch]
        $City,    
        [parameter(HelpMessage="Cambia la provincia del usuario.")]
        [Alias("Province","Provincia")]
        [Switch]
        $State,
        [parameter(HelpMessage="Cambia el código postal del usuario.")]
        [Alias("ZIP","CodigoPostal")]
        [Switch]
        $postalCode,
        [parameter(`
HelpMessage="Cambia todos los atributos de la pestaña Organization del usuario.")]
        [Alias("Org","Organizacion")]
        [Switch]
        $Organization,
        [parameter(HelpMessage="Cambia el cargo del usuario.")]
        [Alias("Titulo","Cargo")]
        [Switch]
        $Title,
        [parameter(HelpMessage="Cambia el departamento del usuario.")]
        [Alias("Departamento")]
        [Switch]
        $Department,
        [parameter(HelpMessage="Cambia la compañía del usuario.")]
        [Switch]
        $Company
        )
    # Bloque de inicio de la función, en el que se establece el comportamiento
    # ante errores que no detienen la ejecución para que sí lo hagan (permite
    # el uso de Try/Catch en este tipo de errores) y se inician las variables
    # de recuento del proceso
    Begin
    {
        # Almacenamos la acción ante errores que no provocan terminación.
        $AccionError = $ErrorActionPreference
        # Hacemos que los errores que no provocan terminación sí lo hagan. Esto
        # lo hacemos para que funcione Try/Catch con ellos.
        $ErrorActionPreference = "Stop"
    
        # Iniciamos los recuentos de usuarios procesados. En primer lugar los
        # usuarios procesados.
        $Procesados = 0
        # El número de usuarios procesados con éxito. Significa que no se
        # produjeron errores, independientemente de si se realizaron cambios o
        # no.
        $Exitos = 0
        # El número de usuarios procesados en los que se produjo algún error.
        $Fracasos = 0
        # Número de usuarios recibidos que no se encontraron en Active
        # Directory.
        $NoEncontrados = 0
        # Número de usuarios en los que no era necesario efectuar ningún cambio,
        # dado que el caso de sus atributos ya corresponde con el caso que se
        # desea establecer.
        $SinCambiosARealizar = 0
        # Número total de usuarios en los que se efectuó algún cambio.
        $TotalCambiados = 0
        
        # Volcamos los encabezados.
        "Usuario`tResultado"
    }
    # Bloque de proceso de usuario.
    Process
    {
        # Incrementamos el contador de procesados.
        $Procesados++
        
        # Revisamos el tipo de origen que trae el usuario. En primer lugar si
        # se trata del objeto usuario en sí.
        If(($User.GetType()).Name -eq "DirectoryEntry")
        {
            # Asignamos el usuario directamente.
            $Usuario = $User
        }
        # Se mira si se trata de una cadena (se supone que es el nombre
        # distinguido del usuario) o un objeto SearchResult (obtenido al
        # efectuar una búsqueda con un objeto DirectorySearcher).
        ElseIf(($User.GetType()).Name -eq "String" -or `
                ($User.GetType()).Name -eq "SearchResult")
        {
            If(($User.GetType()).Name -eq "String")
            {
                # Por si el usuario proviene de una canalización de cadenas,
                # ya sea de un array directamente o de un fichero de texto leído
                # con Get-Content, y el elemento actual es una cadena vacía, en
                # este If se saltará al siguiente elemento, sin tener en cuenta
                # este elemento en los recuentos. Para evitar el recuento del
                # elemento, se resta uno al contador de procesados.
                If([System.String]::IsNullOrEmpty($User.Trim(' ')))
                {
                    $Procesados--
                    Return
                }
                # Si se trata de una cadena, establecemos como ruta LDAP del
                # objeto la cadena recibida con el identificador de protocolo
                # LDAP delante.
                $Ruta = "LDAP://$User"
            }
            Else
            {
                # Si se trata de un SearchResult, su propiedad Path ya trae la
                # ruta LDAP perfectamente montada, y por tanto la asignamos sin
                # más.
                $Ruta = $User.Path
            }
            # Obtendremos el usuario; por si hay errores lo haremos en un Try.
            Try
            {
                # Obtenemos el usuario.
                $Usuario = New-Object `
                             System.DirectoryServices.DirectoryEntry($Ruta)
            }
            Catch
            {
                # El usuario no se ha podido obtener. Incrementamos el número
                # de usuarios no encontrados.
                $NoEncontrados++
                # Obtenemos el índice de último error.
                $Indice = $Error.Count -1
                # Iniciamos el mensaje de error.
                $Mensaje = ""
                # Montamos el identificador del error en el mensaje.
                $Mensaje = "$($error[$Indice].FullyQualifiedErrorId) ("
                # Montamos el mensaje de error.
                $Mensaje = "$Mensaje$($error[$Indice].Message.ToString()))"
                # Montamos la salida del log.
                "$User`tNo Encontrado`: $Mensaje"
                # Vamos al siguiente usuario.
                Return
            }
        }
        # Iniciamos la booleana que registrará si se ha producido algún cambio.
        $HayCambios = $false
        
        # Iremos cambiando los atributos según pestaña de las propiedades del
        # objeto usuario en Active Directory Users and Computers. En todos los
        # atributos, sólo los cambiaremos si no presentan el caso que se desea
        # establecer (si se van a establecer mayúsculas y ya está está en
        # mayúsculas no se cambiarán). Para saber si se han producido cambios,
        # en el caso de que se produzca un cambio a continuación se pondrá a
        # $true la variable $HayCambios.
        
        # En primer lugar la pestaña general. Primero el atributo de nombre
        # propio.
        If($givenName -or $All -or $General `
           -and ([string]::IsNullOrEmpty($Usuario.givenName) -eq $false)`
           -and ((Set-Case $Usuario.givenName $Case) -cne $Usuario.givenName))
        {
            $Usuario.Put("givenName",(Set-Case $Usuario.givenName $Case))
            $HayCambios = $true
        }
        # Ahora las iniciales
        If($initials -or $All -or $General `
           -and ([string]::IsNullOrEmpty($Usuario.initials) -eq $false)`
           -and ((Set-Case $Usuario.initials $Case) -cne $Usuario.initials))
        {
            $Usuario.Put("initials",(Set-Case $Usuario.initials $Case))
            $HayCambios = $true
        }
        # Ahora los apellidos
        If($sn -or $All -or $General `
           -and ([string]::IsNullOrEmpty($Usuario.sn) -eq $false)`
           -and ((Set-Case $Usuario.sn $Case) -cne $Usuario.sn))
        {
            $Usuario.Put("sn",(Set-Case $Usuario.sn $Case))
            $HayCambios = $true
        }
        # Ahora el nombre para mostrar
        If($DisplayName -or $All -or $General `
           -and ([string]::IsNullOrEmpty($Usuario.displayName) -eq $false)`
           -and ((Set-Case $Usuario.displayName $Case) -cne $Usuario.displayName))
        {
            $Usuario.Put("displayName",(Set-Case $Usuario.displayName $Case))
            $HayCambios = $true
        }
        # Ahora la descripción
        If($Description -or $All -or $General `
           -and ([string]::IsNullOrEmpty($Usuario.Description) -eq $false)`
           -and ((Set-Case $Usuario.Description $Case) -cne $Usuario.Description))
        {
            $Usuario.Put("Description",(Set-Case $Usuario.Description $Case))
            $HayCambios = $true
        }
        # Ahora la oficina
        If($physicalDeliveryOfficeName -or $All -or $General `
           -and ([string]::IsNullOrEmpty($Usuario.physicalDeliveryOfficeName) `
                                                                    -eq $false)`
           -and ((Set-Case $Usuario.physicalDeliveryOfficeName $Case) -cne `
                                           $Usuario.physicalDeliveryOfficeName))
        {
            $Usuario.Put("physicalDeliveryOfficeName", `
                           (Set-Case $Usuario.physicalDeliveryOfficeName $Case))
            $HayCambios = $true
        }
        # Ahora se procesan las propiedades de la pestaña Address. En primer
        # lugar la calle
        If($streetAddress -or $All -or $Address `
           -and ([string]::IsNullOrEmpty($Usuario.streetAddress) -eq $false)`
           -and ((Set-Case $Usuario.streetAddress $Case) -cne `
                                                        $Usuario.streetAddress))
        {
            $Usuario.Put("streetAddress", `
                                        (Set-Case $Usuario.streetAddress $Case))
            $HayCambios = $true
        }
        # Ahora el apartado de correos
        If($postOfficeBox -or $All -or $Address `
           -and ([string]::IsNullOrEmpty($Usuario.postOfficeBox) -eq $false)`
           -and ((Set-Case $Usuario.postOfficeBox $Case) -cne `
                                                        $Usuario.postOfficeBox))
        {
            $Usuario.Put("postOfficeBox", `
                                        (Set-Case $Usuario.postOfficeBox $Case))
            $HayCambios = $true
        }
        # Ahora la ciudad
        If($City -or $All -or $Address `
           -and ([string]::IsNullOrEmpty($Usuario.l) -eq $false)`
           -and ((Set-Case $Usuario.l $Case) -cne $Usuario.l))
        {
            $Usuario.Put("l",(Set-Case $Usuario.l $Case))
            $HayCambios = $true
        }
        # Ahora el estado/provincia
        If($State -or $All -or $Address `
           -and ([string]::IsNullOrEmpty($Usuario.st) -eq $false)`
           -and ((Set-Case $Usuario.st $Case) -cne $Usuario.st))
        {
            $Usuario.Put("st",(Set-Case $Usuario.st $Case))
            $HayCambios = $true
        }
        # Ahora el código postal
        If($postalCode -or $All -or $Address `
           -and ([string]::IsNullOrEmpty($Usuario.postalCode) -eq $false)`
           -and ((Set-Case $Usuario.postalCode $Case) -cne $Usuario.postalCode))
        {
            $Usuario.Put("postalCode",(Set-Case $Usuario.postalCode $Case))
            $HayCambios = $true
        }
        # Ahora se procesan las propiedades de la pestaña Organization. En
        # primer lugar el título
        If($Title -or $All -or $Organization `
           -and ([string]::IsNullOrEmpty($Usuario.title) -eq $false)`
           -and ((Set-Case $Usuario.title $Case) -cne $Usuario.title))
        {
            $Usuario.Put("title",(Set-Case $Usuario.title $Case))
            $HayCambios = $true
        }
        # Ahora el departamento
        If($Department -or $All -or $Organization `
           -and ([string]::IsNullOrEmpty($Usuario.department) -eq $false)`
           -and ((Set-Case $Usuario.department $Case) -cne $Usuario.department))
        {
            $Usuario.Put("department",(Set-Case $Usuario.department $Case))
            $HayCambios = $true
        }
        # Por último la compañía
        If($Company -or $All -or $Organization `
           -and ([string]::IsNullOrEmpty($Usuario.company) -eq $false)`
           -and ((Set-Case $Usuario.company $Case) -cne $Usuario.company))
        {
            $Usuario.Put("company",(Set-Case $Usuario.company $Case))
            $HayCambios = $true
        }
        # Se realizarán los cambios si es que se han producido. También se
        # entrará en este If si hay que cambiar el RDN y no es el actual igual
        # al resultante de aplicar el caso establecido.
        If($HayCambios -or (($All -or $RDN) -and `
                   ((Set-Case $Usuario.Name -Case $Case) -cne $Usuario.Name)))
        {
            # Tanto el guardar los cambios producidos hasta ahora como el cambio
            # del RDN los haremos en un Try/Catch.
            Try
            {
                # Con esta booleana controlaremos si se han producido cambios.
                $Control = $false
                # Si se han producido cambios en los atributos, los guardamos
                If($HayCambios)
                {
                    $Usuario.SetInfo()
                    # Marcamos que ha habido cambios.
                    $Control = $true
                }
                # Si hay que cambiar el RDN.
                If(($All -or $RDN) -and `
                   ((Set-Case $Usuario.Name -Case $Case) -cne $Usuario.Name))
                {
                    # Cambiamos el RDN llamando a la función correspondiente,
                    # enviando la devolución de la misma al limbo :-)
                    Set-AdUserNameCase $Usuario -NoBoolean -Case $Case
                    # Marcamos que ha habido cambios.
                    $Control = $true
                }
                # Como todo ha ido bien incrementamos el contador de éxitos.
                $Exitos++
                
                # Si se ha producido algún cambio.
                If($Control)
                {
                    # Incrementamos el contador de usuarios cambiados
                    $TotalCambiados++
                    # Volcamos el resultado
                    "$($Usuario.Name)`tCambiado"
                }
                # Si no se han producido cambios.
                Else
                {
                    # Incrementamos el contador de usuarios que no requerían
                    # cambios.
                    $SinCambiosARealizar++
                    # Volcamos el resultado.
                    "$($Usuario.Name)`tNo Había cambios"
                }
            }
            # Si se produce error.
            Catch
            {
                # Incrementamos el contador de fracasos.
                $Fracasos++
                # Obtenemos el índice del último error.
                $Indice = $Error.Count -1
                # Iniciamos el mensaje de error.
                $Mensaje = ""
                # Ponemos el identificador de error en el mensaje.
                $Mensaje = "$($Error[$Indice].FullyQualifiedErrorId) ("
                # Si hay mensaje en el error, lo agregamos al mensaje. 
                If($Error[$Indice].Message -ne $null)
                {
                    $Mensaje = "$Mensaje$($Error[$Indice].Message.ToString()))"
                }
                # si no hay mensajer en el error, terminamos el mensaje.
                Else
                {
                    $Mensaje = "$Mensaje)"
                }
                # Volcamos la información en el log.
                "$($Usuario.Name)`tNo Cambiado`: $Mensaje"
            }
        }
        # El usuario no tenía cambios que ser realizados.
        Else
        {
            # Incrementamos el contador de usuario que no debían ser cambiados.
            $SinCambiosARealizar++
            # Incrementamos el contador de usuarios procesados sin errores.
            $Exitos++
            # Volcamos la información en el log.
            "$($Usuario.Name)`tNo Había cambios"
        }
    }
    End
    {
        # Restauramos la acción ante errores que no interrumpen
        $ErrorActionPreference = $AccionError
        
        # Mostramos los recuentos si se ha procesado al menos un usuario.
        If($Procesados -gt 0)
        {
            # Mensaje de procesados si hay más de uno.
            If($Procesados -gt 1)
            {
                Write-Host "Procesados $Procesados usuarios"
            }
            # Mensaje de procesados si sólo hay uno.
            Else
            {
                 Write-Host "Procesado $Procesados usuario"
            }
        }
        # No se han procesado usuario, se muestra el mensaje correspondiente.
        Else
        {
            Write-Host "No se han procesado ningún usuario"
            Break
        }
        # Si no se han encontrado más de un usuario, se muestra el mensaje
        # correspondiente.
        If($NoEncontrados -gt 1)
        {
            Write-Host "$NoEncontrados usuarios no se pudieron encontrar"
        }
        # Si no se ha encontrado un usuario, se muestra el mensaje
        # correspondiente.
        ElseIf($NoEncontrados -eq 1)
        {
            Write-Host "$NoEncontrados usuario no se pudo encontrar"
        }
        # Si se han encontrado todos los usuarios, se muestra el mensaje
        # correspondiente.
        Else
        {
            Write-Host "Todos los usuarios se pudieron encontrar"
        }
        # Si se ha procesado sin errores más de un usuario, se muestra el
        # mensaje correspondiente.
        If($Exitos -gt 1)
        {
            Write-Host "$Exitos usuarios procesados con éxito"
        }
        # Si se ha procesado sin errores un usuario, se muestra el mensaje
        # correspondiente.
        ElseIf($Exitos -eq 1)
        {
            Write-Host "$Exitos usuario procesado con éxito"
        }
        # Si no hay usuarios procesados sin errores, se muestra el mensaje
        # correspondiente.
        Else
        {
            Write-Host "Ningún usuario se ha procesado con éxito"
        }
        # Si se ha procesado con errores más de un usuario, se muestra el
        # mensaje correspondiente.
        If($Fracasos -gt 1)
        {
            Write-Host "$Fracasos usuarios no se pudieron cambiar"
        }
        # Si se ha procesado con errores un usuario, se muestra el mensaje
        # correspondiente.
        ElseIf($Fracasos -eq 1)
        {
            Write-Host "$Fracasos usuario no se pudo cambiar"
        }
        # Si no hay usuarios procesados con errores, se muestra el mensaje
        # correspondiente.
        Else
        {
            Write-Host "No falló el cambio de ningún usuario"
        }
        # Si se han cambiado más de un usuario, se muestra el mensaje
        # correspondiente.
        If($TotalCambiados -gt 1)
        {
            Write-Host "$TotalCambiados usuarios cambiados"
        }
        # Si se ha cambiado sólo un usuario, se muestra el mensaje
        # correspondiente.
        ElseIf($TotalCambiados -eq 1)
        {
            Write-Host "$TotalCambiados usuario cambiados"
        }
        # Si ningún usuario se ha cambiado, se muestra el mensaje
        # correspondiente.
        Else
        {
            Write-Host "Ningún usuario se ha cambiado"
        }
        # Si no requería cambios más de un usuario, se muestra el mensaje
        # correspondiente.
        If($SinCambiosARealizar -gt 1)
        {
            Write-Host "$SinCambiosARealizar usuarios no tenían cambios que realizar"
        }
        # Si no requería cambios un solo usuario, se muestra el mensaje
        # correspondiente.
        ElseIf($SinCambiosARealizar -eq 1)
        {
            Write-Host "$SinCambiosARealizar usuario no tenía cambios que realizar"
        }
        # Si todos los usuarios requerían cambios, se muestra el mensaje
        # correspondiente.
        Else
        {
            Write-Host "Ningún usuario no tenía cambios que realizar"
        }
    }
<#
    .SYNOPSIS
        Cambia el caso de atributos de un usuario de Active Directory.

    .DESCRIPTION
        Esta función permite cambiar el caso de determinados atributos de Active
        Directory. Un conjunto de switches permiten establecer qué cambios se
        producirán. Estos Switches permiten establecer que se cambien todos los
        atributos, sólo los de determinada pestaña de las propiedades del
        usuario o sólo un atributo en concreto. No son excluyentes uno de otro,
        si no al contrario, son acumulativos, lo que permite establecer con
        exactitud qué atributos se cambiarán. Las pestañas de las propiedades
        del usuario que se pueden establecer y sus atributos correspondientes
        son:
        
              - General: Nombre propio, iniciales, apellidos, nombre para
                         mostrar, descripción y oficina.
              - Address: Dirección (calle), apartado de correos, ciudad, estado
                         y código postal.
              - Organization: Cargo, departamento y compañía.
        
        Aparte de los anteriores atributos, se puede también cambiar el nombre
        del objeto usuario (esto es moverlo, pues cambia su RDN y por tanto su
        nombre distinguido) con el switch -RDN.
        
        La función permite tres tipos de objetos de entrada:
        
              - String: en este caso se está recibiendo una cadena con el nombre
                        distinguido del usuario.
              - DirectoryEntry: en este caso se está recibiendo el objeto
                                usuario directamente.
              - SearchResult: en este caso se está recibiendo el resultado de
                              una búsqueda realizada con un objeto
                              DirectorySearcher.
                              
        La función admite canalización, lo que permite redireccionar un array de
        cadenas (cada elemento del array es el nombre distinguido de un
        usuario), un fichero de texto (leído con Get-Content) con un nombre
        distinguido por línea, una colección de objetos DirectoryEntry de
        usuario o la devolución del método FindAll de un objeto
        DirectorySearcher, procesándose todos los usuarios implicados.

    .PARAMETER User
        Nombre distinguido, objeto DirectoryEntry de usuario u objeto
        SearchResult de usuario del usuario a ser cambiado. Este parámetro
        admite los alias "U" y "Usuario".

    .PARAMETER Case
        Caso que se establecerá. Puede ser ToUpper (todo mayúsculas), ToLower
        (todo minúsculas) o ToTitle (primera letra de cada palabra mayúscula y
        el resto minúsculas). Si se omite se asume ToTitle.

    .PARAMETER All
        Si se pasa este modificador, todos los atributos son cambiados, así
        como el RDN del usuario. Este parámetro admite los alias "A" y "Todo".

    .PARAMETER RDN
        Si se pasa este modificador, se cambia el RDN del usuario (esto implica
        mover el usuario, pues cambia su nombre distinguido). Este parámetro
        admite los alias "CN" y "Mover".

    .PARAMETER General
        Si se pasa este modificador, todos los atributos de la pestaña General
        de las propiedades del usuario son cambiados. Este parámetro admite el
        alias "G". Los atributos afectados son Nombre propio, Iniciales,
        Apellidos, Nombre para mostrar, Descripción y Oficina.

    .PARAMETER givenName
        Si se pasa este modificador, se cambia el nombre propio del usuario.
        Este parámetro admite los alias "Nombre", "FirstName" y "FN".

    .PARAMETER initials
        Si se pasa este modificador, se cambian las iniciales del usuario. Este
        parámetro admite los alias "I", "MN" e "Iniciales".

    .PARAMETER sn
        Si se pasa este modificador, se cambian los apellidos del usuario. Este
        parámetro admite los alias "Apellidos" y "LastName".

    .PARAMETER DisplayName
        Si se pasa este modificador, se cambia el nombre para mostrar del
        usuario. Este parámetro admite los alias "MostrarComo" y "DN".

    .PARAMETER Description
        Si se pasa este modificador, se cambia la descripción del usuario. Este
        parámetro admite los alias "D" y "Descripcion".

    .PARAMETER physicalDeliveryOfficeName
        Si se pasa este modificador, se cambia la oficina del usuario. Este
        parámetro admite los alias "Office", "Oficina" y "Off".

    .PARAMETER Address
        Si se pasa este modificador, todos los atributos de la pestaña Address
        de las propiedades del usuario son cambiados. Este parámetro admite los
        alias "Direccion" y "Add". Los atributos implicados son Calle, Apartado
        de correos, Ciudad, Estado/Provincia y Código postal

    .PARAMETER streetAddress
        Si se pasa este modificador, se cambia la dirección del usuario. Este
        parámetro admite los alias "Calle" y "Street".

    .PARAMETER postOfficeBox
        Si se pasa este modificador, se cambia el apartado de correos del
        usuario. Este parámetro admite el alias "AppPostal".

    .PARAMETER City
        Si se pasa este modificador, se cambia la ciudad del usuario. Este
        parámetro admite los alias "Ciudad" y "Locality".

    .PARAMETER State
        Si se pasa este modificador, se cambia la provincia del usuario. Este
        parámetro admite los alias "Province" y "Provincia".

    .PARAMETER postalCode
        Si se pasa este modificador, se cambia el código postal del usuario.
        Este parámetro admite los alias "ZIP" y "CodigoPostal".

    .PARAMETER Organization
        Si se pasa este modificador, todos los atributos de la pestaña
        Organization de las propiedades del usuario son cambiados. Este
        parámetro admite los alias "Org" y "Organizacion". Los atributos
        implicados son: cargo, departamento y compañía.

    .PARAMETER Title
        Si se pasa este modificador, se cambia el cargo del usuario. Este
        parámetro admite los alias "Titulo" y "Cargo".

    .PARAMETER Department
        Si se pasa este modificador, se cambia el departamento del usuario.
        Este parámetro admite el alias "Departamento".

    .PARAMETER Company
        Si se pasa este modificador, se cambia la compañía del usuario.
        
    .EXAMPLE
        PS C:\>$DN = 'cn=Mortadelo,ou=Agentes,dc=tia,dc=org'
        PS C:\>Set-AdUserAttributeCase -User $DN -All
        
        Cambia todos los atributos del usuario a caso tipo título.

    .EXAMPLE
        PS C:\>$DN = 'cn=Mortadelo,ou=Agentes,dc=tia,dc=org'
        PS C:\>Set-AdUserAttributeCase -User $DN -General -Case ToLower
        
        Cambia todos los atributos de la pestaña General del usuario a
        minúsculas.

    .EXAMPLE
        PS C:\>$Lista = 'c:\listados\usuarioscambiar.txt'
        PS C:\>Get-Content $Lista | Set-AdUserAttributeCase -General -Case ToLower
        
        Cambia a minúsculas todos los atributos de la pestaña General de los
        usuarios cuyos nombres distinguidos están contenidos en el fichero
        c:\listados\usuarioscambiar.txt, uno por línea.

    .EXAMPLE
        PS C:\>$OU = [ADSI] "LDAP://ou=Agentes,dc=tia,dc=org"
        PS C:\>$Busc = [System.DirectoryServices.DirectorySearcher]$OU
        PS C:\>$Busc.Filter = "(&(objectClass=user)(objectCategory=person))"
        PS C:\>$Busc.SearchScope = "Subtree"
        PS C:\>$Busc.FindAll()| Set-AdUserAttributeCase -G -Org
        
        Cambia a título todos los atributos de las pestañas General y
        Organization de los usuarios obtenidos al realizar una búsqueda de
        usuarios en la unidad organizativa ou=Agentes,dc=tia,dc=org y todas las
        contenidas en la misma.

    .NOTES
        Author: Fernando Reyes López © 05/2012

    .INPUTS
        System.String,System.DirectoryServices.DirectoryEntry,
        System.DirectoryServices.SearchResult
    
    .OUTPUTS
        System.String

    .LINK
        http://freyes.svetlian.com

    .LINK
        https://urpiano.wordpress.com
        
#>
}

3 respuestas to “PowerShell: Cmdlets para cambiar el caso en atributos de usuario de Active Directory”

  1. John Ramirez said

    Caballero mil gracias por la info yo solo requiero cambiar el Display Name que segmento del script necesito correr

  2. sergio said

    solo quiero cambiar el IpPhone a los usuarios :)

Replica a urpiano Cancelar la respuesta