Capítulo 3: Detección de objetos, propiedades y métodos

Mi primer contacto con un equipo fue con un Commodore 64, pero el primero moderno que tuve fue un clon de IBM 286 a 12 MHz con 1 megabyte de memoria, una unidad de disco duro de 40 megabytes y una unidad de disquete de 5 1/4 pulgadas con un monitor CGA que ejecutaba Microsoft DOS 3.3.

Muchos profesionales de TI, como yo mismo, no son extraños a la línea de comandos, pero cuando aparece el asunto de objetos, propiedades y métodos, obtienen el ciervo en los faros miran y dicen: "No soy un desarrollador". ¿Adivina qué? Resulta que no hace falta ser desarrollador para usar PowerShell y hacerlo bien. Que nadie se deje confundir por la terminología. Puede que sea un poco confuso al principio, pero, después de obtener un poco de experiencia práctica, habrá momentos en los que todo de repente comienza a tener sentido. "¡Claro! A eso se refería el libro".

Es recomendable probar los ejemplos en el equipo para obtener un poco de esa experiencia práctica.

Requisitos

Algunos de los ejemplos que se muestran en este capítulo requieren el módulo Active Directory PowerShell. El módulo forma parte de las Herramientas de administración remota del servidor (RSAT) para Windows. Para la compilación 1809 (o posterior) de Windows, las herramientas de RSAT se instalan como una característica de Windows. La compatibilidad con Active Directory no está disponible en Windows Home.

Get-Member

Get-Member ayuda a detectar qué objetos, propiedades y métodos están disponibles para los comandos. Cualquier comando que produzca una salida basada en objetos se puede canalizar a Get-Member. Una propiedad es una característica de un elemento. Los permisos de conducir tienen una propiedad, "nombre", cuyos valores podrían ser Beatriz, Cristina, David o Pedro, por ejemplo. Un método es una acción que se puede realizar en un elemento. Siguiendo con el ejemplo de los permisos de conducir, uno de los métodos sería "revocar", ya que hay diferentes entidades gubernamentales que pueden revocarlos.

Propiedades

En el siguiente ejemplo, voy a recuperar información sobre el servicio de Hora de Windows que se ejecuta en mi equipo.

Get-Service -Name w32time
Status   Name               DisplayName
------   ----               -----------
Running  w32time            Windows Time

Status, Name y DisplayName son ejemplos de propiedades, tal como se muestra en el conjunto de resultados anterior. El valor de la propiedad Status es Running, el valor de la propiedad Name es w32time y el valor de DisplayName es Windows Time.

Ahora canalizaré ese comando a Get-Member:

Get-Service -Name w32time | Get-Member
   TypeName: System.ServiceProcess.ServiceController

Name                      MemberType    Definition
----                      ----------    ----------
Name                      AliasProperty Name = ServiceName
RequiredServices          AliasProperty RequiredServices = ServicesDependedOn
Disposed                  Event         System.EventHandler Disposed(System.Object, Sy...
Close                     Method        void Close()
Continue                  Method        void Continue()
CreateObjRef              Method        System.Runtime.Remoting.ObjRef CreateObjRef(ty...
Dispose                   Method        void Dispose(), void IDisposable.Dispose()
Equals                    Method        bool Equals(System.Object obj)
ExecuteCommand            Method        void ExecuteCommand(int command)
GetHashCode               Method        int GetHashCode()
GetLifetimeService        Method        System.Object GetLifetimeService()
GetType                   Method        type GetType()
InitializeLifetimeService Method        System.Object InitializeLifetimeService()
Pause                     Method        void Pause()
Refresh                   Method        void Refresh()
Start                     Method        void Start(), void Start(string[] args)
Stop                      Method        void Stop()
WaitForStatus             Method        void WaitForStatus(System.ServiceProcess.Servi...
CanPauseAndContinue       Property      bool CanPauseAndContinue {get;}
CanShutdown               Property      bool CanShutdown {get;}
CanStop                   Property      bool CanStop {get;}
Container                 Property      System.ComponentModel.IContainer Container {get;}
DependentServices         Property      System.ServiceProcess.ServiceController[] Depe...
DisplayName               Property      string DisplayName {get;set;}
MachineName               Property      string MachineName {get;set;}
ServiceHandle             Property      System.Runtime.InteropServices.SafeHandle Serv...
ServiceName               Property      string ServiceName {get;set;}
ServicesDependedOn        Property      System.ServiceProcess.ServiceController[] Serv...
ServiceType               Property      System.ServiceProcess.ServiceType ServiceType ...
Site                      Property      System.ComponentModel.ISite Site {get;set;}
StartType                 Property      System.ServiceProcess.ServiceStartMode StartTy...
Status                    Property      System.ServiceProcess.ServiceControllerStatus ...
ToString                  ScriptMethod  System.Object ToString();

La primera línea de los resultados en el ejemplo anterior contiene información muy importante. TypeName indica qué tipo de objeto se devolvió. Se devolvió un objeto System.ServiceProcess. ServiceController en este ejemplo. Esto a menudo se abrevia como la parte de TypeName justo después del último punto; en este ejemplo sería ServiceController.

Una vez que se sepa el tipo de objeto que produce un comando, se puede utilizar esta información para buscar comandos que acepten ese tipo de objeto como entrada.

Get-Command -ParameterType ServiceController
CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Cmdlet          Get-Service                                        3.1.0.0    Microsof...
Cmdlet          Restart-Service                                    3.1.0.0    Microsof...
Cmdlet          Resume-Service                                     3.1.0.0    Microsof...
Cmdlet          Set-Service                                        3.1.0.0    Microsof...
Cmdlet          Start-Service                                      3.1.0.0    Microsof...
Cmdlet          Stop-Service                                       3.1.0.0    Microsof...
Cmdlet          Suspend-Service                                    3.1.0.0    Microsof...

Todos esos comandos tienen un parámetro que acepta un tipo de objeto ServiceController por canalización, entrada de parámetro o ambos.

Observe que hay más propiedades que las que se muestran de forma predeterminada. Aunque estas propiedades adicionales no se muestran de forma predeterminada, se pueden seleccionar de la canalización canalizando el comando al cmdlet Select-Object y usando el parámetro Property. En el ejemplo siguiente se seleccionan todas las propiedades canalizando los resultados de Get-Service a Select-Object y especificando el carácter comodín * como valor para el parámetro Property.

Get-Service -Name w32time | Select-Object -Property *
Name                : w32time
RequiredServices    : {}
CanPauseAndContinue : False
CanShutdown         : True
CanStop             : True
DisplayName         : Windows Time
DependentServices   : {}
MachineName         : .
ServiceName         : w32time
ServicesDependedOn  : {}
ServiceHandle       : SafeServiceHandle
Status              : Running
ServiceType         : Win32ShareProcess
StartType           : Manual
Site                :
Container           :

También se pueden seleccionar propiedades específicas mediante una lista separada por comas para el valor del parámetro Property.

Get-Service -Name w32time | Select-Object -Property Status, Name, DisplayName, ServiceType
 Status Name    DisplayName        ServiceType
 ------ ----    -----------        -----------
Running w32time Windows Time Win32ShareProcess

De forma predeterminada, se devuelven cuatro propiedades en una tabla y se devuelven cinco o más en una lista. Algunos comandos usan formatos personalizados para invalidar el número de propiedades que se muestran de forma predeterminada en una tabla. Hay varios cmdlets Format-* que se pueden usar para invalidar manualmente estos valores predeterminados. Los más comunes son Format-Table y Format-List, y ambos se tratarán en un próximo capítulo.

Se pueden usar caracteres comodín cuando se especifican los nombres de propiedad con Select-Object.

Get-Service -Name w32time | Select-Object -Property Status, DisplayName, Can*
Status              : Running
DisplayName         : Windows Time
CanPauseAndContinue : False
CanShutdown         : True
CanStop             : True

En el ejemplo anterior, se usó Can* como uno de los valores del parámetro Property para devolver todas las propiedades que comienzan con Can. Entre ellas se incluyen CanPauseAndContinue, CanShutdown y CanStop.

Métodos

Los métodos son una acción que se puede realizar. Usando el parámetro MemberType se pueden restringir los resultados de Get-Member para mostrar solo los métodos de Get-Service.

Get-Service -Name w32time | Get-Member -MemberType Method
   TypeName: System.ServiceProcess.ServiceController

Name                      MemberType Definition
----                      ---------- ----------
Close                     Method     void Close()
Continue                  Method     void Continue()
CreateObjRef              Method     System.Runtime.Remoting.ObjRef CreateObjRef(type ...
Dispose                   Method     void Dispose(), void IDisposable.Dispose()
Equals                    Method     bool Equals(System.Object obj)
ExecuteCommand            Method     void ExecuteCommand(int command)
GetHashCode               Method     int GetHashCode()
GetLifetimeService        Method     System.Object GetLifetimeService()
GetType                   Method     type GetType()
InitializeLifetimeService Method     System.Object InitializeLifetimeService()
Pause                     Method     void Pause()
Refresh                   Method     void Refresh()
Start                     Method     void Start(), void Start(string[] args)
Stop                      Method     void Stop()
WaitForStatus             Method     void WaitForStatus(System.ServiceProcess.ServiceC...

Como se puede ver, hay muchos métodos. Se puede usar el método Stop para detener un servicio de Windows.

(Get-Service -Name w32time).Stop()

Ahora comprobemos si el servicio de Hora de Windows de verdad se ha detenido.

Get-Service -Name w32time
Status   Name               DisplayName
------   ----               -----------
Stopped  w32time            Windows Time

No suelo usar métodos, pero son algo que debe tenerse en cuenta. Habrá ocasiones en las que aparecerá un comando Get-* sin un comando correspondiente para modificar dicho elemento. A menudo, se puede usar un método para realizar una acción que lo modifique. El cmdlet Get-SqlAgentJob del módulo SqlServer PowerShell es un buen ejemplo de esto. El módulo se instala como parte de SQL Server Management Studio (SSMS). No existe ningún cmdlet Set-* correspondiente, pero se puede usar un método para completar la misma tarea.

Otro motivo para conocer los métodos es que muchos principiantes dan por hecho que no se pueden realizar cambios destructivos con comandos Get-*. Pero estos comandos sí pueden producir problemas graves si se usan de forma incorrecta.

Una opción mejor es usar un cmdlet para realizar la acción si existe uno. Ahora vamos a iniciar el servicio de Hora de Windows, pero esta vez usaremos el cmdlet para iniciar los servicios.

Get-Service -Name w32time | Start-Service -PassThru
Status   Name               DisplayName
------   ----               -----------
Running  w32time            Windows Time

De forma predeterminada, Start-Service no devuelve ningún resultado, del mismo modo que el método de inicio de Get-Service. Pero una de las ventajas de usar un cmdlet es que muchas veces el cmdlet ofrece funcionalidades adicionales que no están disponibles con un método. En el ejemplo anterior, se usó el parámetro PassThru. Esto provoca que un cmdlet produzca una salida, aunque normalmente no la produzca.

Hay que tener cuidado de no hacer suposiciones sobre la salida de un cmdlet. Todos sabemos lo que pasa cuando se presuponen las cosas. Ahora recuperaré información sobre el proceso de PowerShell que se ejecuta en mi equipo de entorno de laboratorio con Windows 10.

Get-Process -Name PowerShell
Handles  NPM(K)    PM(K)      WS(K)     CPU(s)     Id  SI ProcessName
-------  ------    -----      -----     ------     --  -- -----------
    922      48   107984     140552       2.84   9020   1 powershell

Acto seguido, canalizaré ese mismo comando a Get-Member:

Get-Process -Name PowerShell | Get-Member
   TypeName: System.Diagnostics.Process

Name                       MemberType     Definition
----                       ----------     ----------
Handles                    AliasProperty  Handles = Handlecount
Name                       AliasProperty  Name = ProcessName
NPM                        AliasProperty  NPM = NonpagedSystemMemorySize64
PM                         AliasProperty  PM = PagedMemorySize64
SI                         AliasProperty  SI = SessionId
VM                         AliasProperty  VM = VirtualMemorySize64
WS                         AliasProperty  WS = WorkingSet64
Disposed                   Event          System.EventHandler Disposed(System.Object, ...
ErrorDataReceived          Event          System.Diagnostics.DataReceivedEventHandler ...
Exited                     Event          System.EventHandler Exited(System.Object, Sy...
OutputDataReceived         Event          System.Diagnostics.DataReceivedEventHandler ...
BeginErrorReadLine         Method         void BeginErrorReadLine()
BeginOutputReadLine        Method         void BeginOutputReadLine()
CancelErrorRead            Method         void CancelErrorRead()
CancelOutputRead           Method         void CancelOutputRead()
Close                      Method         void Close()
CloseMainWindow            Method         bool CloseMainWindow()
CreateObjRef               Method         System.Runtime.Remoting.ObjRef CreateObjRef(...
Dispose                    Method         void Dispose(), void IDisposable.Dispose()
Equals                     Method         bool Equals(System.Object obj)
GetHashCode                Method         int GetHashCode()
GetLifetimeService         Method         System.Object GetLifetimeService()
GetType                    Method         type GetType()
InitializeLifetimeService  Method         System.Object InitializeLifetimeService()
Kill                       Method         void Kill()
Refresh                    Method         void Refresh()
Start                      Method         bool Start()
ToString                   Method         string ToString()
WaitForExit                Method         bool WaitForExit(int milliseconds), void Wai...
WaitForInputIdle           Method         bool WaitForInputIdle(int milliseconds), boo...
__NounName                 NoteProperty   string __NounName=Process
BasePriority               Property       int BasePriority {get;}
Container                  Property       System.ComponentModel.IContainer Container {...
EnableRaisingEvents        Property       bool EnableRaisingEvents {get;set;}
ExitCode                   Property       int ExitCode {get;}
ExitTime                   Property       datetime ExitTime {get;}
Handle                     Property       System.IntPtr Handle {get;}
HandleCount                Property       int HandleCount {get;}
HasExited                  Property       bool HasExited {get;}
Id                         Property       int Id {get;}
MachineName                Property       string MachineName {get;}
MainModule                 Property       System.Diagnostics.ProcessModule MainModule ...
MainWindowHandle           Property       System.IntPtr MainWindowHandle {get;}
MainWindowTitle            Property       string MainWindowTitle {get;}
MaxWorkingSet              Property       System.IntPtr MaxWorkingSet {get;set;}
MinWorkingSet              Property       System.IntPtr MinWorkingSet {get;set;}
Modules                    Property       System.Diagnostics.ProcessModuleCollection M...
NonpagedSystemMemorySize   Property       int NonpagedSystemMemorySize {get;}
NonpagedSystemMemorySize64 Property       long NonpagedSystemMemorySize64 {get;}
PagedMemorySize            Property       int PagedMemorySize {get;}
PagedMemorySize64          Property       long PagedMemorySize64 {get;}
PagedSystemMemorySize      Property       int PagedSystemMemorySize {get;}
PagedSystemMemorySize64    Property       long PagedSystemMemorySize64 {get;}
PeakPagedMemorySize        Property       int PeakPagedMemorySize {get;}
PeakPagedMemorySize64      Property       long PeakPagedMemorySize64 {get;}
PeakVirtualMemorySize      Property       int PeakVirtualMemorySize {get;}
PeakVirtualMemorySize64    Property       long PeakVirtualMemorySize64 {get;}
PeakWorkingSet             Property       int PeakWorkingSet {get;}
PeakWorkingSet64           Property       long PeakWorkingSet64 {get;}
PriorityBoostEnabled       Property       bool PriorityBoostEnabled {get;set;}
PriorityClass              Property       System.Diagnostics.ProcessPriorityClass Prio...
PrivateMemorySize          Property       int PrivateMemorySize {get;}
PrivateMemorySize64        Property       long PrivateMemorySize64 {get;}
PrivilegedProcessorTime    Property       timespan PrivilegedProcessorTime {get;}
ProcessName                Property       string ProcessName {get;}
ProcessorAffinity          Property       System.IntPtr ProcessorAffinity {get;set;}
Responding                 Property       bool Responding {get;}
SafeHandle                 Property       Microsoft.Win32.SafeHandles.SafeProcessHandl...
SessionId                  Property       int SessionId {get;}
Site                       Property       System.ComponentModel.ISite Site {get;set;}
StandardError              Property       System.IO.StreamReader StandardError {get;}
StandardInput              Property       System.IO.StreamWriter StandardInput {get;}
StandardOutput             Property       System.IO.StreamReader StandardOutput {get;}
StartInfo                  Property       System.Diagnostics.ProcessStartInfo StartInf...
StartTime                  Property       datetime StartTime {get;}
SynchronizingObject        Property       System.ComponentModel.ISynchronizeInvoke Syn...
Threads                    Property       System.Diagnostics.ProcessThreadCollection T...
TotalProcessorTime         Property       timespan TotalProcessorTime {get;}
UserProcessorTime          Property       timespan UserProcessorTime {get;}
VirtualMemorySize          Property       int VirtualMemorySize {get;}
VirtualMemorySize64        Property       long VirtualMemorySize64 {get;}
WorkingSet                 Property       int WorkingSet {get;}
WorkingSet64               Property       long WorkingSet64 {get;}
PSConfiguration            PropertySet    PSConfiguration {Name, Id, PriorityClass, Fi...
PSResources                PropertySet    PSResources {Name, Id, Handlecount, WorkingS...
Company                    ScriptProperty System.Object Company {get=$this.Mainmodule....
CPU                        ScriptProperty System.Object CPU {get=$this.TotalProcessorT...
Description                ScriptProperty System.Object Description {get=$this.Mainmod...
FileVersion                ScriptProperty System.Object FileVersion {get=$this.Mainmod...
Path                       ScriptProperty System.Object Path {get=$this.Mainmodule.Fil...
Product                    ScriptProperty System.Object Product {get=$this.Mainmodule....
ProductVersion             ScriptProperty System.Object ProductVersion {get=$this.Main...

Observe que hay más propiedades enumeradas que las que se muestran de forma predeterminada. Varias de las propiedades predeterminadas que se muestran no aparecen como propiedades al consultar los resultados de Get-Member. Esto se debe a que muchos de los valores mostrados, como NPM(K), PM(K), WS(K) y CPU(s), son propiedades calculadas. Para determinar los nombres reales de las propiedades, el comando se debe canalizar a Get-Member.

Si un comando no produce una salida, no se puede canalizar a Get-Member. Dado que Start-Service no produce ninguna salida de forma predeterminada, genera un error cuando se intenta canalizar a Get-Member.

Start-Service -Name w32time | Get-Member
Get-Member : You must specify an object for the Get-Member cmdlet.
At line:1 char:31
+ Start-Service -Name w32time | Get-Member
+
    + CategoryInfo          : CloseError: (:) [Get-Member], InvalidOperationException
    + FullyQualifiedErrorId : NoObjectInGetMember,Microsoft.PowerShell.Commands.GetMembe
   rCommand

Se puede especificar el parámetro PassThru con el cmdlet Start-Service para hacer que produzca la salida, la cual se canalizaría a Get-Member sin errores.

Start-Service -Name w32time -PassThru | Get-Member
   TypeName: System.ServiceProcess.ServiceController

Name                      MemberType    Definition
----                      ----------    ----------
Name                      AliasProperty Name = ServiceName
RequiredServices          AliasProperty RequiredServices = ServicesDependedOn
Disposed                  Event         System.EventHandler Disposed(System.Object, Sy...
Close                     Method        void Close()
Continue                  Method        void Continue()
CreateObjRef              Method        System.Runtime.Remoting.ObjRef CreateObjRef(ty...
Dispose                   Method        void Dispose(), void IDisposable.Dispose()
Equals                    Method        bool Equals(System.Object obj)
ExecuteCommand            Method        void ExecuteCommand(int command)
GetHashCode               Method        int GetHashCode()
GetLifetimeService        Method        System.Object GetLifetimeService()
GetType                   Method        type GetType()
InitializeLifetimeService Method        System.Object InitializeLifetimeService()
Pause                     Method        void Pause()
Refresh                   Method        void Refresh()
Start                     Method        void Start(), void Start(string[] args)
Stop                      Method        void Stop()
WaitForStatus             Method        void WaitForStatus(System.ServiceProcess.Servi...
CanPauseAndContinue       Property      bool CanPauseAndContinue {get;}
CanShutdown               Property      bool CanShutdown {get;}
CanStop                   Property      bool CanStop {get;}
Container                 Property      System.ComponentModel.IContainer Container {get;}
DependentServices         Property      System.ServiceProcess.ServiceController[] Depe...
DisplayName               Property      string DisplayName {get;set;}
MachineName               Property      string MachineName {get;set;}
ServiceHandle             Property      System.Runtime.InteropServices.SafeHandle Serv...
ServiceName               Property      string ServiceName {get;set;}
ServicesDependedOn        Property      System.ServiceProcess.ServiceController[] Serv...
ServiceType               Property      System.ServiceProcess.ServiceType ServiceType ...
Site                      Property      System.ComponentModel.ISite Site {get;set;}
StartType                 Property      System.ServiceProcess.ServiceStartMode StartTy...
Status                    Property      System.ServiceProcess.ServiceControllerStatus ...
ToString                  ScriptMethod  System.Object ToString();

Para que se canalice a Get-Member, un comando debe producir una salida basada en objetos.

Get-Service -Name w32time | Out-Host | Get-Member
Status   Name               DisplayName
------   ----               -----------
Running  w32time            Windows Time

Get-Member : You must specify an object for the Get-Member cmdlet.
At line:1 char:40
+ Get-Service -Name w32time | Out-Host | Get-Member
+
    + CategoryInfo          : CloseError: (:) [Get-Member], InvalidOperationException
    + FullyQualifiedErrorId : NoObjectInGetMember,Microsoft.PowerShell.Commands.GetMemberCommand

Out-Host escribe directamente en el host de PowerShell, pero no produce una salida basada en objetos para la canalización. Por lo tanto, no se puede canalizar a Get-Member.

Active Directory

Nota:

Las Herramientas de administración remota del servidor que aparecen en la sección de requisitos de este capítulo son necesarias para completar esta sección. Además, tal y como se mencionó en la introducción de este libro, es necesario que el equipo de entorno de laboratorio con Windows 10 sea miembro del dominio de entorno de laboratorio.

Ahora vamos a usar Get-Command con el parámetro Module para determinar qué comandos se agregaron como parte del módulo ActiveDirectory PowerShell cuando se instalaron las herramientas de administración remota del servidor.

Get-Command -Module ActiveDirectory
CommandType     Name                                               Version    Source
-----------     ----                                               -------    ------
Cmdlet          Add-ADCentralAccessPolicyMember                    1.0.0.0    ActiveDi...
Cmdlet          Add-ADComputerServiceAccount                       1.0.0.0    ActiveDi...
Cmdlet          Add-ADDomainControllerPasswordReplicationPolicy    1.0.0.0    ActiveDi...
Cmdlet          Add-ADFineGrainedPasswordPolicySubject             1.0.0.0    ActiveDi...
Cmdlet          Add-ADGroupMember                                  1.0.0.0    ActiveDi...
Cmdlet          Add-ADPrincipalGroupMembership                     1.0.0.0    ActiveDi...
Cmdlet          Add-ADResourcePropertyListMember                   1.0.0.0    ActiveDi...
Cmdlet          Clear-ADAccountExpiration                          1.0.0.0    ActiveDi...
Cmdlet          Clear-ADClaimTransformLink                         1.0.0.0    ActiveDi...
Cmdlet          Disable-ADAccount                                  1.0.0.0    ActiveDi...
...

Se ha agregado un total de 147 comandos como parte del módulo ActiveDirectory PowerShell. Algunos comandos de estos comandos solo devuelven una parte de las propiedades disponibles de forma predeterminada.

¿No ha observado algo distinto en relación con los nombres de los comandos en este módulo? La parte del nombre de los comandos tiene un prefijo AD. Es habitual ver esto en los comandos de la mayoría de los módulos. El prefijo está diseñado para evitar conflictos de nomenclatura.

Get-ADUser -Identity mike | Get-Member
   TypeName: Microsoft.ActiveDirectory.Management.ADUser

Name              MemberType            Definition
----              ----------            ----------
Contains          Method                bool Contains(string propertyName)
Equals            Method                bool Equals(System.Object obj)
GetEnumerator     Method                System.Collections.IDictionaryEnumerator GetEn...
GetHashCode       Method                int GetHashCode()
GetType           Method                type GetType()
ToString          Method                string ToString()
Item              ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropert...
DistinguishedName Property              System.String DistinguishedName {get;set;}
Enabled           Property              System.Boolean Enabled {get;set;}
GivenName         Property              System.String GivenName {get;set;}
Name              Property              System.String Name {get;}
ObjectClass       Property              System.String ObjectClass {get;set;}
ObjectGUID        Property              System.Nullable`1[[System.Guid, mscorlib, Vers...
SamAccountName    Property              System.String SamAccountName {get;set;}
SID               Property              System.Security.Principal.SecurityIdentifier S...
Surname           Property              System.String Surname {get;set;}
UserPrincipalName Property              System.String UserPrincipalName {get;set;}

Aunque apenas esté familiarizado con Active Directory, podría entender que una cuenta de usuario tiene más propiedades que las que se muestran en este ejemplo.

El cmdlet Get-ADUser tiene un parámetro Properties que se usa para especificar las propiedades (no predeterminadas) adicionales que quiera devolver. Todas se devuelven al especificar el carácter comodín *.

Get-ADUser -Identity mike -Properties * | Get-Member
   TypeName: Microsoft.ActiveDirectory.Management.ADUser

Name                                 MemberType            Definition
----                                 ----------            ----------
Contains                             Method                bool Contains(string proper...
Equals                               Method                bool Equals(System.Object obj)
GetEnumerator                        Method                System.Collections.IDiction...
GetHashCode                          Method                int GetHashCode()
GetType                              Method                type GetType()
ToString                             Method                string ToString()
Item                                 ParameterizedProperty Microsoft.ActiveDirectory.M...
AccountExpirationDate                Property              System.DateTime AccountExpi...
accountExpires                       Property              System.Int64 accountExpires...
AccountLockoutTime                   Property              System.DateTime AccountLock...
AccountNotDelegated                  Property              System.Boolean AccountNotDe...
AllowReversiblePasswordEncryption    Property              System.Boolean AllowReversi...
AuthenticationPolicy                 Property              Microsoft.ActiveDirectory.M...
AuthenticationPolicySilo             Property              Microsoft.ActiveDirectory.M...
BadLogonCount                        Property              System.Int32 BadLogonCount ...
badPasswordTime                      Property              System.Int64 badPasswordTim...
badPwdCount                          Property              System.Int32 badPwdCount {g...
CannotChangePassword                 Property              System.Boolean CannotChange...
CanonicalName                        Property              System.String CanonicalName...
Certificates                         Property              Microsoft.ActiveDirectory.M...
City                                 Property              System.String City {get;set;}
CN                                   Property              System.String CN {get;}
codePage                             Property              System.Int32 codePage {get;...
Company                              Property              System.String Company {get;...
CompoundIdentitySupported            Property              Microsoft.ActiveDirectory.M...
Country                              Property              System.String Country {get;...
countryCode                          Property              System.Int32 countryCode {g...
Created                              Property              System.DateTime Created {get;}
createTimeStamp                      Property              System.DateTime createTimeS...
Deleted                              Property              System.Boolean Deleted {get;}
Department                           Property              System.String Department {g...
Description                          Property              System.String Description {...
DisplayName                          Property              System.String DisplayName {...
DistinguishedName                    Property              System.String Distinguished...
Division                             Property              System.String Division {get...
DoesNotRequirePreAuth                Property              System.Boolean DoesNotRequi...
dSCorePropagationData                Property              Microsoft.ActiveDirectory.M...
EmailAddress                         Property              System.String EmailAddress ...
EmployeeID                           Property              System.String EmployeeID {g...
EmployeeNumber                       Property              System.String EmployeeNumbe...
Enabled                              Property              System.Boolean Enabled {get...
Fax                                  Property              System.String Fax {get;set;}
GivenName                            Property              System.String GivenName {ge...
HomeDirectory                        Property              System.String HomeDirectory...
HomedirRequired                      Property              System.Boolean HomedirRequi...
HomeDrive                            Property              System.String HomeDrive {ge...
HomePage                             Property              System.String HomePage {get...
HomePhone                            Property              System.String HomePhone {ge...
Initials                             Property              System.String Initials {get...
instanceType                         Property              System.Int32 instanceType {...
isDeleted                            Property              System.Boolean isDeleted {g...
KerberosEncryptionType               Property              Microsoft.ActiveDirectory.M...
LastBadPasswordAttempt               Property              System.DateTime LastBadPass...
LastKnownParent                      Property              System.String LastKnownPare...
lastLogoff                           Property              System.Int64 lastLogoff {ge...
lastLogon                            Property              System.Int64 lastLogon {get...
LastLogonDate                        Property              System.DateTime LastLogonDa...
lastLogonTimestamp                   Property              System.Int64 lastLogonTimes...
LockedOut                            Property              System.Boolean LockedOut {g...
logonCount                           Property              System.Int32 logonCount {ge...
LogonWorkstations                    Property              System.String LogonWorkstat...
Manager                              Property              System.String Manager {get;...
MemberOf                             Property              Microsoft.ActiveDirectory.M...
MNSLogonAccount                      Property              System.Boolean MNSLogonAcco...
MobilePhone                          Property              System.String MobilePhone {...
Modified                             Property              System.DateTime Modified {g...
modifyTimeStamp                      Property              System.DateTime modifyTimeS...
msDS-User-Account-Control-Computed   Property              System.Int32 msDS-User-Acco...
Name                                 Property              System.String Name {get;}
nTSecurityDescriptor                 Property              System.DirectoryServices.Ac...
ObjectCategory                       Property              System.String ObjectCategor...
ObjectClass                          Property              System.String ObjectClass {...
ObjectGUID                           Property              System.Nullable`1[[System.G...
objectSid                            Property              System.Security.Principal.S...
Office                               Property              System.String Office {get;s...
OfficePhone                          Property              System.String OfficePhone {...
Organization                         Property              System.String Organization ...
OtherName                            Property              System.String OtherName {ge...
PasswordExpired                      Property              System.Boolean PasswordExpi...
PasswordLastSet                      Property              System.DateTime PasswordLas...
PasswordNeverExpires                 Property              System.Boolean PasswordNeve...
PasswordNotRequired                  Property              System.Boolean PasswordNotR...
POBox                                Property              System.String POBox {get;set;}
PostalCode                           Property              System.String PostalCode {g...
PrimaryGroup                         Property              System.String PrimaryGroup ...
primaryGroupID                       Property              System.Int32 primaryGroupID...
PrincipalsAllowedToDelegateToAccount Property              Microsoft.ActiveDirectory.M...
ProfilePath                          Property              System.String ProfilePath {...
ProtectedFromAccidentalDeletion      Property              System.Boolean ProtectedFro...
pwdAnswer                            Property              System.String pwdAnswer {ge...
pwdLastSet                           Property              System.Int64 pwdLastSet {ge...
pwdQuestion                          Property              System.String pwdQuestion {...
SamAccountName                       Property              System.String SamAccountNam...
sAMAccountType                       Property              System.Int32 sAMAccountType...
ScriptPath                           Property              System.String ScriptPath {g...
sDRightsEffective                    Property              System.Int32 sDRightsEffect...
ServicePrincipalNames                Property              Microsoft.ActiveDirectory.M...
SID                                  Property              System.Security.Principal.S...
SIDHistory                           Property              Microsoft.ActiveDirectory.M...
SmartcardLogonRequired               Property              System.Boolean SmartcardLog...
sn                                   Property              System.String sn {get;set;}
State                                Property              System.String State {get;set;}
StreetAddress                        Property              System.String StreetAddress...
Surname                              Property              System.String Surname {get;...
Title                                Property              System.String Title {get;set;}
TrustedForDelegation                 Property              System.Boolean TrustedForDe...
TrustedToAuthForDelegation           Property              System.Boolean TrustedToAut...
UseDESKeyOnly                        Property              System.Boolean UseDESKeyOnl...
userAccountControl                   Property              System.Int32 userAccountCon...
userCertificate                      Property              Microsoft.ActiveDirectory.M...
UserPrincipalName                    Property              System.String UserPrincipal...
uSNChanged                           Property              System.Int64 uSNChanged {get;}
uSNCreated                           Property              System.Int64 uSNCreated {get;}
whenChanged                          Property              System.DateTime whenChanged...
whenCreated                          Property              System.DateTime whenCreated...

Mucho mejor.

¿Cuál podría ser un motivo por el que las propiedades de una cuenta de usuario de Active Directory podrían estar tan limitadas de forma predeterminada? Imaginemos qué pasaría si se devolviera cada propiedad para cada cuenta de usuario en el entorno de Active Directory de producción. Pensemos en la degradación del rendimiento que podría provocar, y no solo en los controladores de dominio, sino también en la red. No está claro que de verdad se necesiten todas las propiedades. Devolver todas las propiedades a una cuenta de usuario única es perfectamente aceptable cuando se intenta determinar qué propiedades existen.

No es raro ejecutar un comando muchas veces al crear un prototipo. Si va a realizar una consulta enorme, es preferible realizarla una vez y almacenar los resultados en una variable. Hecho esto, se trabajaría con el contenido de la variable, en lugar de usar repetidamente una consulta costosa.

$Users = Get-ADUser -Identity mike -Properties *

Es mejor usar el contenido de la variable $Users, en lugar de ejecutar el comando anterior varias veces. Tenga en cuenta que el contenido de la variable no se actualizará cuando se realicen cambios en el usuario en Active Directory.

Puede canalizarse la variable $Users a Get-Member para detectar las propiedades disponibles.

$Users | Get-Member

Después, seleccione las propiedades individuales mediante la canalización de $Users a Select-Object, sin tener que consultar Active Directory más de una vez.

$Users | Select-Object -Property Name, LastLogonDate, LastBadPasswordAttempt

Si va a consultar Active Directory más de una vez, puede usar el parámetro Properties para especificar las propiedades no predeterminadas que quiera.

Get-ADUser -Identity mike -Properties LastLogonDate, LastBadPasswordAttempt
DistinguishedName      : CN=Mike F. Robbins,OU=Sales,DC=mikefrobbins,DC=com
Enabled                : True
GivenName              : Mike
LastBadPasswordAttempt : 2/4/2017 10:46:15 AM
LastLogonDate          : 2/18/2017 12:45:14 AM
Name                   : Mike F. Robbins
ObjectClass            : user
ObjectGUID             : a82a8c58-1332-4a57-a6e2-68e0c750ea56
SamAccountName         : mike
SID                    : S-1-5-21-2989741381-570885089-3319121794-1108
Surname                : Robbins
UserPrincipalName      : miker@mikefrobbins.com

Resumen

En este capítulo hemos aprendido cómo determinar el tipo de objeto que puede producir un comando, cómo determinar qué propiedades y métodos están disponibles para un comando y cómo trabajar con comandos que limitan las propiedades que se devuelven de forma predeterminada.

Revisar

  1. ¿Qué tipo de objeto produce el cmdlet Get-Process?
  2. ¿Cómo se determinan las propiedades disponibles para un comando?
  3. Si existe un comando para obtener algo, pero no para establecer lo mismo, ¿qué se debe comprobar?
  4. ¿Qué puede hacerse para que determinados comandos que no producen una salida de forma predeterminada puedan producir una salida?
  5. Si se va a trabajar con los resultados de un comando que produce una gran cantidad de salidas, ¿qué se podría hacer?