Descartar un formulario de PowerShell controlado por una tarea de inicio
-
12-11-2019 - |
Pregunta
Me han encargado de construir un script de PowerShell con una GUI que permite a los usuarios instalar impresoras de red.También he logrado hacerlo, pero no puedo cumplir con el requisito de que el usuario se le muestre una ventana "Por favor, espere", mientras que las impresoras se instalan.Si cambia a la ventana del hilo principal, la GUI cuelga.Si me muevo mostrando la ventana a un trabajo separado, nunca más puedo cerrar la ventana.Aquí está mi intento:
$waitForm = New-Object 'System.Windows.Forms.Form'
$CloseButton_Click={
# open "please wait form"
Start-Job -Name waitJob -ScriptBlock $callWork -ArgumentList $waitForm
#perform long-running (duration unknown) task of adding several network printers here
$max = 5
foreach ($i in $(1..$max)){
sleep 1 # lock up the thread for a second at a time
}
# close the wait form - doesn't work. neither does remove-job
$waitForm.Close()
Remove-Job -Name waitJob -Force
}
$callWork ={
param $waitForm
[void][reflection.assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
$waitForm = New-Object 'System.Windows.Forms.Form'
$labelInstallingPrintersPl = New-Object 'System.Windows.Forms.Label'
$waitForm.Controls.Add($labelInstallingPrintersPl)
$waitForm.ClientSize = '502, 103'
$labelInstallingPrintersPl.Location = '25, 28'
$labelInstallingPrintersPl.Text = "Installing printers - please wait..."
$waitForm.ShowDialog($this)
}
¿Alguien sabe cómo puedo descartar la ventana de $ Waitform cuando la tarea de larga duración ha concluido?
Solución
Podría intentar ejecutar el cuadro de diálogo Formularios de Windows en el hilo principal y hacer el trabajo real en un trabajo de fondo:
Add-Type -Assembly System.Windows.Forms
$waitForm = New-Object 'System.Windows.Forms.Form'
$labelInstallingPrintersPl = New-Object 'System.Windows.Forms.Label'
$waitForm.Controls.Add($labelInstallingPrintersPl)
$waitForm.ClientSize = '502, 103'
$labelInstallingPrintersPl.Location = '25, 28'
$labelInstallingPrintersPl.Text = "Installing printers - please wait..."
$waitForm.ShowDialog($this)
Start-Job -ScriptBlock $addPrinters | Wait-Job
$waitForm.Close()
$addPrinters = {
$max = 5
foreach ($i in $(1..$max)) {
sleep 1 # lock up the thread for a second at a time
}
}
Otros consejos
Esta primera respuesta fue correcta, cree el formulario en el hilo principal y realice la tarea de ejecución larga en un hilo separado.La razón por la que no ejecuta el código principal hasta que se desestime el formulario es porque está utilizando el método 'ShowDialog' del formulario, este método ha surgido la ejecución posterior del código hasta que el formulario está cerrado.
Utilice el método 'Mostrar', la ejecución del código continuará, probablemente debería incluir algunos manipuladores de eventos para deshacerse del formulario
Add-Type -Assembly System.Windows.Forms
$waitForm = New-Object 'System.Windows.Forms.Form'
$labelInstallingPrintersPl = New-Object 'System.Windows.Forms.Label'
$waitForm.Controls.Add($labelInstallingPrintersPl)
$waitForm.ClientSize = '502, 103'
$labelInstallingPrintersPl.Location = '25, 28'
$labelInstallingPrintersPl.Text = "Installing printers - please wait..."
$waitForm.Add_FormClosed({
$labelInstallingPrintersPl.Dispose()
$waitForm.Dispose()
})
$waitForm.Show($this)
Start-Job -ScriptBlock $addPrinters | Wait-Job
$waitForm.Close()
$addPrinters = {
$max = 5
foreach ($i in $(1..$max)) {
sleep 1 # lock up the thread for a second at a time
}
}