我试图通过powershell显示图像。我根据script制作了this forum post。
如果我使用ShowDialog()它可以正常工作,除了在对话框启动时powershell执行停止。但是,这是设计用于模态对话框。如果我在PowershellISE中调用Form.Show(),表单会显示,但会冻结,无法移动或解除。如果我将代码复制并传递给PowerShell控制台,则行为类似。
如何使对话非模态,而不是冻结。
答案 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()