Powershell: El cmdlet Test-Connection muestra datos no deseados.

Creado en 28 abr. 2018  ·  64Comentarios  ·  Fuente: PowerShell/PowerShell

pasos para reproducir

The Test-Connection cmdlet is displaying unwanted data as part of the result.

Code:

Test-Connection www.microsoft.com -Count 1 -Quiet

Comportamiento esperado

It should display just the word: True

Comportamiento real

Pinging www.microsoft.com [23.204.153.19] with 32 bytes of data:
Reply from 23.204.153.19: bytes=32 time=17ms TTL=58
Ping complete.
True

Datos ambientales

> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      6.1.0-preview.2
PSEdition                      Core
GitCommitId                    v6.1.0-preview.2
OS                             Microsoft Windows 10.0.16299
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Area-Cmdlets-Management Committee-Reviewed Issue-Bug Resolution-Fixed

Comentario más útil

@GeeLaw :

Buen hallazgo, pero es -InformationAction Ignore que se necesita en este caso para solucionar el error.

$InformationActionPreference todavía tiene como SilentlyContinue , y eso no debería cambiar.

El error es que las llamadas WriteInformation() que enlaza usan erróneamente la etiqueta PSHOST , que efectivamente _ omite_ el $InformationActionPreference y también -InformationAction SilentlyContinue (pero, como se indica , -InformationAction Ignore _es_ eficaz para suprimir la salida).

Lo que dicen que hacen las llamadas WriteInformation() es efectivamente lo que hacen Write-Host para _incondicionalmente_ mostrar su salida (por diseño).

@iSazonov : Realmente no he visto el comportamiento de otros cmdlets con barras de progreso, pero con -Quiet _no_ esperaría una barra de progreso, incluso al llamar de forma interactiva.

Todos 64 comentarios

Esto funciona correctamente en 5.1 pero no en 6, así que he reclasificado el problema como un error.

La razón es que el código actual llama a WriteInformation (¿a ciegas?).

Consulte la línea 751 de TestConnectionCommand.cs , también la línea 775 y la línea 783.

La solución temporal para evitar que la información se muestre al host es usar el parámetro común InformationAction . Ejemplo:

Test-Connection www.microsoft.com -Count 1 -Quiet -InformationAction Continue

Desde la perspectiva de las secuencias de comandos , esto no sería un problema , ya que la información textual nunca se escribe en la canalización y no, la salida textual no forma parte de los datos de resultados, que se definen como cosas enviadas a la canalización. Además, Quiet switch está definido para devolver resultados más simples ( int o bool , en lugar de objetos de registro). Tengo que admitir que uno no puede esperar InformationRecord con Quiet . Sin embargo, conociendo la razón, digo que será mejor que mantengamos InformationAction y Quiet desacoplados.

En PowerShell 5.1, Test-Connection no parece llamar a WriteInformation en absoluto. Por cierto, el valor predeterminado para $InformationPreference en PowerShell 5.1 y PowerShell Core 6.0.2 es SilentlyContinue . El autor del número podría tener un valor efectivo diferente cuando reprodujo el problema. (¿Quizás PS 6.1 Core cambió el valor predeterminado de $InformationPreference ? No estoy seguro).

Si PS 6.1 Core tuviera $InformationPreference predeterminado en SilentlyContinue , la información textual no estaría allí a menos que el usuario la solicite explícitamente.

Necesito más comentarios.
El problema es que en el modo script y en el modo interactivo debería funcionar de diferentes formas. En el modo interactivo, el usuario probablemente preferirá ver el progreso (barra) como sucede con el comando ping.exe. Esto también se aplica a otros parámetros.

@ mklement0 Si tienes tiempo, tu ayuda sería útil.

@GeeLaw :

Buen hallazgo, pero es -InformationAction Ignore que se necesita en este caso para solucionar el error.

$InformationActionPreference todavía tiene como SilentlyContinue , y eso no debería cambiar.

El error es que las llamadas WriteInformation() que enlaza usan erróneamente la etiqueta PSHOST , que efectivamente _ omite_ el $InformationActionPreference y también -InformationAction SilentlyContinue (pero, como se indica , -InformationAction Ignore _es_ eficaz para suprimir la salida).

Lo que dicen que hacen las llamadas WriteInformation() es efectivamente lo que hacen Write-Host para _incondicionalmente_ mostrar su salida (por diseño).

@iSazonov : Realmente no he visto el comportamiento de otros cmdlets con barras de progreso, pero con -Quiet _no_ esperaría una barra de progreso, incluso al llamar de forma interactiva.

@ mklement0 Gracias por la respuesta y la corrección en PSHostTag . Me parece que InformationPreference ( InformationAction ) no aceptará Ignore ? Esto es cierto en 5.1 y 6.0.2. Quizás en 6.1 ha cambiado. (¿Es InformationActionPreference un nuevo alias para InformationPreference ?)

Además, mi primer comentario fue erróneo, por eso establece InformationAction en Continue . La solución correcta es descartar el flujo 6 (flujo de información) redirigiéndolo a $null , es decir,

Test-Connection www.microsoft.com -Count 1 -Quiet 6> $null

Verifique la exactitud de la siguiente manera:

Write-Host 'Hello, world' 6> $null

No debería escribir nada al anfitrión.

@GeeLaw :

Me parece que InformationPreference (InformationAction) no acepta ¿Ignorar?

Sí, la _variable de preferencia_ no acepta Ignore , pero el _ parámetro común_ sí.

Es decir, puede suprimir el flujo de información (número 6 ) _para una invocación determinada_, pero no _categóricamente_ para todo el alcance, por diseño.

Por lo tanto, las siguientes dos declaraciones son equivalentes:

Test-Connection www.microsoft.com -Count 1 -Quiet 6> $null
Test-Connection www.microsoft.com -Count 1 -Quiet -InformationAction Ignore

En otras palabras: tanto 6> $null como -InformationAction Ignore son soluciones eficaces.

¿Es InformationActionPreference un nuevo alias para InformationPreference ?

No, el nombre siempre ha sido $InformationPreference , siguiendo el patrón de $VerbosePreference , $WarningPreference y $DebugPreference .

Por lo que puedo decir, es solo el par -ErrorAction / $ErrorActionPreference donde el nombre de la variable de preferencia conserva la parte Action .


Aparte de la prohibición de Ignore como valor de acción _variables de preferencia_:

  • Hay un problema de diseño fundamental con esta restricción, porque las variables de preferencia locales definidas automáticamente se utilizan para propagar valores de parámetros comunes dentro de funciones avanzadas - ver # 1759

  • La restricción no se aplica en el _momento de la asignación_, lo que significa que no verá el problema hasta que la preferencia se aplique (posiblemente implícitamente) la próxima vez; consulte el n. ° 4348

    • De manera más general, en cualquier ámbito excepto en el global, no se realiza ninguna validación; comparar $ErrorActionPreference = 'bogus' con & { $ErrorActionPreference = 'bogus' } - ver

      3483.

@ mklement0 Estaba preguntando por el alias porque lo mencionaste como InformationActionPreference .

Que yo sepa, -XxxAction (y -Verbose y -Debug ) simplemente establecen la variable de preferencia correspondiente dentro del cmdlet invocado. Como se documenta en los temas de ayuda de about_ , específicamente tenemos lo siguiente:

The value of the -InformationAction parameter, if used, overrides the current value of the $InformationPreference variable.

Within the command or script in which it is used, the InformationAction common parameter overrides the value of the $InformationPreference preference variable, which by default is set to SilentlyContinue.

Interpreto esto como establecer una variable de preferencia local, como puede ser validado por la siguiente demostración:

function test-func { [cmdletbinding()]param() process { $InformationPreference } }
test-func # gives SilentlyContinue
test-func -InformationAction Continue # gives Continue
test-func -InformationAction Ignore # gives Ignore

En 5.1 y 6.0.2, InformationAction no acepta Ignore , como se puede demostrar con el siguiente fragmento:

function test-func { [cmdletbinding()]param() process { write-information 'writing' } }
test-func -InformationAction Ignore

produce

Write-Information : The value Ignore is not supported for an ActionPreference variable. The provided value should be used only as a value for a preference
parameter, and has been replaced by the default value. For more information, see the Help topic, "about_Preference_Variables."
At line:1 char:57
+ ...  { [cmdletbinding()]param() process { Write-Information 'writing' } }
+                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Write-Information], NotSupportedException
    + FullyQualifiedErrorId : System.NotSupportedException,Microsoft.PowerShell.Commands.WriteInformationCommand

Me pregunto si eso cambió en 6.1.


Hay otra cosa interesante: $VerbosePreference y $DebugPreference realidad acepta un rango más amplio que el que puede establecer el parámetro común correspondiente. Por ejemplo, es posible establecer $VerbosePreference en Inquire por asignación explícita, pero no es posible usando -Verbose switch porque, después de todo, es un switch y asigna $True / $False a Continue / SilentlyContinue .

Hasta donde yo sé, a excepción de esos dos conmutadores, los parámetros comunes relacionados con las preferencias se asignan exactamente a las variables de preferencia correspondientes en el ámbito local.

Otra ronda de juegos muestra que el siguiente código funciona:

Write-Information 'writing' -InformationAction Ignore

Pero eso sería engorroso para los desarrolladores, ya que tenemos que proteger Write-Information con el cheque $InformationAction -eq 'Ignore' , y evitar llamarlo en primer lugar, por ejemplo,

Function Test-Inf1
{
    [CmdletBinding()] Param ( )
    Process { Write-Information 'Hello, world!' }
}
Function Test-Inf2
{
    [CmdletBinding()] Param ( )
    Process { If ($InformationPreference -ne 'Ignore') { Write-Information 'Hello, world!' } }
}
Test-Inf1 -InformationAction Ignore # writes an error
Test-Inf2 -InformationAction Ignore # okay

Parece que lo mismo se aplica a los autores que escriben cmdlets con C #.

@GeeLaw

Le preguntaba por el alias porque lo mencionó como InformationActionPreference.

¡Ups! Lo siento, no había notado mi propio error tipográfico.

simplemente establece la variable de preferencia correspondiente dentro del cmdlet invocado.

Sí, y el resto de lo que demuestras es el tema del mencionado # 1759.

En resumen: el defecto de diseño es que no permitir Ignore como valor de variable de preferencia choca con el uso de instancias de variable de preferencia local configuradas automáticamente para propagar valores de parámetro común.

Más específicamente:

En 5.1 y 6.0.2, InformationAction no acepta Ignorar, como se puede demostrar con el siguiente fragmento:

Dado que es importante con respecto a la resolución del problema, permítame señalar que -InformationAction _acepta Ignore , y solo dicho defecto de diseño es el que causa el problema _si y cuando se aplica la preferencia_ en el contexto de _funciones avanzadas_, que en su caso es la llamada Write-Information _dentro_ de la función.
Este problema persiste a partir de PowerShell Core v6.1.0-preview.2.

Los _ cmdlets compilados_, por el contrario, no tienen este problema, por lo que Write-Host foo -InformationAction Ignore funciona según lo previsto, por ejemplo, como ha descubierto desde entonces.

Para resumir, hemos estado discutiendo dos problemas no relacionados aquí:

  • La falla de diseño con respecto a Ignore como valor de variable de preferencia de acción, que ya se está rastreando en # 1759.

  • El tema original de este número, el cmdlet Test-Connection que se comporta mal, utiliza por error la etiqueta PSHOST en sus llamadas a .WriteInformation .

La solución para esto último es simplemente _omitar_ la etiqueta, como lo demuestra el siguiente ejemplo:

# With $InformationAction at its default, 'SilentlyContinue', this invocation is silent.
# If you set it to 'Continue', 'foo' prints.
& { [CmdletBinding()]param() $PSCmdlet.WriteInformation('foo', [string[]] @()) } 

Entonces me encontré con esto porque estoy experimentando el mismo problema en el que no se respeta -Quiet. Miré el código y es un poco difícil de seguir y muy complicado para lo que está haciendo, pero no vi ningún lugar que realmente esté buscando esto como una cuestión de suprimir la salida, ni veo desde dónde está cambiando generar una cadena en un booleano, que es lo que se debe generar cuando se pasa el parámetro -Quiet.

Envié un PR el año pasado (# 2537) para agregar Test-Connection al código y fue rechazado en ese momento porque "@ PowerShell / powershell-Committee no aceptaría este PR ya que introduciría problemas de compatibilidad en el futuro", así que me sorprendió ver la inclusión de este cmdlet ahora, pero no con el código del PR original, sino con un código nuevo que no proporciona toda la funcionalidad esperada.

El mayor problema con el que me encuentro es en mis scripts que realizo verificaciones como esta, "si (Test-Connection 8.8.8.8 -Quiet)" para ramificarme en mi lógica, pero con el parámetro -Quiet no siendo respetado, la rama siempre devuelve True porque no hay Falso o Nulo. Por lo tanto, esto hace que el comando siga siendo completamente inutilizable para mí, y también dado que se ha incluido en las nuevas versiones de PowerShell, eso hace que la actualización sea muy delicada para mí. Solucione este problema, ya que parece que han pasado varios meses desde que se informó por primera vez. O eso, o restablecer el PR original, no importa siempre que se devuelva la funcionalidad.

Envié un PR el año pasado para agregar Test-Connection al código y eso fue rechazado en ese momento porque no querían agregar cmdlets heredados, así que me sorprendió ver la inclusión de este cmdlet ahora, pero no con el código. del PR original que estaba completo y funcionaba exactamente como lo hacía la versión "heredada".

Si tenemos Test-Connection en 5.1 y 6.x, esperaría que tuvieran el mismo resultado. Sé que la implementación es diferente, pero a los usuarios no les debería importar eso. La conexión de prueba actual en 6.1 se comporta de manera diferente y nos da una salida diferente a la de 5.1. Además de eso, el parámetro -Quiet es prácticamente inútil.

Parece que este problema sigue en pie, a partir de ahora (PSVersion = 6.2.0) el cmdlet continúa mostrando la información de "ping" incluso si QUIET está presente (agregar "-InformationAction Ignore" hace el truco pero significa módulos / scripts usando el cmdlet Test-Connection tendrá que actualizarse, no es genial)

Sería realmente bueno si pudiéramos arreglar esto para 7.0. Estoy más que feliz de contribuir con el código, pero necesitamos una especificación de implementación a seguir, ya que hubo muy poco acuerdo sobre los intentos anteriores de mejorar esto.

cc @ SteveL-MSFT @iSazonov

Vuelvo a esto de vez en cuando. Ahora creo que podríamos resolver esto usando una separación explícita de escenarios interactivos y no interactivos con el interruptor -Intercative . Con el parámetro podríamos implementar una salida de consola rica y fácil de usar. Parece que no es demasiado inconveniente para el usuario escribir este parámetro (como "-i"). Sin el conmutador, haríamos una salida de tipo fuerte sin una salida de consola detallada que sea buena para escenarios de scripts.

Dado que ningún otro cmdlet usa este parámetro, no creo que tenga sentido tener tal dualidad. Un cmdlet debe realizar su tarea y comportarse de forma coherente; El comportamiento interactivo no debe separarse de cómo se comporta de otro modo.

Por ejemplo, mire Get-ChildItem. Interactivamente, es muy útil gracias a la pantalla del formateador predeterminada. No se necesitan cambios para que también sea útil para fines de automatización; el mismo comando que funciona de forma interactiva también funciona en un script.

Eso es una complejidad innecesaria, creo.

Podríamos hacer la salida interactiva por defecto y mejorar el parámetro Quiet para suprimir la salida en los scripts.

De nuevo ... no veo la necesidad de tener una salida diferente de forma interactiva frente a los scripts.

Si el cmdlet simplemente se comporta como otros cmdlets y genera datos inutilizables en lugar de ser completamente único y generar todos sus datos en un flujo de texto difícil de capturar o analizar (esto es _PowerShell_, no Bash), no hay absolutamente ninguna necesidad de un cambio de comportamiento .

-Quiet es un modificador que usa el cmdlet original en Windows PowerShell para dar una respuesta puramente verdadera / falsa, en lugar de generar objetos. Romper esa convención es una mala idea, en mi opinión.

Este cmdlet debe comportarse de manera coherente con los cmdlets existentes. No hay razón para que solo use el comportamiento actual. En su iteración actual, se comporta más como uno esperaría que operara una utilidad Unix, muy diferente a cómo operan otros cmdlets de PowerShell.

De nuevo ... no veo la necesidad de tener una salida diferente de forma interactiva frente a los scripts.

¿Puede realizar una demostración de la salida deseada en todos los escenarios admitidos? Tenga en cuenta que la metainformación que genera el cmdlet es muy importante.

generar todos sus datos en un flujo de texto difícil de capturar o analizar

El cmdlet genera una salida de objetos de tipo fuerte. (El problema es que es imposible construir estos objetos y mostrarlos simultáneamente porque hay "meta" información).

-Quiet es un modificador que usa el cmdlet original en Windows PowerShell para dar una respuesta puramente verdadera / falsa, en lugar de generar objetos. Romper esa convención es una mala idea, en mi opinión.

Ese cmdlet de Windows PowerShell solo admite ping para el que no existe el concepto de conexión. Este fue inicialmente un diseño controvertido. El nombre correcto para ellos sería Test-Ping ot Test-ICMP .
El cmdlet actual admite "conexiones" ip. Aunque preferiría algo como "Test-Connectivity".

En su iteración actual, se comporta más como uno esperaría que operara una utilidad Unix, muy diferente a cómo operan otros cmdlets de PowerShell.

No, el cmdlet genera una salida de objetos de tipo fuerte. Y la salida de la consola se hizo para parecer utilidades. Pero al mismo tiempo, puede ver que, de hecho, es más rico y útil.
El problema es que esta salida no se puede obtener utilizando las capacidades del subsistema de formateo y es necesario hacer una salida directa a la consola. (Tenga en cuenta que esto no se mezcla con los objetos de salida en el flujo de salida)

La salida se puede obtener con el sistema de formato, si estructuramos los objetos de datos de una manera más robusta. Ya envié un PR con un prototipo. Un cmdlet que muestra datos en una forma que no refleja adecuadamente los datos del objeto subyacente (por ejemplo, mostrando datos de subpropiedades en lugar de estructurar correctamente la clase de objeto) es generalmente engañoso y, en mi opinión, debe evitarse siempre que sea posible.

Examinaré esto más a fondo y armaré un ejemplo más completo de lo que percibo como resultado deseado. Test-Connection en Windows PowerShell puede haber sido un diseño controvertido, pero creo que fue un paso en la dirección correcta, aunque muy incompleto.

@iSazonov No estaba de acuerdo contigo después de la primera lectura PERO después de la prueba, entiendo tu punto de vista

$a=Test-Connection www.microsoft.com 
$b=Test-Connection www.microsoft.com -Quiet

Los valores de $ ay $ b son los que espero, PERO no quiero la salida adicional.

Select-String también tiene un parámetro Quiet y no tiene nada que ver con el comportamiento "interactivo"

Estoy de acuerdo en que este comando necesita un parámetro adicional para cambiar el comportamiento (Silencio o no).

Prefiero el parámetro 'Interactivo' no por defecto, pero tal vez un parámetro de cambio "NoInteractive" sea un mejor ajuste para dar prioridad al uso interactivo.

Muy bien, esto es lo que consideraría una implementación algo más útil.

Puntos generales

  1. Toda la salida actual de host / información se relega al flujo -Verbose . Actualmente eso no se usa _ en absoluto_, y este es un caso de uso perfecto para ello.
  2. Sin barra de progreso a menos que se especifique con un interruptor -ShowProgress .
  3. Elimina el modificador -Ping (es el comportamiento predeterminado).

Salida primaria

Test-Connection www.google.com

  • La información de la propiedad Replies del objeto de salida debe incluirse en el objeto de salida principal, y el modo de salida principal debe ser _múltiples_ objetos, cada uno de los cuales representa un único objeto de intento / respuesta de ping.
  • El búfer _data_ generalmente es irrelevante, ya que no se puede especificar, y solo se debe exponer una propiedad BufferSize . Replies.Buffer propiedad debe permanecer private .
  • Replies.Options propiedad
  • Los resultados se muestran como una tabla, agrupados por dirección de destino (en el caso de que se especifiquen varios destinos).

Maqueta visual de salida

Comando utilizado:

$Result = Test-Connection www.google.com
$Data = foreach ($Reply in $Result.Replies) {
    [PSCustomObject]@{
        Source = $Result.Source
        Destination = $Result.Destination
        Address = $Reply.Address
        RoundtripTime = $Reply.RoundtripTime
        BufferSize = $Reply.Buffer.Length
        Options = $Reply.Options
    }
}
$Data | Format-Table -GroupBy Destination -Property Source, Address, RoundtripTime, BufferSize

Salida resultante:

   Destination: www.google.com
Source  Address       RoundtripTime BufferSize
------  -------       ------------- ----------
WS-JOEL 172.217.2.132            36         32
WS-JOEL 172.217.2.132            21         32
WS-JOEL 172.217.2.132            25         32
WS-JOEL 172.217.2.132            25         32

Test-Connection www.google.com -TraceRoute

  • Cada salto debe generarse como un objeto separado, cada uno de los cuales contiene los objetos PingReply como una propiedad a la que se puede acceder ocultando el formato.
  • El objeto TraceRouteResult debe contener ETS o propiedades de clase que calculen datos de resumen de sus cuatro PingReplies.
  • Nota: Este tipo de objeto que estamos usando tiene errores actualmente, y todos los objetos PingReply reportan TtlExpired como su estado. Se recomienda investigar el progreso de la corrección para .NET Core 3 o diseñar una solución personalizada para el respaldo de TraceRoute para resolver el problema.
  • Salida como una tabla, agrupada por DestinationHost (¿Por qué este nombre de propiedad es diferente al del otro tipo de objeto usado para pings estándar?)

Maqueta visual de salida

Comando utilizado:

$Result = Test-Connection www.google.com -TraceRoute
$Data = foreach ($Reply in $a.Replies) {
    [PSCustomObject]@{
        Hop = $Reply.Hop
        Source = $a.Source
        Destination = $a.DestinationHost
        DestinationAddress = $a.DestinationAddress
        Replies = $Reply.PingReplies
        RoundtripTimes = $Reply.PingReplies.RoundtripTime
        HopAddress = $Reply.PingReplies[0].Address
        BufferSize = $Reply.PingReplies.ForEach{$_.Buffer.Length}
        Options = $Reply.PingReplies[0].Options
    }
}

$Data | Format-Table -GroupBy Destination -Property Hop, RoundtripTimes, DestinationAddress, HopAddress, BufferSize

Salida resultante:

   Destination: www.google.com
Hop RoundtripTimes DestinationAddress HopAddress     BufferSize
--- -------------- ------------------ ----------     ----------
  1 {0, 0, 0}      172.217.2.132      192.168.22.254
  2 {0, 0, 0}      172.217.2.132      75.144.219.238
  3 {0, 0, 0}      172.217.2.132      96.120.37.17
  4 {0, 0, 0}      172.217.2.132      96.110.136.65
  5 {0, 0, 0}      172.217.2.132      69.139.180.170
  6 {0, 0, 0}      172.217.2.132      68.85.127.121
  7 {0, 0, 0}      172.217.2.132      68.86.165.161
  8 {0, 0, 0}      172.217.2.132      68.86.90.205
  9 {0, 0, 0}      172.217.2.132      68.86.82.154
 10 {0, 0, 0}      172.217.2.132      66.208.233.242
 11 {0, 0, 0}      172.217.2.132      0.0.0.0
 12 {0, 0, 0}      172.217.2.132      216.239.59.124
 13 {0, 0, 0}      172.217.2.132      216.239.59.61
 14 {32, 28, 20}   172.217.2.132      172.217.2.132

Estoy firmemente convencido de que si presentamos datos al usuario, deberían ser fácilmente accesibles de forma programática, con una estructura de superficie similar a la que se muestra en pantalla. Cambiar el nombre de las propiedades o enterrar los datos en uno o dos niveles de profundidad en una propiedad del objeto de salida solo invita a la confusión, los informes de errores, la frustración y una disminución significativa en la usabilidad general.

Oh, @ vexx32 Veo que nunca diagnosticaste una red. Implementé su propuesta en el primer paso y luego la rechacé por no ser adecuada para su uso en una sesión interactiva. Por ejemplo, podemos mirar una pantalla en blanco durante mucho tiempo después de ejecutar un comando Test-Connection www.google.com -TraceRoute . Entonces, la implementación se cambió para mostrar una salida (cadena o barra de progreso) para cada respuesta.

Toda la salida actual de host / información se relega al flujo -Verbose. Actualmente eso no se usa en absoluto, y este es un caso de uso perfecto para ello.

Mi sugerencia anterior fue introducir Interactive switch para dividir el escenario interactivo y el script. Sugieres hacer lo mismo con Verbose switch, que es una práctica aún más antinatural.

Sin barra de progreso a menos que se especifique con un modificador -ShowProgress.

La salida de cadena y la barra de progreso están en implementación actual como dos alternativas. Solo necesitamos uno. La barra de progreso se usa en el cmdlet de Windows PowerShell. Mi preferencia es la salida de cadenas en una sesión interactiva. Es mucho más conveniente.
Y nunca suprimimos una barra de progreso con un interruptor. Tenemos $ ProgressPreference para escenarios de script. Algunos cmdlets muestran una barra de progreso solo para operaciones largas por temporizador.

Quite el interruptor -Ping (es el comportamiento predeterminado).

La mejor práctica es utilizar parámetros explícitos en los scripts. Hace que el código sea más legible. No era necesario en el cmdlet de Windows PowerShell donde solo se implementó ping. El nuevo cmdlet implementa más funcionalidades y necesitamos un nuevo parámetro explícito para cada uno.

Implementé su propuesta en el primer paso y luego la rechacé por no ser adecuada para su uso en una sesión interactiva. Por ejemplo, podemos mirar una pantalla en blanco durante mucho tiempo después de ejecutar un comando Test-Connection www.google.com -TraceRoute. Entonces, la implementación se cambió para mostrar una salida (cadena o barra de progreso) para cada respuesta.

La visualización del progreso no es necesaria con el formato de objeto dividido, ya que podemos ver fácilmente el progreso a medida que cada objeto se envía a la salida. La única razón por la que es necesario aquí es porque no enviamos datos a la canalización, ya que se recuperan como lo hace cualquier otro cmdlet de PowerShell. Si generamos en cada PingReply o traza un salto para -TraceRoute tenemos una pantalla de progreso incorporada en la pantalla de salida.

Mi sugerencia anterior fue introducir el interruptor interactivo para dividir escenarios interactivos y guiones. Sugieres hacer lo mismo con el interruptor Verbose, que es una práctica aún más antinatural.

-Verbose es un parámetro común y, por lo tanto, una opción mucho más natural para un cmdlet que un modificador completamente nuevo. No necesitamos reinventar la rueda aquí.

La mejor práctica es utilizar parámetros explícitos en los scripts. Hace que el código sea más legible. No era necesario en el cmdlet de Windows PowerShell donde solo se implementó ping. El nuevo cmdlet implementa más funcionalidades y necesitamos un nuevo parámetro explícito para cada uno.

No estoy aquí ni allá en esto, pero normalmente el comportamiento predeterminado de un cmdlet no tiene un modificador. Por ejemplo, no tenemos un -Loud como el reverso de -Quiet .

La visualización del progreso no es necesaria con el formato de objeto dividido, ya que podemos ver fácilmente el progreso a medida que cada objeto se envía a la salida.

Con su propuesta anterior, recopilamos objetos "ping" en el objeto "meta" y es imposible generar los objetos "ping" en tiempo real; podemos generar en la canalización solo el objeto "meta"; el usuario verá una pantalla en blanco en todo momento.

-Verbose es un parámetro común y, por lo tanto, una opción mucho más natural para un cmdlet que un modificador completamente nuevo.

No tengo conocimiento de ningún cmdlet que genere información significativa en el flujo detallado. Siempre usamos esta secuencia para mostrar información de diagnóstico adicional para que comprendamos el proceso de ejecución de un cmdlet.

normalmente, el comportamiento predeterminado de un cmdlet no tiene un modificador.

Es adecuado para un solo conjunto de parámetros. Ahora tenemos muchos conjuntos de parámetros y necesitamos designar explícitamente cada uno.

Con su propuesta anterior, recopilamos objetos "ping" en el objeto "meta" y es imposible generar los objetos "ping" en tiempo real; podemos generar en la canalización solo el objeto "meta"; el usuario verá una pantalla en blanco en todo momento.

El meta objeto es innecesario. Como se mencionó en la propuesta anterior, los objetos se crearían y generarían para _each_ PingReply o trace hop. La maqueta no es el código final, simplemente un formato fácil de duplicar para ilustrar la idea. Cada entrada de la tabla se generará una por una. Lea la propuesta completa.

No tengo conocimiento de ningún cmdlet que genere información significativa en el flujo detallado. Siempre usamos esta secuencia para mostrar información de diagnóstico adicional para que comprendamos el proceso de ejecución de un cmdlet.

Tampoco estoy al tanto de _cualquier_ cmdlet que rutinariamente esté enviando información "significativa" a la información / host y no a la salida, excepto enterrado varios niveles en otro objeto.

Es adecuado para un solo conjunto de parámetros. Ahora tenemos muchos conjuntos de parámetros y necesitamos designar explícitamente cada uno.

No creo que sea de mucha utilidad hacerlo, pero supongo que no crea una cantidad significativa de daño. Simplemente creo que es una pérdida de tiempo; No estoy seguro de que mucha gente vea de mucha utilidad especificar un interruptor para el comportamiento predeterminado.

El meta objeto es innecesario.

_Es fundamental necesario_.
Este enfoque hace que el cmdlet sea algo inútil. Si tiene una red donde hay problemas, intente ejecutar un diagnóstico con ese cmdlet. No puedes hacer esto. Lo lanzará y tomará las utilidades de ping y traceroute. Pero ahora puede hacer los mismos diagnósticos con el nuevo cmdlet tanto en la consola como, por ejemplo, en el sistema de monitoreo con un script. Entiendo que es difícil de entender si no realiza diagnósticos de red regulares. Vea cuántos parámetros tienen estas utilidades nativas, especialmente en las versiones Unix. Todos ellos son importantes para el diagnóstico. El arte del diagnóstico consiste en utilizar sus combinaciones y significados mágicos. Intenté agregar todo esto al nuevo cmdlet.

Simplemente creo que es una pérdida de tiempo

El uso de parámetros posicionales le ayuda :-)

El breve resumen del Comité de PowerShell.

Se diseñó el cmdlet actual

  • para obtener un cmdlet portátil para todas las plataformas compatibles. Realmente todavía tenemos algunos problemas en .Net Core, por lo que no todas las funciones funcionan en las formas de plan Unix
  • para obtener funciones de herramientas populares como ping, traceroute, pathping, Portqry.exe, etc.
  • para obtener objetos de salida útiles en __scripts__ adecuados para análisis de accesibilidad de red simples y detallados
  • para obtener resultados de consola útiles con _header_ y _footer_. Observe que el cmdlet muestra información aún más útil en algunos escenarios que la utilidad de protótopos nativos.
  • para permitir mejoras futuras como pruebas remotas "Test-Connection -Source ... -Destination ..."

El principal problema es cómo combinar la salida de la consola interactiva (escenario interactivo) y la salida de objetos en la canalización (escenario de script). Mi sugerencia actual es hacer una división con un parámetro (-Interactive) o con un nuevo cmdlet (Show-Connectivity para escenario interactivo y Test-Connectivity para escenario de script).
También sugiero cambiar el nombre del cmdlet a Test -__ Connectivity__, que es más preciso. También permitirá el uso gratuito del antiguo cmdlet de Windows mediante proxy (WCM) sin conflicto de nombres.

@iSazonov ¿ puede proporcionar un ejemplo de dicho diagnóstico que requiera que haya un metaobjeto que oculte todos los datos? Mi propuesta es mover la información del meta objeto a cada objeto PingReply; No veo cómo eso disminuiría la utilidad del cmdlet.

¿Cómo coloca las estadísticas desde el pie de página hasta el primer objeto "ping" si genera el objeto inmediatamente después de la creación?

¿Qué información de pie de página? La única información de pie de página de un ping es Ping complete.

No hay estadísticas en los metaobjetos actuales que pueda ver en cualquier lugar; simplemente contienen todos los objetos con la misma información que se representan como datos de cadena en el flujo de información, solo que en un formato menos utilizable.

El punto aquí es mantener los cmdlets (en este caso Test-Connection) de la misma manera en ambas versiones (WinPS y Pwsh) agregando un interruptor al cmdlet para, en este caso, 'deshabilitar' esa salida sería incorrecta ya que como dije antes de que signifique que cada script / módulo que use este cmdlet tendrá que actualizarse, la solución es hacerlo de la misma manera en ambas versiones

El cmdlet de Windows @ NJ-Dude se basa en WMI y es imposible portarlo con compatibilidad con versiones anteriores. También se congeló 5.1; no habrá adiciones en el futuro.

El cmdlet de Windows @ NJ-Dude se basa en WMI y es imposible portarlo con compatibilidad con versiones anteriores. También se congeló 5.1; no habrá adiciones en el futuro.

Entiendo y sé que, solo digo que la SINTAXIS y la funcionalidad deberían ser las mismas, es decir, si el uso de QUIET no muestra ninguna salida, entonces no debería mostrar ninguna salida independientemente del tipo de PS que se esté usando.

Solo digo que SYNTAX y la funcionalidad deberían ser las mismas

Es imposible. El módulo de compatibilidad de Windows es una forma única de obtener la funcionalidad anterior.

La salida de un cmdlet debería poder almacenarse y usarse sin tener que suprimir también manualmente la visualización no deseada en la consola que de alguna manera está separada de la salida principal.

No hay ningún otro cmdlets que se comporte de esta manera, donde los datos más útiles están en forma de cadena en el flujo de información. No hay ninguna razón para que se comporte de esta manera. Todos los datos deben estar en el flujo de salida, punto . Los datos adicionales están en los flujos detallados o de depuración según sea necesario. El uso del flujo de información de esta manera no tiene precedentes literalmente para un cmdlet que se incluye con PowerShell.

Y como se mencionó, no hay datos en el pie de página que mencionas que necesiten estar específicamente en un pie de página; todo está disponible desde el principio o a medida que se procesa cada respuesta.

Poner esto en cola para una discusión del Comité

Así que perdí un poco la pista del hilo aquí, teniendo problemas en la maleza, pero mi opinión básica sin tener en cuenta la implementación es esta:

  • Los datos deben enviarse línea por línea. Creo que ese es el caso actual con Test-Connection sy ping.exe et al.
  • Los datos deben devolverse como un objeto estructurado. El formato debe ser independiente de este hecho. (Por horrible que sea esto, he visto un formateador que emite una cadena JSON a la consola a pesar de que es un objeto PSObject bajo el capó. Mi punto es simplemente que se puede hacer). El formateo también es un lugar donde podemos Se nos permite cambiar lo que queramos sin romper los cambios. (También estoy muy de acuerdo con @ vexx32 en que debemos tener cuidado con los encabezados de columna que no coinciden con los nombres de las propiedades. En ocasiones es necesario para la legibilidad, pero también me vuelve loco).
  • -Quiet debería emitir nada excepto True / False como booleano, al igual que Windows PowerShell.
  • Si hay más información que necesitamos emitir que el caso predeterminado (que debería ser más que el booleano mínimo -Quiet caso), -Verbose suena razonable, pero no lo he pensado lo suficiente. (Aquí es también donde pierdo el hilo, es difícil decir qué quieren más personas arriba).
  • Imitar exactamente el mismo objeto ( cimv2\Win32_PingStatus ) con todas las mismas propiedades que Windows PowerShell es imposible (porque .NET Core, WMI, etc.), pero deberíamos intentar acercarlo lo más posible.
  • No sé de progreso. Mi opinión de alto nivel es que el progreso aún enloquece a todos porque es lento (a pesar de nuestras optimizaciones), pero también que no importa tanto en los no interactivos porque todos están configurando $ProgressPreference todos modos.

¡Suena bien para mí!

El progreso principalmente me molesta muchísimo porque no se puede manejar en la llamada de comando; tienes que establecer $ ProgressPreference. Realmente desearía que fuera un parámetro común ... Pero tengo otro problema al quejarme al respecto, ¡así que no entremos en eso aquí! :sonreír:

@ PowerShell / powershell-Committee revisó esto. Acordamos que Test-Connection debería emular el comportamiento de Windows PowerShell 5.1 lo más fielmente posible (incluido -Quiet ). Esto significa que se debe emitir un objeto de salida PingStatus (eliminando win32_ ) para cada respuesta que tenga las propiedades en el formato predeterminado y las adicionales que estén disponibles. No se debe utilizar el progreso.

¿Alguien estaría dispuesto a crear un RFC breve que muestre la sintaxis del cmdlet junto con el formato de salida propuesto para su revisión?

@ stevel-msft Me encantaría. :)

Amo el sonido de eso.
Gracias

Es un poco interesante que PR 3125 cubriera todo esto, pero el uso de Test-Connection fue rechazado, pero ahora hemos completado el círculo. ¿Qué hay de mirar hacia atrás en 3125?

Mirándolo brevemente, parece que esencialmente reemplazó Test-Connection con un comando implementado de manera diferente en plataformas Unix para intentar emular el comando de Windows. ¿Estoy leyendo eso bien?

No creo que esa sea la mejor opción disponible para nosotros; la coherencia en ambas plataformas en la implementación del comando en su conjunto es más valiosa. Sin embargo, puede que tenga algunas ideas interesantes que podamos utilizar, ¡estoy seguro!

Dejaré un enlace al borrador del RFC cuando termine de escribirlo y siéntete libre de comentar, ajustar, etc. Me encantaría escuchar más puntos de vista sobre esto. 🙂

EDITAR: https://github.com/PowerShell/PowerShell-RFC/pull/172

Mi caso de uso específico para solicitar esto se basó en el deseo de usar PowerShell Core en Linux, pero la implementación se probó completamente tanto en Windows como en Linux. Estaba destinado a reemplazar el comando faltante en su totalidad.

¿Cuándo veremos esto? En 6.2.2? ¿Cuándo aterrizará probablemente?
(Fue divertido ver que este hilo se extendió desde abril de 2018 hasta ahora sobre _-quiet_ siendo ruidoso. Parece un cambio tan obvio)

Creo que puedo escribir este código con bastante facilidad, solo estoy esperando que se acepte el RFC. Tan pronto como eso suceda, lo haré y enviaré un PR para esto. :sonreír:

Oh, pensé que el estado era que estaba aprobado (sin saber exactamente qué estados hay o cuál es el proceso completo). Pero gracias por la actualización. Sigue siendo una lástima que se hayan tardado más de 12 meses en silenciarlo :)

más de 12 meses para hacerlo tranquilo

Esperaba más comentarios

@ vexx32 puede comenzar a codificar esto y ponerlo detrás de una bandera experimental en caso de que llegue algún comentario que cambie la propuesta actual

@ SteveL-MSFT Ya tengo una implementación que funciona principalmente. Buscaré enviar un PR con algunas banderas experimentales pronto para que podamos hablar sobre el código de manera más concreta. 💖

Después de pensar en los últimos días sobre el comportamiento deseado, preferiría tener un comportamiento interactivo con un mínimo de parámetros por defecto (escritura rápida y visualización amigable), lo que sería conveniente en una sesión interactiva. Y convertir al estilo de script con parámetros adicionales (esto implica diferentes tipos en la salida).

¿Podrías explicar un poco más cómo crees que podría funcionar @isazonov?

@ vexx32 ¿Preguntas sobre implementación o diseño UX?

Principalmente, creo que lo que crees que sería la UX para eso. :)

En una sesión interactiva, la mejor experiencia de usuario es
1. mecanografía mínima
Significa:
- ping es predeterminado
- cambiar a otro modo (traceroute y etc.) con un parámetro
2. salida fácil de usar
Significa:
- emular la salida de ping.exe (tracert.exe y otros) _en el host de la consola_ como lo intenté en el código de demostración, con encabezados, pies de página y líneas informativas bien formateadas. No es necesario pensar en los tipos de salida: no se utilizan, solo se muestran.
- agregar parámetros para cambiar al modo de secuencia de comandos, es decir, suprimir la salida de texto fácil de usar en el host de la consola y emitir objetos de tipo fuerte. No es necesario formatear esta salida. Hablamos de Quiet, que devuelve Verdadero / Falso, pero necesitamos un parámetro (s) para emitir otros objetos crudos de tipo fuerte (como -RawOutput). Es aceptable UX usar parámetros adicionales en scripts.

Gracias, creo que ahora entiendo un poco mejor lo que estás haciendo.

Sin embargo, realmente no veo la necesidad de un modo dual como este. Ningún otro cmdlets de PowerShell tiene esta división entre parámetros interactivos y "modo de secuencia de comandos".

Si quisiera la salida exacta de ping / tracert, ¿por qué no usaría esas utilidades directamente?

PowerShell nunca ha realizado un esfuerzo significativo para imitar completamente un comando existente; Creo que Get-ChildItem es probablemente el más cercano, pero es casi el único que lo hace.

Si quisiéramos emular completamente la pantalla de ping / tracert como usted dice, sugeriría que en su lugar lo tengamos como un cmdlet o función separada, por ejemplo, Show-Connection , en lugar de desordenar Show-Command con parámetros adicionales que no tienen precedente o necesidad dentro de PowerShell.

Sin embargo, realmente no veo la necesidad de un modo dual como este. Ningún otro cmdlets de PowerShell tiene esta división entre parámetros interactivos y "modo de secuencia de comandos".

Tenemos lagunas en nuestro sistema de formato. Por ejemplo, tenemos un problema con la solicitud de tener un directorio de encabezado / pie de página. Hay otros escenarios en los que sería conveniente.

Si quisiera la salida exacta de ping / tracert, ¿por qué no usaría esas utilidades directamente?

Hago :-). Estas utilidades nativas son muy poderosas porque son de bajo nivel pero están congeladas. Podemos hacer cosas _más inteligentes_ que ellos; esta es la esencia de la apariencia de este cmdlet (y no solo para hacer un ping), si observa en profundidad cómo se forman ahora las direcciones y nombres en el cmdlet y cómo son salidas, verá que son mucho más útiles que en el ping nativo. Parece un truco pero es realmente muy útil.

Por supuesto, tenemos lagunas en el sistema de formato. Pero no creo que la respuesta sea implementar una solución personalizada _todas las veces_. Eso solo crea más problemas y hace que sea aún más difícil mejorar o reescribir el sistema de formato para que sea más efectivo en todos los ámbitos.

Sí, ¡has hecho un gran trabajo con él! Te lo agradezco mucho. El modo de salida actual no es útil para nada _pero_ uso interactivo. Podríamos simplemente eliminar el paso de salida y llamarlo Show-Connection y luego utilizar lo que ha escrito en una solución más centrada en PowerShell para Test-Connection como describo en el RFC.

@ vexx32 Acabo de probar su PR y lo mejora bastante, pero noté que en Windows PowerShell, emite PingReply individualmente a la canalización para que obtenga algo que se parece a:

PS C:\Users\slee> Test-Connection localhost

Source        Destination     IPV4Address      IPV6Address                              Bytes    Time(ms)
------        -----------     -----------      -----------                              -----    --------
SLEE-DESKTOP  localhost       127.0.0.1        ::1                                      32       0
SLEE-DESKTOP  localhost       127.0.0.1        ::1                                      32       0
SLEE-DESKTOP  localhost       127.0.0.1        ::1                                      32       0
SLEE-DESKTOP  localhost       127.0.0.1        ::1                                      32       0

Sin embargo, con su cambio, todas las respuestas de ping son miembros de un solo objeto:

PS> Test-Connection localhost

Source       Destination Replies
------       ----------- -------
slee-desktop localhost   {System.Net.NetworkInformation.PingReply, System.Net.NetworkInformation.PingReply, System.Net.NetworkInformation.PingReply, System.Net.N…

¿No podemos recuperar el comportamiento de Windows PowerShell?

@ SteveL-MSFT La salida de ese objeto no ha cambiado desde la implementación inicial en PS Core; la salida de éxito siempre ha tenido un único objeto. 🙂

Como se mencionó en los comentarios finales del RP, esa es solo una implementación parcial del RFC para ayudar a simplificar las revisiones. En breve enviaré un PR de seguimiento. Solo tiene que reajustar esa rama para eliminar las confirmaciones ahora duplicadas y enviar el resto para acercarse mucho más a la verdadera paridad con la implementación de Windows PowerShell. Todavía diferirá un poco (como se puede ver en el RFC que revisamos hace unas semanas) pero con suerte será mucho más versátil. 😊

@ SteveL-MSFT, consulte el número 10697 para ver el próximo capítulo de esta aventura. 😊

: tada: este problema se abordó en # 10478, que ahora se ha publicado con éxito como v7.0.0-preview.5 .: tada:

Enlaces útiles:

En la versión 7.0.0 Test-Connection -Quiet todavía da
Prueba de conexión: Prueba de conexión a la computadora 'borrada' falló: No se puede resolver el nombre de destino.
en vez de
Falso

@chvol, ¿ podría abrir un nuevo número para eso con el mayor detalle posible?

¡Gracias! 🙂

¿Fue útil esta página
0 / 5 - 0 calificaciones