La salida de texto de los comandos en la ventana del intérprete de PowerShell es solo una forma de mostrar información en una forma adecuada para la percepción humana. En realidad el miércoles
Tabla de contenido:
Objetos en PowerShell
Recordemos que un objeto es una colección de campos de datos (propiedades, eventos, etc.) y métodos para procesarlos (métodos). Su estructura se especifica mediante un tipo, que normalmente se basa en las clases utilizadas en la plataforma unificada .NET Core. También es posible trabajar con objetos COM, CIM (WMI) y ADSI. Se necesitan propiedades y métodos para realizar diversas acciones sobre los datos; además, en PowerShell, los objetos se pueden pasar como argumentos a funciones y cmdlets, asignar sus valores a variables, y también existe
Ver la estructura de los objetos.
Por ejemplo, ejecutemos el cmdlet Get-Process, que le permite obtener información sobre los procesos que se ejecutan en el sistema:
Mostrará algunos datos de texto formateados que no dan ninguna idea sobre las propiedades de los objetos devueltos y sus métodos. Para ajustar el resultado, necesitamos aprender a examinar la estructura de los objetos, y el cmdlet Get-Member nos ayudará con esto:
Get-Process | Get-Member
Aquí ya vemos el tipo y la estructura, y con la ayuda de parámetros adicionales podemos, por ejemplo, mostrar solo las propiedades del objeto incluido en la entrada:
Get-Process | Get-Member -MemberType Property
Este conocimiento será necesario para resolver problemas de administración de forma interactiva o para escribir sus propios scripts: por ejemplo, para obtener información sobre procesos colgados utilizando la propiedad Responding.
Filtrar objetos
PowerShell permite que los objetos que cumplen una determinada condición pasen a través de una canalización:
Where-Object { блок сценария }
El resultado de ejecutar el bloque de script entre paréntesis debe ser un valor booleano. Si es verdadero ($true), el objeto que se ingresa en el cmdlet Where-Object se pasará a lo largo de la canalización; de lo contrario ($false), se eliminará. Por ejemplo, mostremos una lista de servicios de Windows Server detenidos, es decir. aquellos cuya propiedad Estado está establecida en "Detenido":
Get-Service | Where-Object {$_.Status -eq "Stopped"}
Aquí nuevamente vemos una representación textual, pero si desea comprender el tipo y la estructura interna de los objetos que pasan por la tubería, no es difícil:
Get-Service | Where-Object {$_.Status -eq "Stopped"} | Get-Member
Ordenar objetos
Cuando se procesan objetos en canalización, a menudo existe la necesidad de ordenarlos. Al cmdlet Sort-Object se le pasan los nombres de las propiedades (claves de clasificación) y devuelve objetos ordenados por sus valores. Es fácil ordenar el resultado de los procesos en ejecución por el tiempo de CPU invertido (propiedad de la CPU):
Get-Process | Sort-Object –Property cpu
El parámetro -Property se puede omitir al llamar al cmdlet Sort-Object; se usa de forma predeterminada. Para ordenación inversa, use el parámetro -Descending:
Get-Process | Sort-Object cpu -Descending
Seleccionar objetos y sus partes.
El cmdlet Select-Object le permite seleccionar una cantidad específica de objetos al principio o al final de una canalización mediante los parámetros -First o -Last. Con su ayuda, puede seleccionar objetos individuales o ciertas propiedades, y también crear nuevos objetos basados en ellos. Veamos cómo funciona el cmdlet usando ejemplos simples.
El siguiente comando muestra información sobre los 10 procesos que consumen la cantidad máxima de RAM (propiedad WS):
Get-Process | Sort-Object WS -Descending | Select-Object -First 10
Puede seleccionar solo ciertas propiedades de los objetos que pasan por la tubería y crear otras nuevas basadas en ellas:
Get-Process | Select-Object ProcessName, Id -First 1
Como resultado de la operación de la canalización, recibiremos un nuevo objeto, cuya estructura será diferente de la estructura devuelta por el cmdlet Get-Process. Verifiquemos esto usando Get-Member:
Get-Process | Select-Object ProcessName, Id -First 1 | Get-Member
Tenga en cuenta que Select-Object devuelve un único objeto (-First 1) que tiene solo dos de los campos que especificamos: sus valores se copiaron del primer objeto pasado a la canalización mediante el cmdlet Get-Process. Una de las formas de crear objetos en scripts de PowerShell se basa en el uso de Select-Object:
$obj = Get-Process | Select-Object ProcessName, Id -First 1
$obj.GetType()
Usando Select-Object, puede agregar propiedades calculadas a objetos que deben representarse como
Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}}
Veamos la estructura de los objetos que pasan por el transportador:
Get-Process | Select-Object -Property ProcessName, @{Name="StartTime"; Expression = {$_.StartTime.Minute}} | Get-Member
Para cada objeto, objeto de grupo y objeto de medida
Existen otros cmdlets para trabajar con objetos. A modo de ejemplo, hablemos de los tres más útiles:
Para cada objeto le permite ejecutar código de PowerShell para cada objeto en la canalización:
ForEach-Object { блок сценария }
Objeto de grupo agrupa objetos por valor de propiedad:
Group-Object PropertyName
Si lo ejecuta con el parámetro -NoElement, puede averiguar la cantidad de elementos en los grupos.
Objeto de medida agrega varios parámetros de resumen por valores de campo de objeto en la canalización (calcula la suma y también encuentra el valor mínimo, máximo o promedio):
Measure-Object -Property PropertyName -Minimum -Maximum -Average -Sum
Normalmente, los cmdlets analizados se usan de forma interactiva y, a menudo, se crean en scripts.
Creación de objetos .NET y COM (Nuevo-Objeto)
Hay muchos componentes de software con interfaces .NET Core y COM que son útiles para los administradores de sistemas. Con la clase System.Diagnostics.EventLog, puede administrar los registros del sistema directamente desde Windows PowerShell. Veamos un ejemplo de cómo crear una instancia de esta clase usando el cmdlet New-Object con el parámetro -TypeName:
New-Object -TypeName System.Diagnostics.EventLog
Como no especificamos un registro de eventos específico, la instancia resultante de la clase no contiene datos. Para cambiar esto, necesita llamar a un método constructor especial durante su creación usando el parámetro -ArgumentList. Si queremos acceder al registro de la aplicación, debemos pasar la cadena "Aplicación" como argumento al constructor:
$AppLog = New-Object -TypeName System.Diagnostics.EventLog -ArgumentList Application
$AppLog
Tenga en cuenta que guardamos el resultado del comando en la variable $AppLog. Aunque las canalizaciones se utilizan comúnmente en modo interactivo, escribir scripts a menudo requiere mantener una referencia a un objeto. Además, las clases principales de .NET Core están contenidas en el espacio de nombres del sistema: PowerShell busca de forma predeterminada tipos específicos en él, por lo que escribir Diagnostics.EventLog en lugar de System.Diagnostics.EventLog es bastante correcto.
Para trabajar con el registro, puede utilizar los métodos adecuados:
$AppLog | Get-Member -MemberType Method
Digamos que se borra mediante el método Clear() si hay derechos de acceso:
$AppLog.Clear()
El cmdlet New-Object también se utiliza para trabajar con componentes COM. Hay bastantes, desde las bibliotecas suministradas con el servidor de scripts de Windows hasta aplicaciones ActiveX, como Internet Explorer. Para crear un objeto COM, debe configurar el parámetro -ComObject con el ProgId programático de la clase deseada:
New-Object -ComObject WScript.Shell
New-Object -ComObject WScript.Network
New-Object -ComObject Scripting.Dictionary
New-Object -ComObject Scripting.FileSystemObject
Para crear sus propios objetos con una estructura arbitraria, usar New-Object parece demasiado arcaico y engorroso; este cmdlet se usa para trabajar con componentes de software externos a PowerShell. En futuros artículos se abordará este tema con más detalle. Además de los objetos .NET y COM, también exploraremos los objetos CIM (WMI) y ADSI.
Llamar a métodos estáticos
No se pueden crear instancias de algunas clases de .NET Core, incluidas System.Environment y System.Math. Ellos son
[System.Environment] | Get-Member
Para ver solo miembros estáticos, llame a Get-Member con el parámetro -Static (tenga en cuenta el tipo de objeto):
[System.Environment] | Get-Member -Static
Para acceder a propiedades y métodos estáticos, utilice dos dos puntos consecutivos en lugar de un punto después del literal:
[System.Environment]::OSVersion
O
$test=[System.Math]::Sqrt(25)
$test
$test.GetType()
Escriba PSCustomObject
Entre los numerosos tipos de datos disponibles en PowerShell, cabe mencionar PSCustomObject, diseñado para almacenar objetos con una estructura arbitraria. Crear un objeto de este tipo utilizando el cmdlet New-Object se considera una forma clásica, pero engorrosa y obsoleta:
$object = New-Object –TypeName PSCustomObject -Property @{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'}
Veamos la estructura del objeto:
$object | Get-Member
A partir de PowerShell 3.0, hay otra sintaxis disponible:
$object = [PSCustomObject]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Puede acceder a los datos de una de las formas equivalentes:
$object.Name
$object.'Name'
$value = 'Name'
$object.$value
A continuación se muestra un ejemplo de cómo convertir una tabla hash existente en un objeto:
$hash = @{'Name'='Ivan Danko'; 'City'='Moscow'; 'Country'='Russia'}
$hash.GetType()
$object = [pscustomobject]$hash
$object.GetType()
Una de las desventajas de los objetos de este tipo es que el orden de sus propiedades puede cambiar. Para evitar esto, debes utilizar el atributo [ordenado]:
$object = [PSCustomObject][ordered]@{Name = 'Ivan Danko';
City = 'Moscow';
Country = 'Russia'
}
Hay otras opciones para crear un objeto: arriba vimos cómo usar el cmdlet
$object | Add-Member –MemberType NoteProperty –Name Age –Value 33
$object | Get-Member
El cmdlet Add-Member le permite agregar no solo propiedades, sino también métodos a un objeto $ creado previamente mediante la construcción "-MemberType ScriptMethod":
$ScriptBlock = {
# код
}
$object | Add-Member -Name "MyMethod" -MemberType ScriptMethod -Value $ScriptBlock
$object | Get-Member
Tenga en cuenta que utilizamos la variable $ScriptBlock de tipo ScriptBlock para almacenar el código del nuevo método.
Para eliminar propiedades, utilice el método correspondiente:
$object.psobject.properties.remove('Name')
Creando tus propias clases
PowerShell 5.0 introdujo la capacidad de definir
class MyClass
{
# тело класса
}
Este es un verdadero tipo .NET Core, con un cuerpo que describe sus propiedades, métodos y otros elementos. Veamos un ejemplo de cómo definir la clase más simple:
class MyClass
{
[string]$Name
[string]$City
[string]$Country
}
Para crear un objeto (instancia de clase), use el cmdlet
$object = New-Object -TypeName MyClass
o
$object = [MyClass]::new()
Analicemos la estructura del objeto:
$object | Get-Member
No se olvide del alcance: no puede hacer referencia a un nombre de tipo como una cadena ni utilizar un literal de tipo fuera del script o módulo en el que se define la clase. En este caso, las funciones pueden devolver instancias de clase (objetos) a las que se podrá acceder fuera del módulo o script.
Después de crear el objeto, complete sus propiedades:
$object.Name = 'Ivan Danko'
$object.City = 'Moscow'
$object.Country = 'Russia'
$object
Tenga en cuenta que la descripción de la clase especifica no sólo los tipos de propiedades, sino también sus valores predeterminados:
class Example
{
[string]$Name = 'John Doe'
}
La descripción de un método de clase se parece a la descripción de una función, pero sin utilizar la palabra función. Como en una función, los parámetros se pasan a los métodos si es necesario:
class MyClass
{
[string]$Name
[string]$City
[string]$Country
#описание метода
Smile([bool]$param1)
{
If($param1) {
Write-Host ':)'
}
}
}
Ahora el representante de nuestra clase puede sonreír:
$object = [MyClass]::new()
$object.Smile($true)
Los métodos pueden estar sobrecargados; además, una clase tiene
class MyClass2 : MyClass
{
#тело нового класса, базовым для которого является MyClass
}
[MyClass2]::new().Smile($true)
Nuestra descripción del trabajo con objetos en PowerShell no es exhaustiva. En las siguientes publicaciones intentaremos profundizar en esto con ejemplos prácticos: el quinto artículo de la serie estará dedicado a las cuestiones de la integración de PowerShell con componentes de software de terceros. Las partes anteriores se pueden encontrar en los enlaces a continuación.
Fuente: habr.com