В PowerShell Form.Show () не работает правильно, но Form.ShowDialog () работает - PullRequest
13 голосов
/ 13 мая 2011

Я пытаюсь отобразить изображение с помощью powershell.Я сделал скрипт на основе этого сообщения на форуме .

Если я использую ShowDialog () , он работает нормально, за исключением того, что выполнение powershell останавливается, покадиалог вверх.Тем не менее, это дизайн модального диалога.Если я звоню Form.Show () в PowershellISE, форма появляется, но зависает и не может быть перемещена или отклонена.Поведение аналогично, если я копирую и вставляю код в консоль PowerShell.

Как сделать диалоговое окно немодальным и не зависать.

Ответы [ 3 ]

19 голосов
/ 13 мая 2011

Первый ответ Почему он добавляется.

В графической программе Windows поток, создающий окно, должен зацикливаться в насосе сообщений, чтобы перераспределять (переводить) сообщения, приходящие от пользователя.действие для событий в его Windows.

В модальном окне модальный код, который обрабатывает отображение окна, запускает свой собственный цикл обработки сообщений и не возвращается, пока окно не будет закрыто.Вот почему код после ShowDialog() не будет выполняться до тех пор, пока окно не будет закрыто.

Show(), просто попросите показать окно, но если нет цикла насоса для управления сообщениями, поступающими от действий пользователя, он просто зависает.

Второй простой способ иметь два потока

При запуске задания CmdLet используется другой поток из пула, выделенного Powershell, поэтому он создает диалогнемодальный, и он не замерзает.

function goForm
{
  [void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")

  $file = (get-item 'C:\temp\jpb.png')
  #$file = (get-item "c:\image.jpg")

  $img = [System.Drawing.Image]::Fromfile($file);

  # This tip from /3333425/formy-windows-vyglyadyat-po-raznomu-v-powershell-i-powershell-ise-zachem#3333431
  [System.Windows.Forms.Application]::EnableVisualStyles();
  $form = new-object Windows.Forms.Form
  $form.Text = "Image Viewer"
  $form.Width = $img.Size.Width;
  $form.Height =  $img.Size.Height;
  $pictureBox = new-object Windows.Forms.PictureBox
  $pictureBox.Width =  $img.Size.Width;
  $pictureBox.Height =  $img.Size.Height;

  $pictureBox.Image = $img;
  $form.controls.add($pictureBox)
  $form.Add_Shown( { $form.Activate() } )
  $form.ShowDialog()
}

Clear-Host

start-job $function:goForm

$name = Read-Host "What is you name"
Write-Host "your name is $name"
4 голосов
/ 13 мая 2011

Есть способы заставить это работать, но ничего не стоит тратить пять часов на объяснение на открытом форуме. Существуют и другие бесплатные способы упаковки в PowerShell. В частности, с помощью бесплатного набора инструментов WPF powershell: Show-UI на http://showui.codeplex.com/ (ранее известный как WPK и / или PowerBoots - теперь они объединены).

3 голосов
/ 13 мая 2011

Если ваша цель на самом деле не блокировать интерактивную консоль при отображении изображения, тогда вы все равно можете использовать сценарий, как он есть с ShowDialog, но вы должны запустить его, например, Start-Job. Таким образом, диалог все еще является модальным, но он блокирует выполнение в другом пространстве выполнения. Основное пространство выполнения по-прежнему может использоваться для вызова других команд.

Предостережения: 1) Вы должны закрыть все открытые диалоговые окна перед закрытием интерактивной консоли. 2) Если вам не безразлично, вы должны удалить завершенные задания самостоятельно (когда диалоговое окно закрыто, задание, которое было запущено, все еще существует).

Я использую аналогичный подход в моем собственном хосте, и он отлично работает. Я также проверил это скриптом по вашей ссылке Я немного изменил его, так что он называется show-image.ps1 и принимает путь к файлу в качестве параметра.

Эта команда показывает изображение и блокирует пространство выполнения вызова:

show-image.ps1 C:\TEMP\_110513_055058\test.png

Эта команда показывает изображение и не блокирует пространство выполнения вызова:

Start-Job { show-image.ps1 $args[0] } -ArgumentList C:\TEMP\_110513_055058\test.png
...