bugger
Goto Top

Powershell Multiple Select Box und Dateien kopieren

Hallo zusammen,

ich möchte gerne über eine Box mehrere Server auswählen und auf diesen sollen dann Dateien kopiert werden. Folgendes Script funktioniert super, allerdings nur, wenn ich nur einen Server auswähle. Was muss ich tun, damit die Werte aus $Script:x einzeln abgearbeitet werden? Danke im Voraus!

 
$Script:x = @()

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")  
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")   

$objForm = New-Object System.Windows.Forms.Form 
$objForm.Text = "Data Entry Form"  
$objForm.Size = New-Object System.Drawing.Size(300,200) 
$objForm.StartPosition = "CenterScreen"  

$objForm.KeyPreview = $True

$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")   
    {
        foreach ($objItem in $objListbox.SelectedItems)
            {$x += $objItem}
        $objForm.Close()
    }
    })

$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")   
    {$objForm.Close()}})

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,120)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"  

$OKButton.Add_Click(
   {
        foreach ($objItem in $objListbox.SelectedItems)
            {$Script:x += $objItem}
        $objForm.Close()
   })

$objForm.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,120)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"  
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)

$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20) 
$objLabel.Size = New-Object System.Drawing.Size(280,20) 
$objLabel.Text = "Please make a selection from the list below:"  
$objForm.Controls.Add($objLabel) 

$objListbox = New-Object System.Windows.Forms.Listbox 
$objListbox.Location = New-Object System.Drawing.Size(10,40) 
$objListbox.Size = New-Object System.Drawing.Size(260,20) 

$objListbox.SelectionMode = "MultiExtended"  

[void] $objListbox.Items.Add("Server1")  
[void] $objListbox.Items.Add("Server2")  
[void] $objListbox.Items.Add("Server3")  
[void] $objListbox.Items.Add("Server4")  
[void] $objListbox.Items.Add("Server5")  

$objListbox.Height = 70
$objForm.Controls.Add($objListbox) 
$objForm.Topmost = $True

$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

copy -Recurse \\Pfad\Dateien\ \\$Script:x\c$\Ziel\

Write-Host "Fertig"  

$y = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")  

Content-ID: 251561

Url: https://administrator.de/contentid/251561

Ausgedruckt am: 04.12.2024 um 08:12 Uhr

colinardo
Lösung colinardo 10.10.2014 aktualisiert um 18:58:17 Uhr
Goto Top
Hallo Bugger,
da du ein Array aus deiner Listbox-Auswahl erstellst, musst du natürlich über alle Elemente mit einer foreach-Schleife (%{} = Abkürzung für Foreach-Object) iterieren (Zeile 71 folgendermaßen ändern):
$script:x | %{copy -Recurse '\\Pfad\Dateien\' "\\$_\c$\Ziel\"}
$_ ist dabei immer die aktuelle Schleifenvariable.

Noch zur Info: Du musst nur aufpassen wenn du Dollarzeichen innerhalb von doppelten Anführungszeichen verwendest. In diesem Fall geht das c$ in Ordnung weil ihm direkt dahinter ein Backslash folgt, wenn aber direkt ein Buchstabe oder Zahl folgt musst du das Dollarzeichen mit Voranstellen eines Backticks (`) escapen, da es sonst als Variable interpretiert wird.

Grüße Uwe

p.s. Bitte nutze Code-Tags für deinen Quellcode: <code> Quellcode </code>. Merci. Kannst du auch nachträglich korrigieren.
Bugger
Bugger 10.10.2014 aktualisiert um 14:16:06 Uhr
Goto Top
Super, genau das habe ich gesucht. Funktioniert einwandfrei. Vielen Dank!

Die eigentlich Frage ist zwar gelöst aber ich hätte noch mehr. Wie kann ich denn $_ für weitere Befehle verwenden? So wie unten funktioniert es jedenfalls nicht.^^

function Test-Process{
param(
[string]$procid
)
  (get-wmiobject Win32_Process ProcessId -filter "ProcessId=$procid" -ComputerName $_) -ne $NULL  
}

$process = ([WMICLASS]“\\$_\ROOT\CIMV2:win32_process”).Create(“c:\\setup.exe /sAll /rs")  

[string]$ID = $process.ProcessID
Write-Output "Waiting for process $ID to finish on $_"  
while (test-process $process.ProcessId $_) { }  # Wait for terminate
colinardo
colinardo 10.10.2014 aktualisiert um 19:42:53 Uhr
Goto Top
Zitat von @Bugger:
Die eigentlich Frage ist zwar gelöst aber ich hätte noch mehr. Wie kann ich denn $_ für weitere Befehle verwenden?
So wie unten funktioniert es jedenfalls nicht.^^
sory, habe ich leider nicht rechtzeitig gesehen, das du noch was nachgetragen hast ...das nächste mal in ein neues Kommentar packen damit ich das mitbekomme ...

Du musst das ganze natürlich in das Foreach-Object kapseln.
function Test-Process{
param(
[string]$procid,
[string]$computer
)
  (get-wmiobject Win32_Process ProcessId -filter "ProcessId=$procid" -ComputerName $computer) -ne $NULL  
}

$script:x | %{
    copy -Recurse '\\Pfad\Dateien\' "\\$_\c$\Ziel\"  
    $process = ([WMICLASS]“\\$_\ROOT\CIMV2:win32_process”).Create(“c:\\setup.exe /sAll /rs")  
    [string]$ID = $process.ProcessID
    Write-Output "Waiting for process $ID to finish on $_"  
    while (Test-Process $process.ProcessId $_) { sleep -Milliseconds 200 }  # Wait for terminate
}
das lässt sich aber natürlich auch ausführlich mit einer normalen foreach() schreiben, wobei du dann anstatt $_ die Variable $server nutzt. Aber aber das kennst du ja deinem Script oben zu urteilen face-smile
foreach ($server in $script:x){
    copy -Recurse '\\Pfad\Dateien\' "\\$server\c$\Ziel\"  
    $process = ([WMICLASS]“\\$server\ROOT\CIMV2:win32_process”).Create(“c:\\setup.exe /sAll /rs")  
    [string]$ID = $process.ProcessID
    Write-Output "Waiting for process $ID to finish on $server"  
    while (Test-Process $process.ProcessId $server) { sleep -Milliseconds 200 }  # Wait for terminate
}
das kannst du selber entscheiden was du nutzen möchtest.

By the way kannst du auch Invoke-Command nutzen um einen Prozess Remote auszuführen, dann brauchst du auch nicht mit deiner Funktion testen ob der Prozess noch läuft face-wink Diesem Befehl kannst du auch gleich ein Array an Servernamen übergeben auf denen der Befehl ausgeführt werden soll
$result = Invoke-Command -ComputerName $script:x -ScriptBlock {&'c:\setup.exe' /sAll /rs}
Siehe auch: http://www.howtogeek.com/117192/how-to-run-powershell-commands-on-remot ...

Grüße Uwe
Bugger
Bugger 14.10.2014 aktualisiert um 10:14:50 Uhr
Goto Top
Hi,

funktioniert super, vielen Dank! Ich lass es nochmal offen falls, ich noch auf weitere Probleme stoße face-smile

Gruß
Bugger
Bugger
Bugger 14.10.2014 um 12:01:39 Uhr
Goto Top
Hi,

ein kleines Problemchen hätte ich noch. Ich habe zusätzlich zu der Multiple Box noch ein Textfeld eingebaut, das funktioniert auch, allerdings nicht beides gleichzeitig. Und die Textbox funktioniert nur wenn ich Enter drücke und die Listbox nur wenn ich auf OK klicke:

$Script:x = @()

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")  
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")   

$objForm = New-Object System.Windows.Forms.Form 
$objForm.Text = "Auto Installation"  
$objForm.Size = New-Object System.Drawing.Size(300,480) 
$objForm.StartPosition = "CenterScreen"  

$objForm.KeyPreview = $True

$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")   
    {
        foreach ($objItem in $objListbox.SelectedItems)
            {$Script:x += $objItem}
        $objForm.Close()
    }
    })

$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")   
    {$objForm.Close()}})

$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(75,320)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"  

$OKButton.Add_Click(
   {
        foreach ($objItem in $objListbox.SelectedItems)
            {$Script:x += $objItem}
        $objForm.Close()
   })
   
$objForm.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,320)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"  
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)

$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20) 
$objLabel.Size = New-Object System.Drawing.Size(280,20) 
$objLabel.Text = "Server auswählen:"  
$objForm.Controls.Add($objLabel) 

$objListbox = New-Object System.Windows.Forms.Listbox 
$objListbox.Location = New-Object System.Drawing.Size(10,40) 
$objListbox.Size = New-Object System.Drawing.Size(260,20) 

$objListbox.SelectionMode = "MultiExtended"  

[void] $objListbox.Items.Add("Server 1")  
[void] $objListbox.Items.Add("Server 2")  
[void] $objListbox.Items.Add("Server 3")  

$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Enter")   
    {$Script:x=$objTextBox.Text;$objForm.Close()}})
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")   
    {$objForm.Close()}})

$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,360) 
$objLabel.Size = New-Object System.Drawing.Size(280,20) 
$objLabel.Text = "Eigenen Server eintragen - Enter:"  
$objForm.Controls.Add($objLabel) 
	
$objTextBox = New-Object System.Windows.Forms.TextBox 
$objTextBox.Location = New-Object System.Drawing.Size(10,380) 
$objTextBox.Size = New-Object System.Drawing.Size(260,20) 
$objForm.Controls.Add($objTextBox) 

$objListbox.Height = 270
$objForm.Controls.Add($objListbox) 
$objForm.Topmost = $True

$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()
colinardo
Lösung colinardo 14.10.2014 aktualisiert um 13:18:16 Uhr
Goto Top
$OKButton.Location = New-Object System.Drawing.Size(75,320)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"  

$OKButton.Add_Click({
        $Script:x += $objListbox.SelectedItems
        $objForm.Close()
   })
   
$objForm.Controls.Add($OKButton)

$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(150,320)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"  
$CancelButton.Add_Click({$objForm.Close()})
$objForm.Controls.Add($CancelButton)

$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,20) 
$objLabel.Size = New-Object System.Drawing.Size(280,20) 
$objLabel.Text = "Server auswählen:"  
$objForm.Controls.Add($objLabel) 

$objListbox = New-Object System.Windows.Forms.Listbox 
$objListbox.Location = New-Object System.Drawing.Size(10,40) 
$objListbox.Size = New-Object System.Drawing.Size(260,20) 

$objListbox.SelectionMode = "MultiExtended"  

[void] $objListbox.Items.Add("Server 1")  
[void] $objListbox.Items.Add("Server 2")  
[void] $objListbox.Items.Add("Server 3")  

$objForm.KeyPreview = $True
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape")   
    {$objForm.Close()}})

$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(10,360) 
$objLabel.Size = New-Object System.Drawing.Size(280,20) 
$objLabel.Text = "Eigenen Server eintragen - Enter:"  
$objForm.Controls.Add($objLabel) 
	
$objTextBox = New-Object System.Windows.Forms.TextBox 
$objTextBox.Location = New-Object System.Drawing.Size(10,380) 
$objTextBox.Size = New-Object System.Drawing.Size(260,20) 
$objForm.Controls.Add($objTextBox) 

$objTextBox.Add_KeyPress({
if ($_.KeyChar -eq 13) {
    $objListbox.Items.Add($objTextBox.Text)
   }
})

$objListbox.Height = 270
$objForm.Controls.Add($objListbox) 
$objForm.Topmost = $True

$objForm.Add_Shown({$objForm.Activate()})
[void] $objForm.ShowDialog()

write-host "Gewählte Server:" -ForegroundColor Green  
$script:x
Wenns das dann war, den Beitrag bitte noch auf gelöst setzen. Merci.
Bugger
Bugger 14.10.2014 um 13:18:12 Uhr
Goto Top
Ja, ich glaube das war es dann.^^ Ich hatte es mir anders vorgestellt aber deine Lösung gefällt mir noch besser face-smile Vielen vielen Dank! face-smile

Gruß
Bugger