Вывод графического интерфейса PowerShell

Я пишу небольшой скрипт PowerShell с графическим интерфейсом, который обрабатывает команду Ping. В настоящее время у меня есть скрипт, читающий ввод от пользователя, чтобы определить IP-адрес/URL-адрес для ping, а затем отображать вывод в поле с расширенным текстом.

Однако в настоящее время команда COMPLETES записывает сразу весь вывод. Я хочу, чтобы он отображал каждую строку вывода в реальном времени, чтобы она выглядела так же, как если бы она выполняла команду в оболочке.

Когда нажимается кнопка Ping, вызывается следующая функция (и я думаю, что проблема именно в этом):

Function FNPing {
    $OutputBox.Text = "Please Wait..."
    $ping = ping ($InputBox.text)
    $OutputBox.Text = ""
    foreach ($line in $ping) {
        $OutputBox.Appendtext($line+[char]13+[char]10)
    }
}

Я предполагаю, что проблема, вероятно, может быть решена в операторе ForEach, я просто не знаю, как это сделать! Любая помощь приветствуется!


person Chad    schedule 20.09.2013    source источник


Ответы (2)


Я бы попробовал использовать командлет test-connection. Проблема в том, что пингуется внешний исполняемый файл, поэтому все, что вы получаете от него, - это текстовый блок, когда он завершается. Единственный способ получить вывод ping во время его работы — это использовать start-process и перенаправить вывод (это довольно грязно).

С test-connection вы не получите красивого резюме, но вся информация есть. Для сводной информации measure-object может помочь. Вот имитация вывода ping, которая должна помочь вам начать:

function fnping {
    $outputBox.Text = "Please Wait..."
    $count = 4
    $results = test-connection $inputbox.Text -count $count | foreach { $outputBox.AppendText("Reply from $($_.ProtocolAddress): bytes=$($_.ReplySize) time=$($_.ResponseTime)ms TTL=$($_.TimeToLive)`r`n"); $_ }
    $summary = $results | measure-object -Property ResponseTime -Average -Minimum -Maximum
    $lost = $count - $summary.Count
    $percentLost = $lost * 100.0 / $count
    $outputBox.AppendText("Packets: Sent = $count, Received = $($summary.Count), Lost = $lost ($($percentLost)% loss)`r`n")
    $outputBox.AppendText("Minimum = $($summary.Minimum)ms, Maximum = $($summary.Maximum)ms, Average = $($summary.Average)ms`r`n")
}

Изменить

На самом деле я исправляюсь. Присвоение результата переменной ($ping) заставляет powershell ждать закрытия выходного потока. Вы можете легко делать то, что хотите, с foreach-object. Здесь я использую небольшую вспомогательную функцию, чтобы очистить поле вывода перед записью в поле:

function WriteEach-Object() { 
    param(
      [Parameter(Mandatory=$true,ValueFromPipeline=$true)]
      [object[]]$inputs
    )  

    begin { $outputBox.Text = "" } 
    process { $inputs | foreach { $outputBox.AppendText($_) } } 
    end { $outputBox.AppendText("`r`n") } 
}

function fnping() {
    $outputBox.Text = "Please Wait..."
    ping $inputBox.Text | writeeach-object
}
person Mike Zboray    schedule 20.09.2013

Вам нужно добавить операторы BEGIN {} PROCESS {} и END {}, чтобы управлять работой вашей функции. Если таковые не указаны, Powershell предполагает, что все находится в инструкции END {}, обрабатывая все за один раз.

Превращение в это

Function FNPing {
  BEGIN {
  }

  PROCESS {
     $OutputBox.Text = "Please Wait..."
     $ping = ping ($InputBox.text)
     $OutputBox.Text = ""
     foreach ($line in $ping) {
         $OutputBox.Appendtext($line+[char]13+[char]10)
     }
  }

  END {
  }
}

должен сделать трюк. В качестве альтернативы вы можете заменить Function на Filter, что предполагает, что код находится в блоке PROCESS {}.

Дополнительные сведения: http://technet.microsoft.com/en-us/magazine/hh413265.aspx

person Torbjörn Bergstedt    schedule 20.09.2013