Exchange PowerShell – Manejo de objetos y “Pipelining”

Por Daniel Seveso

Luego del artículo de Introducción publicado anteriormente, veamos lo que para mi es la principal diferencias entre PowerShell y los shells disponibles hasta ahora.

Objetos en PowerShell

Los shells en general, poseen la funcionalidad de redirigir la salida de un comando a otro utilizando cadena de caracteres (proceso conocido como pipelining). Por ejemplo, el siguiente es el resultado de hacer pipelining de la salida del comando ipconfig en el shell de Windows, enviándola como entrada del comando “find”:

C:\>ipconfig /all | find "IP Address"

        IP Address. . . . . . . . . . . . : 192.168.0.7

La desventaja principal de este método es que debemos conocer exactamente cual será la salida del primer comando para no tener resultados inesperados.

En Exchange Management Shell (EMS) el pasaje de resultados de un comando a otro se realiza en el contexto de objetos. EMS usa información estructurada para representar los distintos ítems en la jerarquía de Exchange y a los que llamamos objetos. Cada objeto en EMS contiene información relacionada al ítem que representa y su estructura de datos. El objeto funciona como un una entidad que representa el ítem, por ejemplo, si modificamos un buzón desde EMS, estaremos trabajando con el objeto que representa ese buzón, no con el buzón en sí.

Al utilizar objetos para el pasaje de información entre comandos, evitamos los problemas de interpretación de la información, ya que todos los cmdlets conocerán el modelo de objetos a utilizar.

Un objeto está compuesto por tres tipos de información: el tipo de objeto, sus métodos y sus propiedades.

Tipo: El tipo de objeto identifica que clase de objeto es. Por ejemplo, en EMS, un objeto que representa un buzón es un objeto Mailbox, un objeto que representa un archivo es un objeto FileInfo.

Propiedades: Una propiedad es información asociada al objeto que especifica algo en particular del mismo. Por ejemplo, en un objeto Mailbox, tiene una propiedad Name que representa el atributo DisplayName en el directorio activo para usuario con buzón. También tiene una propiedad ServerLegacyDN que representa el valor del atributo msExchangeHomeServerName del usuario con buzón en el directorio activo. Este usuario con buzón, es el ítem representado por el objeto Mailbox en ESM.

Como se habrán dado cuenta, las propiedades de los objetos de EMS no tienen el mismo nombre que las propiedades de los objetos en el directorio activo, aunque representen el mismo valor.

El nombre y el tipo de datos de cada propiedad (entero, binario, cadena, etc.) es también información que está incluida en el objeto.

Para ver las propiedades del objeto Mailbox, pueden ejecutar el comando:

[MSH] C:\>get-mailbox <nombre> | List

Métodos: Un método es un conjunto de instrucciones que definen una acción en particular para un objeto. Por ejemplo, un objeto Mailbox incluye un método set_emailAddresses que se usa para configurar la dirección de correo (atributo proxyAddresses del directorio activo) para ese usuario con buzón. El nombre del método no es relevante para configurar la dirección de correo, dado que el cmdlet set-mailbox expone un parámetro –emailaddresses que utiliza este método en forma transparente.

[MSH] C:\>set-mailbox <nombre> -emailaddresses smtp:nombre@dominio.com

Si quieres ver todos los métodos asociados a un objeto mailbox, puedes usar el cmdlet get-member. Get-member trabaja con un objeto en particular, así que podríamos obtenerlos mediante el siguiente comando:

[MSH] C:\>get-mailbox <nombre> |get-member –membertype method

Pipelining – Pasando información entre comandos

Pipelining es el término en inglés utilizado para la redirección de la salida de un proceso hacia la entrada de otro. El símbolo “ | ” es usado para indicar esta redirección en EMS. Cuando encontremos este símbolo en una línea de comandos, significa que el resultado del comando que está a la izquierda del signo se usará como entrada para el comando que está a la derecha del signo. Este resultado tendrá la forma de uno o más objetos.

Ejemplo

Si quieres mostrar las propiedades del usuario Susana Oliveira, el comando sería:

[MSH] C:\>get-mailbox "Susana Oliveira"

Name Alias Server ProhibitSendQuo

                                                                ta

---- ----- ------ ---------------

Susana Oliveira susoli fc-mbc 400MB

Solamente algunos atributos del objeto mailbox son mostrados en la consola pero en realidad la salida del comando es el objeto completo que representa el mailbox “Susana Oliveira”

Luego, por ejemplo, puedes usar el cmdlet format-list, que toma la salida del pipeline y despliega en pantalla una lista de propiedades de cada objeto. Si enviamos la salida del get-mailbox anterior al cmdlet format-list pidiendo las propiedades name y legacyexchangedn, obtendremos este resultado:

[MSH] C:\>get-mailbox "Susana Oliveira" |format-list -Property name,legacyexchangedn

Name : Susana Oliveira

LegacyExchangeDN : /o=Fourth Coffee/ou=Exchange Administrative Group (FYDIBOHF2

                   3SPDLT)/cn=Recipients/cn=susoli

Si por ejemplo usamos el comando get-mailbox sin parámetros (devuelve la lista de todos los mailbox del forest), format-list tomará cada objeto y desplegará las propiedades indicadas:

[MSH] C:\>get-mailbox |format-list -Property name,legacyexchangedn

Name : Administrator

LegacyExchangeDN : /o=Fourth Coffee/ou=Exchange Administrative Group (FYDIBOHF2

                   3SPDLT)/cn=Recipients/cn=Administrator

Name : Aaron Con

LegacyExchangeDN : /o=Fourth Coffee/ou=Exchange Administrative Group (FYDIBOHF2

                   3SPDLT)/cn=Recipients/cn=aarcon

Name : Anton Kirilov

LegacyExchangeDN : /o=Fourth Coffee/ou=Exchange Administrative Group (FYDIBOHF2

                   3SPDLT)/cn=Recipients/cn=antkir

Name : Aaron Lee

LegacyExchangeDN : /o=Fourth Coffee/ou=Exchange Administrative Group (FYDIBOHF2

                   3SPDLT)/cn=Recipients/cn=aarlee

... continuando con todos los usuarios de la organización

Otro ejemplo práctico: digamos que necesitas establecer límites de tamaño de envío a todos los usuarios de la base de datos “managers”:

[MSH] C:\>get-mailbox -database managers

Name Alias Server ProhibitSendQuo

                              ta

---- ----- ------ ---------------

Wilson Pais               wilpai fc-mbc unlimited

Susana Oliveira susoli fc-mbc 300MB

* *devuelve los usuarios en la base de datos “managers”

[MSH] C:\>get-mailbox -database managers | set-mailbox -ProhibitSendQuota 400mb

                                                   

** Utilizando el mismo commando, usamos pipelining para enviar los objetos al cmdlet set-mailbox y configurar el límite de tamaño requerido a 400Mb

[MSH] C:\>get-mailbox -database managers

Name Alias Server ProhibitSendQuo

                                                                ta

---- ----- ------ ---------------

Wilson Pais               wilpai fc-mbc 400MB

Susana Oliveira susoli fc-mbc 400MB

* *listamos nuevamente los usuarios de la base “managers” para confirmar los cambios

Llevemos este concepto a un nivel más interesante. Primero necesito introducir el concepto de variables. Como mencioné anteriormente podemos usar variables en EMS. Una variable especial es “ $_ ” que representa cada objeto que se está pasando por el pipeline. Mediante esta variable y el cmdlet where-object podemos filtrar lo que obtenemos del pipeline y entregar una salida parcial al cmdlet que recibe esta salida.

Supongamos que queremos configurar el límite de tamaño de envío de todos los usuarios de la organización a 300Mb, pero sólo a los usuarios cuyo límite actual sea “unlimited”. En otras palabras, los usuarios que ya tienen un límite establecido, quedarán como están. (alguien recuerda como hacer esto en Exchange 2000/2003? J)

[MSH] C:\>get-mailbox |where-object {$_.ProhibitSendQuota -eq "unlimited"} |set-mailbox

–ProhibitSendQuota 300mb

**Get-mailbox pasa al pipeline todos los objetos mailbox de la organización

**Where-object los toma y pasa al pipeline sólo los objetos donde la propiedad ProhibitSendQuota sea igual a “unlimited”

**Set-mailbox toma los objetos devueltos por Where-object y les configura el límite deseado.

Estos ejemplos son simplemente parte de la diversión de EMS. Hasta ahora trabajamos con el objeto mailbox, pero hay muchos más objetos representados en EMS, incluyendo objetos que no pertenecientes a la jerarquía de Exchange como procesos, servicios, archivos, etc.

Podemos utilizar get-proces, get-service o get-childitem para obtener la lista de estos objetos. Filtrarlos con where-object y ordenarlas con sort-object y tomar acciones como start-service, stop-process (kill) o remove-item por ejemplo.

Algunos ejemplos:

[MSH] C:\>Get-Service | Where-Object {$_.name -like "msexchange*"}

                  

Status Name DisplayName

------ ---- -----------

Running MSExchangeIS Microsoft Exchange Information Store

Running MSExchangeMA Microsoft Exchange Mailbox Assistants

Running MSExchangeMGMT Microsoft Exchange Management

Running MSExchangeRepl Microsoft Exchange Replication Service

Running MSExchangeSA Microsoft Exchange System Attendant

Running MSExchangeSearch Microsoft Exchange Search

** Listado de servicios cuyo nombre continene msexchange

[MSH] C:\>Get-Process

Handles NPM(K) PM(K) WS(K) VS(M) CPU(s) Id ProcessName

------- ------ ----- ----- ----- ------ -- -----------

    388 132 6164 2820 284 4.20 1084 ADTopologyService

    631 6 1764 1376 25 72.62 352 csrss

    260 129 8288 1592 308 0.69 1528 exmgmt

    303 11 8848 5684 55 6.49 3508 explorer

      0 0 0 16 0 0 Idle

    196 5 3624 3584 47 4.77 1192 inetinfo

    573 16 7636 3880 44 13.65 432 lsass

    834 264 26156 16136 327 18.42 1660 mad

    331 12 25004 9096 199 15.48 1716 MailSubmissionSvc

    245 9 19544 7696 111 50.60 1616 Microsoft.Exchange...

    481 21 30792 11756 223 32.25 1440 Microsoft.Exchange...

    362 16 28600 6504 197 11.23 2584 Microsoft.Exchange...

    203 6 7144 2500 58 10.90 344 mmc

** Listado de procesos corriendo en el server

[MSH] C:\>Get-Process | Sort-Object -property Id

Handles NPM(K) PM(K) WS(K) VS(M) CPU(s) Id ProcessName

------- ------ ----- ----- ----- ------ -- -----------

      0 0 0 16 0 0 Idle

   1848 0 0 40 2 106.18 4 System

     18 1 140 200 4 0.08 304 smss

    681 23 102824 80804 237 49.20 340 Msh

    203 6 7144 2500 58 10.90 344 mmc

    631 6 1764 1388 25 72.75 352 csrss

    588 64 7712 2980 53 8.97 376 winlogon

    359 10 3852 2504 27 6.80 420 services

    573 16 7636 3880 44 13.65 432 lsass

     76 2 732 836 17 0.24 636 svchost

    116 4 2984 1220 25 1.72 972 spoolsv

    145 6 1428 620 23 0.16 996 msdtc

     47 2 544 588 22 1.79 1072 vmsrvc

   ......

** Listado de procesos ordenados por ID

[MSH] C:\>get-childitem "c:\program files"

    Directory: Microsoft.Msh.Core\FileSystem::C:\program files

Mode LastWriteTime Length Name

---- ------------- ------ ----

d---- 3/28/2006 4:10 PM bginfo

d---- 5/8/2005 10:30 AM Common Files

d---- 5/8/2005 10:27 AM ComPlus Applications

d---- 5/8/2005 10:33 AM Internet Explorer

d---- 5/19/2006 1:26 PM Microsoft

d---- 5/19/2006 1:17 PM Microsoft Command Shell

d---- 5/8/2005 10:30 AM NetMeeting

d---- 5/8/2005 10:30 AM Outlook Express

d---- 6/28/2006 8:10 AM Support Tools

d---- 3/28/2006 5:52 PM Virtual Machine Additions

d---- 5/8/2005 10:44 AM Windows Media Player

d---- 5/8/2005 10:23 AM Windows NT

** Listado de elementos bajo el directorio Program Files

[MSH] C:\>get-service |group-object -property status

Count Name Group

----- ---- -----

   55 Running {1-vmsrvc, AeLookupSvc, Browser, CryptSvc...}

   53 Stopped {Alerter, ALG, AppMgmt, aspnet_state...}

** Cuantos servicios corriendo y cuantos detenidos?

[MSH] C:\>set-location "hklm:\system\currentcontrolset\services\msexchange transport"

[MSH] HKLM:\system\currentcontrolset\services\msexchange transport>get-itemprope

rty diagnostics

MshPath : Microsoft.Msh.Core\Registry::HKEY_LOCAL_MACHINE\system\cu

                      rrentcontrolset\services\msexchange transport\diagnostics

MshParentPath : Microsoft.Msh.Core\Registry::HKEY_LOCAL_MACHINE\system\cu

                      rrentcontrolset\services\msexchange transport

MshChildName : diagnostics

MshDrive : HKLM

MshProvider : Microsoft.Msh.Core\Registry

1 SmtpReceive : 0

2 SmtpSend : 0

3 DSN : 0

4 Routing : 0

5 Logging : 0

6 Components : 0

7 RemoteDelivery : 0

8 Pickup : 0

9 Categorizer : 0

10 PoisonMessage : 0

11 MessageSecurity : 0

12 TransportService : 0

13 Exch50 : 0

14 Process : 0

15 ResourceManager : 0

16 Configuration : 0

17 Storage : 0

** Consulta en el registry cual es el nivel de diagnóstico (diagnostic logging)para el motor de transporte

Funciones y Scripts

En cuanto el tiempo permita, escribiré una nota referida a automatización usando funciones y scripts en EMS.

Mientras tanto usa tu imaginación y prueba Exchange Management Shell en los laboratorios virtuales de Technet.

                               

Nos vemos!