在PowerShell中Form.Show()不能正常工作,但Form.ShowDialog()可以

时间:2011-05-13 02:31:34

标签: winforms powershell modal-dialog

我试图通过powershell显示图像。我根据script制作了this forum post

如果我使用ShowDialog()它可以正常工作,除了在对话框启动时powershell执行停止。但是,这是设计用于模态对话框。如果我在PowershellISE中调用Form.Show(),表单会显示,但会冻结,无法移动或解除。如果我将代码复制并传递给PowerShell控制台,则行为类似。

如何使对话非模态,而不是冻结。

4 个答案:

答案 0 :(得分:19)

第一个答案为何附加。

在Windows图形程序中,创建Window的线程必须在消息泵中循环,以便将来自用户操作的消息重新分发(转换)到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"

答案 1 :(得分:4)

有很多方法可以完成这项工作,但没有什么值得在开放的论坛上花费五个小时来解释。还有其他免费的,收缩包装的方法在powershell上执行此操作。最值得注意的是免费的WPF powershell工具包:http://showui.codeplex.com/的Show-UI(以前称为WPK和/或PowerBoots - 它们现在已合并。)

答案 2 :(得分:3)

如果你的目标实际上是在显示图像时没有阻止交互式控制台,那么你仍然可以像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

答案 3 :(得分:0)

基于@JPBlanc的anwer,使用运行空间也可以(而且更快)实现这一点。

这是一个基本示例(其余基本保持不变)

$ps = [PowerShell]::Create()
[void]$ps.AddScript({
  Add-Type -AssemblyName System.Windows.Forms
  $form = [Windows.Forms.Form]::new()
  $form.ShowDialog()
})
[void]$ps.BeginInvoke()