Question

J'ai été chargé de construire un script PowerShell avec une interface graphique qui permet aux utilisateurs d'installer des imprimantes réseau. J'ai réussi à le faire, mais je ne peux pas répondre à l'exigence selon laquelle l'utilisateur est affiché une fenêtre «s'il vous plaît patinez» pendant que les imprimantes installent. Si je passe à la fenêtre à partir du fil principal, l'interface graphique est suspendue. Si je bouge en montrant la fenêtre à un travail séparé, je ne suis plus en mesure de fermer la fenêtre. Voici ma tentative:

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

Est-ce que quelqu'un sait comment je peux rejeter la fenêtre $ Wattform lorsque la tâche de longue durée s'est terminée?

Était-ce utile?

La solution

Vous pouvez essayer d'exécuter la boîte de dialogue Windows Forms sur le thread principal et effectuer le travail réel en arrière-plan:

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

Autres conseils

Cette première réponse était correcte, créez le formulaire sur le thread principal et effectuez la longue tâche en cours d'exécution sur un thread séparé. La raison pour laquelle il n'exécute pas le code principal avant que le formulaire ne soit rejeté parce que vous utilisez la méthode «showDialog» du formulaire, cette méthode augmente l'exécution de code ultérieure jusqu'à ce que le formulaire soit fermé.

Au lieu de cela, utilisez la méthode «Show», l'exécution de code se poursuivra, vous devriez probablement inclure certains gestionnaires d'événements pour éliminer le formulaire

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 diriez-vous d'ajouter un Windows.forms.progressbar à la fenêtre GUI principale? Mettez à jour sa valeur étape par étape lors de l'ajout d'imprimantes, les utilisateurs verront donc que l'application fonctionne.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top