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



我正在尝试通过Powershell显示图像。我根据这个论坛帖子制作了一个脚本。

如果我使用 ShowDialog(),它可以正常工作,除了 powershell 执行在对话框启动时停止。但是,这是模式对话的设计使然。如果我在PowershellISE中调用Form.Show(),表单会显示,但会冻结并且无法移动或关闭。如果我将代码复制并粘贴到 Powershell 控制台,则行为类似。

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

第一个答案 为什么它附加。

在 Windows 图形程序中,创建窗口的线程必须在消息泵中循环,以便将来自用户操作的消息重新分发(翻译)到他的 Windows 中的事件。

在模式窗口中,处理窗口显示的模式代码运行自己的消息泵循环,并且在窗口关闭之前不会返回。 这就是为什么ShowDialog()之后的代码在窗口关闭之前不会执行。

Show(),只需要求显示窗口,但是如果没有泵循环来管理来自用户操作的消息,它只会冻结。

第二种拥有两个线程的简单方法

CmdLet 启动作业使用 Powershell 分配的池中的另一个线程,因此它使对话框非模式,并且不会冻结。

function goForm
{
  [void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
  $file = (get-item 'C:tempjpb.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"

有很多方法可以做到这一点,但没有什么值得花五个小时在公开论坛上解释的。还有其他免费的、收缩包装的方法可以在 powershell 上做到这一点。最值得注意的是免费的WPF powershell工具包:Show-UI at http://showui.codeplex.com/(以前称为WPK和/或PowerBoots - 它们现在已合并。

如果您

的目标实际上是在显示图像时不阻止交互式控制台,那么您仍然可以像使用ShowDialog一样使用该脚本,但您应该使用例如Start-Job .因此,对话框仍然是模式的,但它会阻止在另一个运行空间中执行。主运行空间仍可用于调用其他命令。

注意事项:1) 在关闭交互式控制台之前,您应该关闭所有打开的对话框。2)如果你关心,你应该自己删除已完成的作业(当对话框关闭时,启动它的作业仍然存在)。

我在自定义主机中使用了类似的方法,它工作正常。我还使用您链接中的脚本对其进行了测试。我稍微更改了它,以便它被称为show-image.ps1并接受文件路径作为参数。

此命令显示映像并阻止调用运行空间:

show-image.ps1 C:TEMP_110513_055058test.png

此命令显示映像,并且不会阻止调用运行空间:

Start-Job { show-image.ps1 $args[0] } -ArgumentList C:TEMP_110513_055058test.png

建立在@JPBlanc的 anwer 之上,使用运行空间也可以(并且更快)。

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

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

最新更新