none
Wie binde ich mit Windowsforms eine Progressbar in meine Kopiervorgang ein? RRS feed

  • Frage

  • Hi,

    Ich habe ein Skript geschrieben mit dem eine oder mehrere Dateien in mehrere Ordner kopiert werden. Das funktioniert auch einwandfrei. Allerdings dauert es bei größeren Dateien oft etwas länger und ich wollte daher einen Ladebalken bzw. eine Progressbar mit einbinden. Irgendwie bekomme ich dies aber nicht so richtig zum laufen. Ich habe es mit dem Befehl write-progress versucht und da funktioniert es einwandfrei.

    foreach($global:Schueler in $Schuelers)
           {			
    
                   #Write-Progress -percentcomplete (($i/$Schuelers.count)*100)
                   #Start-Sleep -s 1
    					
    foreach($Element in $quelle)
    		{
    						
    Copy-Item -Path $Element -Destination $Schueler.FullName
    		
                     }
    	}
    

    wäre schön wenn mir jemand sagen könnte wie ich hier eine Progressbar (z.B. $prog) richtig einbinde :)

    Danke schon im vorraus :)

    Dienstag, 7. Juni 2016 13:52

Antworten

  • Moin,

    wenn du deine Oberfläche (egal ob Windows Forms oder WPF) während der Laufzeit aktualisieren möchtest (z.B. eine Progress Bar aktualisieren), dann betrittst du das Feld von Multithreading, Jobs, Runspaces, etc...

    Das gibt es sooo viele verschiedene Möglichkeiten.

    Eine sehr einfache Variante ist es dein aktuellen Prozess kurz für die UI Aktualisierung zu unterbrechen udn dann sofort weiterzurechnen:

    [System.Windows.Forms.Application]::DoEvents()

    Im kontext sieht das dann so aus:

    function Copy-Something
    {
        $anzahl = 1..50
        $window.progressBar.Maximum = $anzahl.count
        
        $anzahl | foreach {
            $window.textBlock.Text = "Datei $_ wird kopiert "
            $window.progressBar.Value = $_
            Start-Sleep -Milliseconds 200
            [System.Windows.Forms.Application]::DoEvents()
        }
    
        $window.textBlock.Text = '...fertig'
    }
    
    function Convert-XAMLtoWindow
    {
        param(
            [Parameter(Mandatory=$true)]
            [string]
            $XAML,
            [string[]]
            $NamedElements,
            [switch]$PassThru)
        Add-Type -AssemblyName PresentationFramework
        $reader = [System.XML.XMLReader]::Create([System.IO.StringReader]$XAML)
        $result = [System.Windows.Markup.XAMLReader]::Load($reader)
        foreach($Name in $NamedElements){$result | Add-Member NoteProperty -Name $Name -Value $result.FindName($Name) -Force}
        if ($PassThru){$result}
        else{$result.ShowDialog()}
    }
    
    $xaml = @'
    <Window
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Height="200"
       Width="525"
       SizeToContent="WidthAndHeight"
       Title="PowerShell WPF Window"
       Topmost="True">
        <Grid>
            <TextBlock Name="textBlock" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top"/>
            <ProgressBar Name="progressBar" HorizontalAlignment="Left" Height="36" Margin="10,77,10,10" VerticalAlignment="Top" Width="492" Minimum="1" Maximum="100" />
            <Button Name="button" Content="start" HorizontalAlignment="Left" Margin="427,10,0,0" VerticalAlignment="Top" Width="75"/>
        </Grid>
    </Window>
    '@
    
    $window = Convert-XAMLtoWindow -XAML $xaml -NamedElements 'textBlock', 'progressBar', 'button' -PassThru
    
    $window.button.add_Click(
        {
            [System.Object]$sender = $args[0]
            [System.Windows.RoutedEventArgs]$e = $args[1]   
            Copy-Something
        }
    )
    
    $window.showdialog()
    

    Hier als Windows Forms Variante

    Gruß,

    Dienstag, 7. Juni 2016 15:47

Alle Antworten

  • > Ich habe es mit dem Befehl write-progress versucht und da funktioniert
    > es einwandfrei.
     
    Ich verstehe die Frage nicht... Wenn es mit Write-Progress funktioniert,
    was genau möchtest Du jetzt erreichen? Wozu Forms, wenn es doch mit PoSh
    nativ geht?
     
    Dienstag, 7. Juni 2016 14:45
  • Oder willst Du für die Foreach-Schleife unten eine zweite Progressbar?
    Dann schau Dir mal -id und -parentid an :)
     
    Dienstag, 7. Juni 2016 14:49
  • Moin,

    wenn du deine Oberfläche (egal ob Windows Forms oder WPF) während der Laufzeit aktualisieren möchtest (z.B. eine Progress Bar aktualisieren), dann betrittst du das Feld von Multithreading, Jobs, Runspaces, etc...

    Das gibt es sooo viele verschiedene Möglichkeiten.

    Eine sehr einfache Variante ist es dein aktuellen Prozess kurz für die UI Aktualisierung zu unterbrechen udn dann sofort weiterzurechnen:

    [System.Windows.Forms.Application]::DoEvents()

    Im kontext sieht das dann so aus:

    function Copy-Something
    {
        $anzahl = 1..50
        $window.progressBar.Maximum = $anzahl.count
        
        $anzahl | foreach {
            $window.textBlock.Text = "Datei $_ wird kopiert "
            $window.progressBar.Value = $_
            Start-Sleep -Milliseconds 200
            [System.Windows.Forms.Application]::DoEvents()
        }
    
        $window.textBlock.Text = '...fertig'
    }
    
    function Convert-XAMLtoWindow
    {
        param(
            [Parameter(Mandatory=$true)]
            [string]
            $XAML,
            [string[]]
            $NamedElements,
            [switch]$PassThru)
        Add-Type -AssemblyName PresentationFramework
        $reader = [System.XML.XMLReader]::Create([System.IO.StringReader]$XAML)
        $result = [System.Windows.Markup.XAMLReader]::Load($reader)
        foreach($Name in $NamedElements){$result | Add-Member NoteProperty -Name $Name -Value $result.FindName($Name) -Force}
        if ($PassThru){$result}
        else{$result.ShowDialog()}
    }
    
    $xaml = @'
    <Window
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Height="200"
       Width="525"
       SizeToContent="WidthAndHeight"
       Title="PowerShell WPF Window"
       Topmost="True">
        <Grid>
            <TextBlock Name="textBlock" HorizontalAlignment="Left" Margin="10,10,0,0" TextWrapping="Wrap" Text="" VerticalAlignment="Top"/>
            <ProgressBar Name="progressBar" HorizontalAlignment="Left" Height="36" Margin="10,77,10,10" VerticalAlignment="Top" Width="492" Minimum="1" Maximum="100" />
            <Button Name="button" Content="start" HorizontalAlignment="Left" Margin="427,10,0,0" VerticalAlignment="Top" Width="75"/>
        </Grid>
    </Window>
    '@
    
    $window = Convert-XAMLtoWindow -XAML $xaml -NamedElements 'textBlock', 'progressBar', 'button' -PassThru
    
    $window.button.add_Click(
        {
            [System.Object]$sender = $args[0]
            [System.Windows.RoutedEventArgs]$e = $args[1]   
            Copy-Something
        }
    )
    
    $window.showdialog()
    

    Hier als Windows Forms Variante

    Gruß,

    Dienstag, 7. Juni 2016 15:47