В PowerShell Form.Show() работает неправильно, но Form.ShowDialog() делает
Я пытаюсь отобразить изображение через powershell. Я сделал script на основе этот пост форума.
Если я использую ShowDialog(), он отлично работает, за исключением того, что выполнение powershell прекращается во время разговора. Тем не менее, это дизайн для модального диалога. Если я вызываю Form.Show() в PowershellISE, форма появляется, но зависает и не может быть перемещена или удалена. Поведение аналогично, если я копирую и прохожу код в консоль powershell.
Как сделать диалог немодальным, а не заморозить.
Ответы
Ответ 1
Первый ответ Почему он добавляет.
В графической программе 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 http://stackoverflow.com/questions/3358372/windows-forms-look-different-in-powershell-and-powershell-ise-why/3359274#3359274
[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"
Ответ 2
Есть способы сделать эту работу, но ничто не стоит тратить пять часов на объяснение на открытом форуме. Есть и другие бесплатные, с термоусадочными способами сделать это на PowerShell. В первую очередь со свободным набором инструментов PowerWoot WPF: Show-UI на http://showui.codeplex.com/ (ранее известный как WPK и/или PowerBoots - они теперь объединены. )
Ответ 3
Если ваша цель состоит в том, чтобы не блокировать интерактивную консоль при показе изображения, вы все равно можете использовать script, как и в случае с ShowDialog
, но вы должны запустить его, используя, например, Start-Job
. Таким образом, диалог по-прежнему модальный, но он блокирует выполнение в другой области. Основное рабочее пространство все еще может использоваться для вызова других команд.
Предостережения: 1) Перед закрытием интерактивной консоли необходимо закрыть все открытые диалоги. 2) Если вам все равно, вы должны сами удалить выполненные задания (когда диалог закрыт заданием, которое его начало все еще существует).
Я использую подобный подход в своем пользовательском хосте, и он отлично работает. Я также проверил его с помощью script по вашей ссылке. Я немного изменил его так, что он называется 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