我正在尝试通过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()