2011-05-13 25 views
13

Estoy intentando mostrar una imagen mediante powershell. Hice un script basado en this forum post.En PowerShell Form.Show() no funciona bien, pero Form.ShowDialog() hace

Si uso ShowDialog() funciona bien, excepto que la ejecución de powershell se detiene mientras el cuadro de diálogo está activo. Sin embargo, eso es por diseño para un diálogo modal. Si llamo al Form.Show() en PowershellISE, el formulario aparece, pero se congela y no se puede mover ni descartar. El comportamiento es similar si copio y paso el código a una consola de powershell.

Cómo hago que el diálogo no sea modal y no se congele.

+3

Show() podría no ser una buena idea : http: // stackoverflow.com/questions/2192558/why-do-a-form-displayed-by-powershell-sometimes-not-show-up – keyboardP

+0

Esa es una buena referencia. –

Respuesta

18

Primera respuesta Por qué se agrega.

En un programa gráfico de Windows, el hilo que crea una ventana debe crear un bucle en una bomba de mensajes para redistribuir (traducir) mensajes provenientes de la acción del usuario a eventos en su Windows.

En una ventana modal, el código modal que maneja la visualización de la ventana ejecuta su propio bucle de bomba de mensajes y no regresa hasta que se cierra la ventana. Es por eso que el código después de ShowDialog() no se ejecutará hasta que se cierre la ventana.

Show(), solo solicite mostrar la ventana, pero si no hay ningún bucle de bomba para administrar los mensajes provenientes de la acción del usuario, simplemente se congela.

Segundo una forma sencilla de tener dos hilos

el cmdlet Start-Job utilizar otro hilo de la piscina asignado por Powershell lo que hace que el diálogo no modal, y no se congela.

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" 
+0

Si hace esta clase de pregunta, ¿de verdad crees que le da una salchicha a las bombas de mensajes? – x0n

+5

Ok, para ti, el conocimiento es una salchicha, y es mejor mantener a la gente ignorante ... tú eres el arquitecto ... – JPBlanc

+5

x0n ¿Qué tal "ese tipo de pregunta" te hace pensar que no me importa cómo es la salchicha? ¿hecho? Sí, al final necesito GTD, por lo que a corto plazo necesito start-job o show-ui. Sin embargo, entender el "por qué" me ayuda a evaluar qué está pasando aquí. –

4

Hay formas de hacer que esto funcione, pero nada vale la pena pasar cinco horas explicando en un foro abierto. Hay otras formas gratuitas y envueltas para hacer esto en PowerShell. Más notablemente con el kit de herramientas WPF powershell gratuito: Show-UI en http://showui.codeplex.com/ (anteriormente conocido como WPK y/o PowerBoots - se fusionan ahora.)

+7

explicación de 5 minutos como la de @JPBlanc también es digna;) ¿Por qué? También es para otras personas que vienen y tratan de descubrir qué está pasando. Y además de eso, puede llevar a Justin aún más lejos, porque podría ser curioso de lo que se trata todo sobre el bombeo de mensajes. +1 para los dos ... – stej

2

Si su objetivo es en realidad no bloquear la consola interactiva cuando se muestra una imagen entonces aún puede usar la secuencia de comandos tal como está con ShowDialog pero debe iniciarla usando, por ejemplo, Start-Job. Por lo tanto, el diálogo sigue siendo modal pero bloquea la ejecución en otro espacio de ejecución. El espacio de ejecución principal aún se puede usar para invocar otros comandos.

Advertencias: 1) Debe cerrar todos los cuadros de diálogo abiertos antes de cerrar la consola interactiva. 2) Si le importa, debe eliminar los trabajos completos usted mismo (cuando se cierra un diálogo, un trabajo que comenzó todavía existe).

Uso un enfoque similar en mi host personalizado y funciona bien. También lo probé con la secuencia de comandos de su enlace. Lo cambié ligeramente para que se llame show-image.ps1 y acepte una ruta de archivo como parámetro.

Este comando muestra una imagen y para el espacio de ejecución de llamadas:

show-image.ps1 C:\TEMP\_110513_055058\test.png 

Este comando muestra una imagen y no bloquee el espacio de ejecución de llamadas:

Start-Job { show-image.ps1 $args[0] } -ArgumentList C:\TEMP\_110513_055058\test.png 
+0

Según comenta, me acabo de dar cuenta de que detener el trabajo o eliminar el trabajo parece depender de trabajos con este rey de la función. ¿Experimenta lo mismo? – JPBlanc

+0

'Stop-Job' termina solo cuando se cierra un cuadro de diálogo. 'Remove-Job' funciona bien después de cerrar un cuadro de diálogo y falla" no se puede eliminar el trabajo ... porque el trabajo no está terminado "si aún se abre un cuadro de diálogo. –

+0

'Remove-Job -Force' funciona pero también" espera "la salida del diálogo. –

Cuestiones relacionadas