Pergunta

Recebi a tarefa de criar um script do PowerShell com uma GUI que permite aos usuários instalar impressoras de rede.Consegui fazer isso com sucesso, mas não consigo atender ao requisito de que o usuário veja uma janela 'aguarde' enquanto as impressoras são instaladas.Se eu mudar para a janela do thread principal, a GUI trava.Se eu mudar a exibição da janela para um trabalho separado, nunca mais poderei fechar a janela.Aqui está minha tentativa:

$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)
} 

Alguém sabe como posso descartar a janela $waitForm quando a tarefa de longa duração for concluída?

Foi útil?

Solução

Você poderia tentar executar a caixa de diálogo Windows Forms no thread principal e fazer o trabalho real em um trabalho em segundo plano:

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
    }
}

Outras dicas

Esta primeira resposta estava correta, crie o formulário no thread principal e execute a tarefa de longa duração em um thread separado.A razão pela qual ele não executa o código principal até que o formulário seja descartado é porque você está usando o método 'ShowDialog' do formulário, esse método interrompe a execução do código subsequente até que o formulário seja fechado.

Em vez disso, use o método 'show', a execução do código continuará, você provavelmente deverá incluir alguns manipuladores de eventos para descartar o formulário

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
    }
}

Que tal adicionar um Windows.Forms.Progressbar para a janela principal da GUI?Atualize seu valor passo a passo ao adicionar impressoras, para que os usuários vejam que o aplicativo está funcionando.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top