Powershell: Cmdlet Test-Connection exibindo dados indesejados.

Criado em 28 abr. 2018  ·  64Comentários  ·  Fonte: PowerShell/PowerShell

Passos para reproduzir

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

Code:

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

Comportamento esperado

It should display just the word: True

Comportamento 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

Dados ambientais

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

Comentários muito úteis

@GeeLaw :

Bom achado, mas é -InformationAction Ignore que é necessário neste caso para contornar o bug.

$InformationActionPreference ainda tem como padrão SilentlyContinue , e isso não deve mudar.

O bug é que as chamadas WriteInformation() que você vincula usam erroneamente a tag PSHOST , que efetivamente _bypasses_ o $InformationActionPreference e também -InformationAction SilentlyContinue (mas, como indicado , -InformationAction Ignore _is_ eficaz em suprimir a saída).

O que as chamadas WriteInformation() fazem é efetivamente o que Write-Host faz para _uncondicionalmente_ exibir sua saída (por design).

@iSazonov : Eu realmente não olhei para o comportamento de outros cmdlets com barras de progresso, mas com -Quiet eu _não_ esperaria uma barra de progresso, mesmo quando chamando interativamente.

Todos 64 comentários

Isso funciona corretamente no 5.1, mas não no 6, então reclassifiquei o problema como um bug.

O motivo é que o código atual chama WriteInformation (às cegas?).

Consulte a linha 751 de TestConnectionCommand.cs , também as linhas 775 e 783.

A solução temporária para impedir que as informações sejam exibidas para o host é usar o parâmetro InformationAction common. Exemplo:

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

Do ponto de vista do script , isso não seria um problema , já que as informações textuais nunca são gravadas no pipeline e não, a saída textual não faz parte dos dados do resultado, que são definidos como coisas enviadas ao pipeline. Além disso, Quiet switch é definido para retornar resultados mais simples ( int ou bool , em vez de objetos de registro). Tenho que admitir que não se pode esperar InformationRecord com Quiet . No entanto, sabendo o motivo, acho melhor manter InformationAction e Quiet desacoplados.

No PowerShell 5.1, Test-Connection não parece chamar WriteInformation alguma. A propósito, o valor padrão para $InformationPreference no PowerShell 5.1 e PowerShell Core 6.0.2 é SilentlyContinue . O autor da edição pode ter um valor efetivo diferente quando reproduziu a edição. (Talvez o PS 6.1 Core tenha alterado o valor padrão de $InformationPreference ? Não tenho certeza.)

Se o PS 6.1 Core tivesse $InformationPreference padronizado como SilentlyContinue , a informação textual não estaria lá a menos que o usuário explicitamente pedisse por ela.

Eu preciso de mais feedback.
O problema é que no modo script e no modo interativo deve funcionar de maneiras diferentes. No modo interativo, o usuário provavelmente preferirá ver o progresso (barra) conforme ocorre com o comando ping.exe. Isso se aplica a outros parâmetros também.

@ mklement0 Se você tiver tempo, sua ajuda será útil.

@GeeLaw :

Bom achado, mas é -InformationAction Ignore que é necessário neste caso para contornar o bug.

$InformationActionPreference ainda tem como padrão SilentlyContinue , e isso não deve mudar.

O bug é que as chamadas WriteInformation() que você vincula usam erroneamente a tag PSHOST , que efetivamente _bypasses_ o $InformationActionPreference e também -InformationAction SilentlyContinue (mas, como indicado , -InformationAction Ignore _is_ eficaz em suprimir a saída).

O que as chamadas WriteInformation() fazem é efetivamente o que Write-Host faz para _uncondicionalmente_ exibir sua saída (por design).

@iSazonov : Eu realmente não olhei para o comportamento de outros cmdlets com barras de progresso, mas com -Quiet eu _não_ esperaria uma barra de progresso, mesmo quando chamando interativamente.

@ mklement0 Obrigado pela resposta e pela correção em PSHostTag . Parece-me que InformationPreference ( InformationAction ) não aceita Ignore ? Isso é verdade em 5.1 e 6.0.2. Talvez no 6.1 tenha mudado. ( InformationActionPreference um novo alias para InformationPreference ?)

Além disso, meu primeiro comentário estava errado, pois define InformationAction para Continue . A solução alternativa correta é descartar o fluxo 6 (fluxo de informações) redirecionando-o para $null , ou seja,

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

Verifique a exatidão da seguinte forma:

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

Não deve escrever nada para o host.

@GeeLaw :

Parece-me que InformationPreference (InformationAction) não aceita Ignorar?

Sim, a _variável de preferência_ não aceita Ignore , mas o _parâmetro comum_ aceita.

Ou seja, você pode suprimir o fluxo de informações (número 6 ) _para uma determinada invocação_, mas não _categoricamente_ para todo o escopo - por design.

Portanto, as duas declarações a seguir são equivalentes:

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

Em outras palavras: 6> $null e -InformationAction Ignore são soluções alternativas eficazes.

InformationActionPreference um novo apelido para InformationPreference ?

Não, o nome sempre foi $InformationPreference , seguindo o padrão de $VerbosePreference , $WarningPreference e $DebugPreference .

Pelo que eu posso dizer, é apenas o par -ErrorAction / $ErrorActionPreference onde o nome da variável de preferência retém a parte Action .


Como um aparte em relação à proibição de Ignore como o valor da ação _variáveis ​​de preferência_:

  • Há um problema de design fundamental com essa restrição, porque variáveis ​​de preferência local definidas automaticamente são usadas para propagar valores de parâmetros comuns dentro de funções avançadas - consulte # 1759

  • A restrição não é aplicada no momento da limitação_, o que significa que você não verá o problema até que a preferência seja (possivelmente implicitamente) aplicada da próxima vez - consulte # 4348

    • De maneira mais geral, em qualquer escopo exceto o global, nenhuma validação é realizada; compare $ErrorActionPreference = 'bogus' com & { $ErrorActionPreference = 'bogus' } - veja

      3483.

@ mklement0 Eu estava perguntando sobre o alias porque você o mencionou como InformationActionPreference .

Até onde sei, -XxxAction (e -Verbose e -Debug ) simplesmente define a variável de preferência correspondente dentro do cmdlet invocado. Conforme documentado nos tópicos de ajuda about_ , especificamente temos o seguinte:

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.

Eu interpreto isso como a definição de uma variável de preferência local, que pode ser validada pela seguinte demonstração:

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

Em 5.1 e 6.0.2, InformationAction não aceita Ignore , como pode ser demonstrado pelo seguinte snippet:

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

produz

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

Eu me pergunto se isso mudou em 6.1.


Há outra coisa interessante: $VerbosePreference e $DebugPreference realmente aceitam um intervalo mais amplo do que aquele que pode ser definido pelo parâmetro comum correspondente. Por exemplo, é possível definir $VerbosePreference para Inquire por atribuição explícita, mas não é possível usando -Verbose switch porque, afinal, é um switch e mapeia $True / $False a Continue / SilentlyContinue .

Até onde eu sei, exceto por essas duas opções, os parâmetros comuns relacionados à preferência mapeiam exatamente para as variáveis ​​de preferência correspondentes no escopo local.

Outra rodada de brincadeiras mostra que o seguinte código funciona:

Write-Information 'writing' -InformationAction Ignore

Mas isso seria complicado para os desenvolvedores, pois temos que proteger Write-Information com o cheque $InformationAction -eq 'Ignore' e evitar chamá-lo em primeiro lugar, por exemplo,

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 o mesmo se aplica a autores que escrevem cmdlets com C #.

@GeeLaw

Eu estava perguntando sobre o alias porque você o mencionou como InformationActionPreference.

Ops! Desculpe - não notei meu próprio erro de digitação.

simplesmente define a variável de preferência correspondente dentro do cmdlet invocado.

Sim, e o resto do que você demonstra é o assunto do # 1759 mencionado anteriormente.

Resumindo: a falha de design é que não permitir Ignore como um valor de variável de preferência entra em conflito com o uso de instâncias de variável de preferência local definidas automaticamente para propagar valores de parâmetro comum.

Mais especificamente:

Em 5.1 e 6.0.2, InformationAction não aceita Ignorar, como pode ser demonstrado pelo seguinte snippet:

Uma vez que é importante em relação à resolução do problema, deixe-me apontar que -InformationAction _sobre_ aceita Ignore , e é apenas a referida falha de design que causa o problema _se e quando a preferência for aplicada_ no contexto de _funções avançadas_, que no seu caso é a Write-Information chamada _interior_ da função.
Este problema persiste a partir do PowerShell Core v6.1.0-preview.2.

Os _cmdlets_ compilados, por outro lado, não têm esse problema, e é por isso que Write-Host foo -InformationAction Ignore funciona conforme planejado, por exemplo, como você já descobriu.

Para resumir, estivemos discutindo dois problemas não relacionados aqui:

  • A falha de design em relação a Ignore como um valor de variável de preferência de ação, que já está sendo rastreado em # 1759.

  • O tópico original deste problema, o cmdlet Test-Connection incorreto, que usa por engano a tag PSHOST em suas chamadas para .WriteInformation .

A solução para o último é simplesmente _omit_ a tag, como o exemplo a seguir demonstra:

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

Então me deparei com isso porque estou enfrentando o mesmo problema em que -O silêncio não está sendo respeitado. Eu olhei para o código e é um pouco difícil de seguir e muito complicado para o que está fazendo, mas não vi nenhum lugar que esteja realmente procurando por isso como uma questão de suprimir a saída, nem estou vendo de onde está mudando enviar uma string para um booleano, que é o que deve ser enviado quando o parâmetro -Quiet é passado.

Eu enviei um PR no ano passado (# 2537) para adicionar Test-Connection ao código e isso foi rejeitado na época porque "@ PowerShell / powershell-Committee não aceitaria este PR porque iria introduzir problemas de compatibilidade no futuro", por isso, fiquei surpreso ao ver a inclusão deste cmdlet agora, mas não com o código do PR original, mas um código totalmente novo que não fornece todas as funcionalidades esperadas.

O maior problema que encontro é em meus scripts que eu executo verificações como esta, “if (Test-Connection 8.8.8.8 -Quiet)” para ramificar em minha lógica, mas com o parâmetro -Quiet não sendo respeitado, a ramificação sempre retorna True porque não existe um False ou Null. Portanto, isso torna o comando ainda completamente inutilizável para mim, e também como foi incluído em novas versões do PowerShell, isso torna a atualização muito delicada para mim. Corrija isso, pois parece que já se passaram vários meses desde que o problema foi relatado pela primeira vez. Isso, ou reinstalar o PR original, não importa, desde que a funcionalidade seja devolvida.

Eu enviei um PR no ano passado para adicionar Test-Connection ao código e que foi rejeitado na época porque eles não queriam adicionar cmdlets legados, então fiquei surpreso ao ver a inclusão deste cmdlet agora, mas não com o código do PR original que estava completo e funcionava exatamente como a versão "legada".

Se tivermos Test-Connection em 5.1 e 6.x, eu esperaria que eles tivessem a mesma saída. Eu sei que a implementação é diferente, mas os usuários não devem se preocupar com isso. A conexão de teste atual em 6.1 se comporta de maneira diferente, dando-nos uma saída diferente da 5.1. Além disso, o parâmetro -Quiet é praticamente inútil.

Parece que o problema ainda existe, a partir de agora (PSVersion = 6.2.0) o cmdlet continua a exibir as informações de "ping" mesmo se QUIET estiver presente (adicionar "-InformationAction Ignore" funciona, mas significa módulos / scripts usando o cmdlet Test-Connection terá que ser atualizado, não é legal)

Seria muito bom se pudéssemos consertar isso para 7.0. Estou mais do que feliz em contribuir com o código, mas precisamos de uma especificação de implementação a seguir, pois havia muito pouco acordo sobre as tentativas anteriores de melhorar isso.

cc @ SteveL-MSFT @iSazonov

Eu volto a isso de vez em quando. Agora eu acredito que poderíamos resolver isso usando uma separação explícita de cenários interativos e não interativos com -Intercative switch. Com o parâmetro, podemos implementar uma saída de console rica e amigável. Parece que não é muito inconveniente para o usuário digitar este parâmetro (como "-i"). Sem a opção, teríamos uma saída de tipo forte sem uma saída de console verbosa, que é boa para cenários de script.

Visto que nenhum outro cmdlet usa esse parâmetro, não acho que faça sentido ter essa dualidade. Um cmdlet deve realizar sua tarefa e se comportar de maneira consistente; O comportamento interativo não deve ser separado de como se comporta de outra forma.

Por exemplo, observe Get-ChildItem. Interativamente, é muito útil graças à exibição do formatador padrão. Nenhuma mudança é necessária para torná-lo útil para fins de automação; o mesmo comando que funciona interativamente também funciona em um script.

Essa é uma complexidade desnecessária, eu sinto.

Poderíamos fazer a saída interativa por padrão e aprimorar o parâmetro Quiet para suprimir a saída nos scripts.

Novamente ... Não vejo a necessidade de ter uma saída diferente interativamente em relação aos scripts.

Se o cmdlet simplesmente se comportar como outros cmdlets e gerar dados inutilizáveis ​​em vez de ser totalmente exclusivo e gerar todos os seus dados em um fluxo de texto difícil de capturar ou analisar (isto é _PowerShell_, não Bash), não há absolutamente nenhuma necessidade de mudança no comportamento .

-Quiet é uma opção usada pelo cmdlet original no Windows PowerShell para fornecer uma resposta True / False pura, em vez de objetos de saída. Quebrar essa convenção é uma má ideia, na minha opinião.

Este cmdlet deve se comportar de maneira consistente com os cmdlets existentes. Não há razão para que ele sozinho use o comportamento atual. Em sua iteração atual, ele se comporta mais como se esperaria que um utilitário Unix operasse, muito diferente de como outros cmdlets do PowerShell operam.

Novamente ... Não vejo a necessidade de ter uma saída diferente interativamente em relação aos scripts.

Você pode demonstrar a saída desejada em todos os cenários suportados? Observe que a meta informação que o cmdlet produz é muito importante.

saída de todos os seus dados em um fluxo de texto difícil de capturar ou analisar

O cmdlet produz uma saída de objeto de tipo forte. (O problema é que é impossível construir esses objetos e exibi-los simultaneamente porque há "meta" informações.)

-Quiet é uma opção usada pelo cmdlet original no Windows PowerShell para fornecer uma resposta True / False pura, em vez de objetos de saída. Quebrar essa convenção é uma má ideia, na minha opinião.

Esse cmdlet do Windows PowerShell oferece suporte apenas a ping para o qual o conceito de conexão não existe. Este foi um design inicialmente controverso. O nome certo para eles seria Test-Ping ot Test-ICMP .
O cmdlet atual oferece suporte a "conexões" de IP. Embora eu prefira algo como "Teste de conectividade".

Em sua iteração atual, ele se comporta mais como se esperaria que um utilitário Unix operasse, muito diferente de como outros cmdlets do PowerShell operam.

Não, o cmdlet produz uma saída de objeto de tipo forte. E a saída do console foi feita para se parecer com utilitários. Mas, ao mesmo tempo, você verá que, na verdade, é mais rico e útil.
O problema é que essa saída não pode ser obtida usando os recursos do subsistema de formatação e é necessário fazer uma saída direta para o console. (Observe que isso não se confunde com objetos de saída no fluxo de saída)

A saída pode ser obtida com o sistema de formatação, se estruturarmos os objetos de dados de forma mais robusta. Já enviei um PR com um protótipo. Um cmdlet que exibe dados em um formato que não reflete adequadamente os dados do objeto subjacente (por exemplo, exibindo dados de subpropriedades em vez de estruturar adequadamente a classe de objeto) geralmente é enganoso e, em minha opinião, deve ser evitado sempre que possível.

Examinarei isso mais detalhadamente e reunirei um exemplo mais completo do que considero ser a saída desejada. O teste de conexão no Windows PowerShell pode ter sido um design controverso, mas acho que foi um passo na direção certa, embora muito incompleta.

@iSazonov Não concordei com você após a primeira leitura, MAS após o teste, eu entendo seu ponto de vista

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

Os valores $ a e $ b são o que espero, MAS não quero a saída extra.

Select-String também tem um parâmetro silencioso e não tem nada a ver com o comportamento "interativo"

Concordo que este comando precisa de um parâmetro adicional para alterar o comportamento (Silencioso ou não).

Eu prefiro o parâmetro 'Interativo' não por padrão, mas talvez um parâmetro de opção "NoInteractive" seja um ajuste melhor para dar prioridade ao uso interativo.

Tudo bem, aqui está o que eu consideraria uma implementação um pouco mais útil.

Pontos Gerais

  1. Todas as saídas de informações / hosts atuais são relegadas ao fluxo -Verbose . Atualmente isso não é usado _de forma alguma_ e este é um caso de uso perfeito para ele.
  2. Nenhuma barra de progresso, a menos que seja especificado com um switch -ShowProgress .
  3. Remova a opção -Ping (é o comportamento padrão).

Produto Primário

Test-Connection www.google.com

  • As informações da propriedade Replies do objeto de saída devem ser incluídas no objeto de saída principal e o modo de saída principal deve ser _múltiplos_ objetos, cada um representando uma única tentativa de ping / objeto de resposta.
  • Os _dados_ do buffer geralmente são irrelevantes, pois não podem ser especificados e apenas uma propriedade BufferSize deve ser exposta. Replies.Buffer propriedade deve permanecer private .
  • Replies.Options propriedade deve ser ocultada da formatação padrão.
  • Saída de resultados como uma tabela, agrupados por endereço de destino (no caso de vários destinos serem especificados).

Modelo visual de saída

Comando usado:

$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

Resultado 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 deve ser gerado como um objeto separado, cada um contendo os objetos PingReply como uma propriedade acessível por meio de ocultação da formatação.
  • O objeto TraceRouteResult deve conter as propriedades ETS ou de classe que calculam os dados de resumo de seus quatro PingReplies.
  • Nota: Este tipo de objeto que estamos usando está atualmente bugado , e todos os objetos PingReply relatam TtlExpired como seu status. Recomende investigar o andamento da correção do .NET Core 3 ou projetar uma solução personalizada para o suporte do TraceRoute para resolver o problema.
  • Saída como uma tabela, agrupada por DestinationHost (por que esse nome de propriedade é diferente daquele de outro tipo de objeto usado para pings padrão?)

Modelo visual de saída

Comando usado:

$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

Resultado 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

Estou firmemente convicto de que, se estivermos apresentando dados ao usuário, eles devem estar prontamente acessíveis de forma programática, com uma estrutura de superfície semelhante à que está sendo exibida na tela. Renomear propriedades ou enterrar dados em um ou dois níveis de profundidade em uma propriedade do objeto de saída apenas convida a confusão, relatórios de bug, frustração e uma diminuição significativa na usabilidade geral.

Oh, @ vexx32 vejo que você nunca diagnosticou uma rede. Sua proposta foi implementada por mim na primeira etapa e depois rejeitada por não ser adequada para uso em uma sessão interativa. Por exemplo, podemos olhar para uma tela em branco por muito tempo depois de executar um comando Test-Connection www.google.com -TraceRoute . Portanto, a implementação foi alterada para mostrar uma saída (string ou barra de progresso) para cada resposta.

Todas as saídas de host / informações atuais são relegadas ao fluxo -Verbose. Atualmente isso não é usado de forma alguma, e este é um caso de uso perfeito para isso.

Minha sugestão acima foi introduzir Interactive switch para dividir o cenário interativo e o script. Você sugere fazer o mesmo com Verbose switch, que é uma prática ainda menos natural.

Nenhuma barra de progresso, a menos que seja especificado com uma opção -ShowProgress.

A saída da string e a barra de progresso estão na implementação atual como duas alternativas. Precisamos apenas de um. A barra de progresso é usada no cmdlet do Windows PowerShell. Minha preferência é a saída de string na sessão interativa. É muito mais conveniente.
E nunca suprimimos uma barra de progresso com um switch. Temos $ ProgressPreference para cenários de script. Alguns cmdlets mostram uma barra de progresso apenas para operações longas por cronômetro.

Remova a opção -Ping (é o comportamento padrão).

A melhor prática é usar parâmetros explícitos em scripts. Isso torna o código mais legível. Não era necessário no cmdlet do Windows PowerShell onde apenas ping foi implementado. O novo cmdlet implementa mais funcionalidades e precisamos de um novo parâmetro explícito para cada um.

Sua proposta foi implementada por mim na primeira etapa e depois rejeitada por não ser adequada para uso em uma sessão interativa. Por exemplo, podemos olhar para uma tela em branco por muito tempo depois de executar um comando Test-Connection www.google.com -TraceRoute. Portanto, a implementação foi alterada para mostrar uma saída (string ou barra de progresso) para cada resposta.

A exibição de progresso não é necessária com o formato de objeto dividido, pois podemos ver facilmente o progresso à medida que cada objeto é enviado para a saída. A única razão pela qual ele é necessário aqui é porque não enviamos dados para o pipeline, pois eles são recuperados como qualquer outro cmdlet do PowerShell. Se dermos saída em cada PingReply ou salto de rastreamento para -TraceRoute nós _teremos_ exibição de progresso embutida na exibição de saída.

Minha sugestão acima foi introduzir o switch Interactive para dividir o cenário interativo e o script. Você sugere fazer o mesmo com a opção Verbose, que é uma prática ainda mais artificial.

-Verbose é um parâmetro comum e, portanto, uma escolha muito mais natural para um cmdlet do que um switch completamente novo. Não precisamos reinventar a roda aqui.

A melhor prática é usar parâmetros explícitos em scripts. Isso torna o código mais legível. Não era necessário no cmdlet do Windows PowerShell onde apenas ping foi implementado. O novo cmdlet implementa mais funcionalidades e precisamos de um novo parâmetro explícito para cada um.

Não estou aqui nem ali sobre isso, mas normalmente o comportamento padrão de um cmdlet não tem uma opção. Por exemplo, não temos um switch -Loud como o reverso de -Quiet .

A exibição de progresso não é necessária com o formato de objeto dividido, pois podemos ver facilmente o progresso à medida que cada objeto é enviado para a saída.

Com a sua proposta acima, coletamos objetos "ping" no objeto "meta" e é impossível gerar os objetos "ping" em tempo real - podemos enviar no pipeline apenas o objeto "meta" - o usuário verá uma tela em branco o tempo todo.

-Verbose é um parâmetro comum e, portanto, uma escolha muito mais natural para um cmdlet do que uma opção completamente nova.

Não tenho conhecimento de nenhum cmdlet que estava gerando informações significativas para o fluxo detalhado. Sempre usamos esse fluxo para exibir informações de diagnóstico adicionais para que possamos entender o processo de execução de um cmdlet.

normalmente, o comportamento padrão de um cmdlet não tem uma opção.

É adequado para um único conjunto de parâmetros. Agora temos muitos parâmetros definidos e precisamos designar explicitamente cada um.

Com a sua proposta acima, coletamos objetos "ping" no objeto "meta" e é impossível gerar os objetos "ping" em tempo real - podemos enviar no pipeline apenas o objeto "meta" - o usuário verá uma tela em branco o tempo todo.

O meta objeto é desnecessário. Conforme mencionado na proposta acima, os objetos seriam criados e produzidos para _cada_ PingReply ou salto de rastreamento. O mock up não é o código final, apenas um formato fácil de duplicar para ilustrar a ideia. Cada entrada na tabela seria produzida uma por uma. Por favor, leia a proposta completa.

Não tenho conhecimento de nenhum cmdlet que estava gerando informações significativas para o fluxo detalhado. Sempre usamos esse fluxo para exibir informações de diagnóstico adicionais para que possamos entender o processo de execução de um cmdlet.

Também não estou ciente de _qualquer_ cmdlet que rotineiramente produz informações "significativas" para as informações / host e não para a saída, exceto enterrado em vários níveis profundos em outro objeto.

É adequado para um único conjunto de parâmetros. Agora temos muitos parâmetros definidos e precisamos designar explicitamente cada um.

Não acho que haja muita utilidade em fazer isso, mas não cria uma quantidade significativa de dano, suponho. Eu simplesmente acho que é uma perda de tempo; Não tenho certeza se muitas pessoas verão muita utilidade em especificar uma opção para o comportamento padrão.

O meta objeto é desnecessário.

_É fundamentalmente necessário._
Essa abordagem torna o cmdlet uma coisa inútil. Se você tiver uma rede com problemas, tente executar um diagnóstico usando esse cmdlet. Você não pode fazer isso. Você vai jogá-lo e usar os utilitários ping e traceroute. Mas agora você pode fazer o mesmo diagnóstico com o novo cmdlet no console e, por exemplo, no sistema de monitoramento com um script. Eu entendo que é difícil entender se você não faz diagnósticos de rede regulares. Veja quantos parâmetros esses utilitários nativos possuem, especialmente nas versões Unix. Todos eles são importantes para o diagnóstico. A arte do diagnóstico consiste em usar suas combinações e significados mágicos. Tentei adicionar tudo isso ao novo cmdlet.

Eu simplesmente acho que é uma perda de tempo

O uso de parâmetros posicionais ajuda você a :-)

O breve resumo do Comitê do PowerShell.

O cmdlet atual foi projetado

  • para obter cmdlet portátil para todas as plataformas com suporte. Na verdade, ainda temos alguns problemas no .Net Core, então nem todos os recursos funcionam em planforms Unix
  • para obter recursos de ferramentas populares como ping, traceroute, pathping, Portqry.exe e etc
  • para obter objetos de saída úteis em __scripts__ adequados para análise de acessibilidade de rede simples e profunda
  • para obter uma saída de console útil com _header_ e _footer_. Observe que o cmdlet exibe informações ainda mais úteis em alguns cenários do que o utilitário de protótipo nativo.
  • para permitir melhorias futuras, como testes remotos "Test-Connection -Source ... -Destination ..."

O principal problema é como combinar a saída do console interativo (cenário interativo) e a saída de objetos no pipeline (cenário de script). Minha sugestão atual é fazer uma divisão com um parâmetro (-Interactive) ou com um novo cmdlet (Show-Connectivity para cenário interativo e Test-Connectivity para cenário de script).
Também sugiro alterar o nome do cmdlet para Test -__ Connectivity__ que é mais preciso. Também permitirá o uso gratuito do antigo cmdlet do Windows por meio de proxy (WCM) sem conflito de nome.

@iSazonov você pode fornecer um exemplo de um diagnóstico que exija que haja um metaobjeto que oculte todos os dados? Minha proposta é mover as informações do metaobjeto para cada objeto PingReply; Não vejo como isso diminuiria a utilidade do cmdlet.

Como você coloca estatísticas do rodapé para o primeiro objeto de "ping" se você gerar o objeto imediatamente após a criação?

Quais informações de rodapé? A única informação de rodapé de um ping é Ping complete.

Não há estatísticas nos objetos meta atuais que eu possa ver em qualquer lugar; eles apenas contêm todos os objetos com as mesmas informações que estão sendo processados ​​como dados de string no fluxo de informações, apenas em um formato menos utilizável.

O objetivo aqui é manter os cmdlets (neste caso Test-Connection) da mesma maneira em ambas as versões (WinPS e Pwsh), adicionando uma opção ao cmdlet para, neste caso, para 'desabilitar' a saída estaria errada, pois como eu disse antes que signifique que cada script / módulo usando este cmdlet terá que ser atualizado, a solução é torná-lo da mesma maneira em ambas as versões

@ NJ-Dude O cmdlet do Windows é baseado no WMI e é impossível portá-lo com compatibilidade com versões anteriores. Também 5.1 foi congelado - nenhuma adição será no futuro.

@ NJ-Dude O cmdlet do Windows é baseado no WMI e é impossível portá-lo com compatibilidade com versões anteriores. Também 5.1 foi congelado - nenhuma adição será no futuro.

Eu entendo e sei que, estou apenas dizendo que a SINTAXE e a funcionalidade devem ser as mesmas, ou seja, se o uso de QUIET não exibir nenhuma saída, ele não deve exibir nenhuma saída, independentemente do tipo de PS sendo usado.

Só estou dizendo que a SYNTAX e a funcionalidade devem ser as mesmas

É impossível. O módulo de compatibilidade do Windows é uma forma única de obter a funcionalidade antiga.

A saída de um cmdlet deve poder ser armazenada e usada sem a necessidade de suprimir manualmente a exibição indesejada no console que é de alguma forma separada da saída principal.

_Nenhum outro cmdlets_ se comporta dessa maneira, em que os dados mais úteis estão na forma de string no fluxo de informações. Não há razão para se comportar dessa maneira. Todos os dados devem estar no fluxo de saída, ponto final . Dados adicionais estão nos fluxos detalhados ou de depuração, conforme necessário. O uso do fluxo de informações dessa maneira é literalmente sem precedentes para um cmdlet que vem com o próprio PowerShell.

E, como mencionado, não há dados no rodapé que você mencionou que precisem estar especificamente em um rodapé; está tudo disponível desde o início ou à medida que cada resposta é processada.

Enfileirando isso para uma discussão do Comitê

Entããão, perdi um pouco o fio da meada aqui, tendo problemas no mato, mas minha opinião básica, sem considerar a implementação, é esta:

  • Os dados devem ser produzidos linha por linha. Acho que esse é o caso atual com Test-Connection s e ping.exe et al
  • Os dados devem ser retornados como um objeto estruturado. A formatação deve ser independente desse fato. (Por mais horrível que seja, eu vi um formatador que emite uma string JSON para o console, apesar de ser um PSObject subjacente. Meu ponto é simplesmente que isso pode ser feito.) A formatação também é um lugar onde nós tem permissão para alterar o que quisermos sem interromper as alterações. (Também concordo totalmente com @ vexx32 que devemos ter cuidado com os cabeçalhos das colunas que não correspondem aos nomes das propriedades. Ocasionalmente, é necessário para facilitar a leitura, mas também me deixa louco.)
  • -Quiet deve emitir nada, exceto True / False como um booleano, assim como o Windows PowerShell.
  • Se houver mais informações que precisamos emitir do que o caso padrão (que deve ser mais do que o caso booleano -Quiet mínimo), -Verbose parece razoável, mas eu não pensei sobre isso o suficiente. (É aqui também que eu perco o fio, difícil dizer o que mais pessoas querem acima).
  • Imitar exatamente o mesmo objeto ( cimv2\Win32_PingStatus ) com todas as mesmas propriedades do Windows PowerShell é impossível (porque .NET Core, WMI, etc.), mas devemos tentar chegar o mais próximo possível.
  • Eu não sei sobre o progresso. Minha opinião de alto nível é que o progresso ainda deixa todo mundo louco porque é lento (apesar de nossas otimizações), mas também que não importa tanto no modo não interativo porque todo mundo está definindo $ProgressPreference qualquer maneira.

Parece bom para mim!

O progresso me irrita principalmente porque não pode ser tratado na chamada de comando; você deve definir $ ProgressPreference. Eu realmente gostaria que fosse um parâmetro comum ... Mas eu tenho outro problema reclamando sobre isso, então não vamos entrar nisso aqui! :sorriso:

@ PowerShell / powershell-Committee revisou isso. Concordamos que Test-Connection deve emular o comportamento do Windows PowerShell 5.1 o mais próximo possível (incluindo -Quiet ). Isso significa que um objeto de saída PingStatus (eliminando o win32_ ) deve ser emitido para cada resposta com as propriedades no formato padrão e quaisquer outras que estejam disponíveis. O progresso não deve ser usado.

Alguém estaria disposto a criar um RFC curto que mostre a sintaxe do cmdlet junto com o formato de saída proposto para revisão?

@stevel-msft eu ficaria feliz em. :)

Eu amo o som disso.
obrigado

É interessante que PR 3125 cobriu tudo isso, mas o uso de Test-Connection foi rejeitado, mas agora fechamos o círculo. Que tal olhar para 3125?

Olhando brevemente, parece que essencialmente substituiu Test-Connection por um comando implementado de forma diferente em plataformas Unix para tentar emular o comando do Windows. Eu estou lendo isso certo?

Não acho que essa seja a melhor opção disponível para nós; consistência em ambas as plataformas na implementação do comando como um todo é mais valiosa. Pode ter algumas ideias interessantes que podemos utilizar, tenho certeza!

Deixarei um link para o rascunho da RFC quando terminar de escrevê-lo e sinta-se à vontade para comentar, ajustar, etc ... Adoraria ouvir mais alguns pontos de vista sobre isso. 🙂

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

Meu caso de uso específico para solicitar isso foi baseado no desejo de usar PowerShell Core no Linux, mas a implementação foi totalmente testada em Windows e Linux. O objetivo era substituir o comando ausente por completo.

Quando veremos isso? Em 6.2.2? Quando isso provavelmente vai pousar?
(foi engraçado ver este tópico de discussão irado de abril de 2018 até agora sobre _-quiet_ sendo barulhento. Parece uma mudança tão óbvia)

Posso escrever esse código facilmente, acho, estou apenas esperando que o RFC seja aceito. Assim que isso acontecer, vou fazer isso e enviar um PR para isso. :sorriso:

Ah, achei que o status era de aprovado (sem saber exatamente quais estados existem ou qual é o processo completo). Mas obrigado pela atualização. Ainda assim, é uma pena que tenha demorado mais de 12 meses para ficar quieto :)

mais de 12 meses para ficar quieto

Eu esperava mais feedback

@ vexx32 você pode começar a codificar isso e colocá-lo atrás de um sinalizador Experimental no caso de

@ SteveL-MSFT Eu já tenho uma implementação praticamente funcionando. Vou enviar um PR com alguns sinalizadores Experimentais em breve para que possamos falar sobre o código de forma mais concreta. 💖

Depois de pensar nos últimos dias sobre o comportamento desejado, prefiro ter um comportamento interativo com um mínimo de parâmetros por padrão (digitação rápida e exibição amigável), o que seria conveniente em uma sessão interativa. E a conversão para o estilo de script com parâmetros adicionais (isso implica em diferentes tipos de saída).

Você poderia explicar um pouco mais como você acha que isso poderia funcionar @isazonov?

@ vexx32 Você pergunta sobre implementação ou design UX?

Principalmente como você acha que a experiência do usuário seria para isso, eu acho. :)

Na sessão interativa, o melhor UX é
1. digitação mínima
Isso significa:
- ping é o padrão
- mudar para outro modo (traceroute e etc.) com um parâmetro
2. saída amigável
Isso significa:
- emule a saída de ping.exe (tracert.exe e outros) _no host do console_ como tentei no código de demonstração - com cabeçalhos, rodapés e linhas informativas bem formatados. Não há necessidade de pensar sobre os tipos de saída - eles não são usados, apenas exibidos.
- adicionar parâmetros para alternar para o modo de script - isto é, suprimir a saída de texto amigável no host do console e emitir objetos fortemente tipados. Não há necessidade de formatar esta saída. Discutimos Quiet, que retorna True / False, mas precisamos de um ou mais parâmetros para emitir outros objetos de tipo forte bruto (como -RawOutput). É UX aceitável usar parâmetros adicionais em scripts.

Obrigado, acho que entendo um pouco melhor o que você está conseguindo agora.

Eu realmente não vejo a necessidade de um modo duplo como este, entretanto? Nenhum outro cmdlets no PowerShell tem essa divisão entre parâmetros interativos e "modo de script".

Se você quisesse a saída exata de ping / tracert, por que não usar esses utilitários diretamente?

O PowerShell nunca fez um esforço significativo para imitar completamente um comando existente; Acho que Get-ChildItem é provavelmente o mais próximo, mas é quase o único a fazer isso.

Se quiséssemos emular completamente a exibição de ping / tracert como você disse, sugeriria que, em vez disso, tivéssemos isso como um cmdlet ou função separada, por exemplo, Show-Connection , em vez de confundir Show-Command com parâmetros extras que não existem precedente ou necessidade dentro do PowerShell.

Eu realmente não vejo a necessidade de um modo duplo como este, entretanto? Nenhum outro cmdlets no PowerShell tem essa divisão entre parâmetros interativos e "modo de script".

Temos lacunas no nosso sistema de formatação. Por exemplo, temos um problema com a solicitação para ter um diretório de cabeçalho / rodapé. Existem outros cenários em que seria conveniente.

Se você quisesse a saída exata de ping / tracert, por que não usar esses utilitários diretamente?

Eu faço :-). Esses utilitários nativos são muito poderosos porque são de baixo nível, mas estão congelados. Podemos fazer coisas _mais inteligentes_ do que eles - esta é a essência da aparência deste cmdlet (e não apenas para fazer um ping) - se você der uma olhada em como os endereços e nomes no cmdlet estão agora formados e como eles são produzidos, você verá que há muito mais úteis do que no ping nativo. Parecem truques, mas são realmente muito úteis.

É claro que temos lacunas no sistema de formatação. Mas não acho que a resposta seja implementar uma solução customizada _ toda vez_. Isso apenas cria mais problemas e torna ainda mais difícil melhorar ou reescrever o sistema de formatação para ser mais eficaz em todas as áreas.

Sim, você fez um ótimo trabalho com ele! Eu agradeço muito isso. O modo de saída atual não é útil para nada _mas_ uso interativo. Poderíamos simplesmente remover a etapa de saída e chamá-la de Show-Connection e, em seguida, utilizar o que você escreveu em uma solução mais focada em PowerShell para o próprio Test-Connection conforme descrevo no RFC.

@ vexx32 Acabei de

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

No entanto, com a sua alteração, todas as respostas do ping são membros de um único 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…

Não conseguimos recuperar o comportamento do Windows PowerShell?

@ SteveL-MSFT Essa saída de objeto não mudou desde a implementação inicial no PS Core; a saída de sucesso sempre teve um único objeto. 🙂

Conforme mencionado nos comentários finais do PR, essa é apenas uma implementação parcial da RFC para ajudar a simplificar as revisões. Vou enviar um PR de acompanhamento em breve. Basta fazer o rebase desse branch para remover os commits agora duplicados e enviar o restante para ficar muito mais perto da verdadeira paridade com a implementação do Windows PowerShell. Ele ainda será um pouco diferente (como pode ser visto na RFC que analisamos algumas semanas atrás), mas será muito mais versátil. 😊

@ SteveL-MSFT veja # 10697 para o próximo capítulo desta aventura! 😊

: tada: Este problema foi resolvido em # 10478, que agora foi lançado com sucesso como v7.0.0-preview.5 .: tada:

Links úteis:

Na versão 7.0.0 Test-Connection -Quiet ainda oferece
Test-Connection: Falha no teste de conexão com o computador 'scrubbed': Não é possível resolver o nome do destino.
ao invés de
Falso

@chvol, você poderia abrir uma nova edição com o máximo de detalhes possível?

Obrigado! 🙂

Esta página foi útil?
0 / 5 - 0 avaliações