none
Wie verwende ich ein Element eines Arrays als Variable ohne das Element zu verändern? RRS feed

  • Frage

  • Hallo zusammen,

    ich habe mir ein kleines Powershell Skript geschrieben mit dem ich eine XML Datei grafisch editieren kann. Für jeden Eintrag der in der XML Datei geändert werden soll gibt es ein Textfeld das den bisherigen Wert enthält, beim Klicken auf den Speichern Button wird dann der geänderte Wert zurückgeschrieben.

    Das Ganze sieht dann etwa so aus:

    SWRepository = $XMLFile.Installer.Resources.Repository.Trim()
    
    $label2 = New-Object Windows.Forms.Label
    $label2.text = "Path to your Software Repository"
    
    $text2 = New-Object Windows.Forms.TextBox
    $text2.Location = New-Object Drawing.Point 200,90
    $text2.Size = New-Object Drawing.Point 200,30
    $text2.Text = $SWRepository
    
    ...
    
    $button.add_click({
    $XMLFile.Installer.Resources.Repository = $text2.text
    $XMLFile.Save(((Get-Item $PSScriptRoot).FullName) + "\Variable.xml")
    })
    

    Da die XML Datei allerdings wächst (und damit auch der Bedarf einzelne Werte zu ändern) möchte ich meine GUI nicht jedes mal mühselig neu aufbauen und einzelne Textfelder verschieben, sondern habe das in eine Schleife ausgelagert. Für jeden Wert aus der XML Datei unterscheiden sich die einzelnen Zeilen meiner GUI eigentlich nur in drei Werten (Titel, Beschreibung, Pfad innerhalb der XML Datei). Ich habe daher einen verschachtelten Array gebaut in dem ich diese drei Werte angebe, eine Schleife baut mir dann die GUI zusammen. Der Code dazu sieht so aus:

     
    $Important += @( ,($XMLFile.Installer.Resources.Repository,"Path to your Software Repository","Path that contains the VHD repository","text"))
    
    foreach ($element in $Important)
    {
    $label = New-Object Windows.Forms.Label
    $label.text = $element[1]
     
    $element[3] = New-Object Windows.Forms.TextBox
    $element[3].Location = New-Object Drawing.Point 200,$p
    $element[3].Size = New-Object Drawing.Point 200,30
    $element[3].Text = $element[0]
    
    $form.controls.add($label)
    $form.controls.add($element[3]) }

    Soweit funktioniert alles ganz wunderbar, allerdings brauche ich eine zweite Schleife die das Speichern übernimmt (beim Klick auf den Speichern Button). Da ich ursprünglich einen einzelnen Eintrag für jeden Wert der XML Datei hatte, konnte ich den explizit ansprechen und geänderte Texte eintragen, jetzt muss ich aber innerhalb der Schleife das Objekt aus meinem Array verwenden. Ich habe das hier probiert:

    $button.add_click({
    foreach ($element in $Important)
    {
    $element[0] = $element[3].text
    }
    $XMLFile.Save(((Get-Item $PSScriptRoot).FullName) + "\Variable.xml")
    })

    Damit ändere ich aber den Wert von "$element[0]", schreibe also statt meinem Objekt das auf einen XML Wert verweist einen simplen String hinein. Logischerweise wird dann auch nichts in meiner XML Datei geschrieben.

    Habt ihr einen Tipp für mich, wie ich meinen geänderten Text in die XML Datei bekomme indem ich den Inhalt von "$element[0]" verwende, statt die Zelle zu überschreiben?

    Vielen Dank für Eure Hilfe

    Joh

    Samstag, 29. November 2014 03:38

Antworten

  • Hallo Joh!

    Du musst eine eindeutige Zuordnung von Windows Forms zum XML dokument (DOM) hinbekommen.

    Ich nehme hier als Beispiel die books.xml Datei von folgendem Link damit du das nachvollziehen kannst:

    http://msdn.microsoft.com/en-us/library/ms762271%28v=vs.85%29.aspx

    $XMLFilePath = 'D:\temp\books.xml'
    
    # XML file einlesen und aus dem Text ein XML Document Object Model (XML-DOM oder kurz DOM) machen
    $XMLFile = [XML](Get-Content -Path $XMLFilePath)
    
    #region Assambly loading ################################################################
    
      Add-Type -AssemblyName System.Windows.Forms
      Add-Type -AssemblyName System.Drawing
    
    #endregion Assambly loading ################################################################
    
    #region object creation ################################################################
    
    # createn Windows form object
    $Form1 = New-Object Windows.Forms.Form
    
    $Form1.Text = 'PowerShell first Windows Form' # Text für die Titelleiste der Form
    $Form1.Name = 'MyFirstForm' # Name des Objektes im Speicher
    $Form1.StartPosition = 1 # Startposition der Form  1 = center screen 
    $Form1.DataBindings.DefaultDataSourceUpdateMode = 0 # keine Datenbindung
    $Form1.ClientSize = '500, 600' # zuweisen der Size zur Form
    $Form1.FormBorderStyle = 1 # Style des Rahmens festlegen 1 = FixedDialog
    
    # für jedes Buch in der XML Datei werden Windows Forms controls erstellt
    # Variable zum 'zählen' der Y Position der controls
    $Y = 0 
    ForEach($Book in $XMLFile.catalog.book) {
      $label = New-Object Windows.Forms.Label
      $label.Location = "0, $Y"
      $label.Size = '200, 15'
      $label.Name = "LblTitle$($Book.id)"
      $label.text = "Title: $($Book.title)"
      $Form1.Controls.Add($label)
      $Y += 20
      $label = New-Object Windows.Forms.Label
      $label.Location = "0, $Y"
      $label.Size = '50, 15'
      $label.Name = "LblAuthor$($Book.id)"
      $label.text = 'Author:'
      $Form1.Controls.Add($label)
      $TxtBx = New-Object Windows.Forms.TextBox
      $TxtBx.Location = "55, $Y"
      $TxtBx.Size = '200, 15'
      # Anhand des eindeitigen Namens von dem Control, kann es in der liste der Controls wiedergefunden werden
      # die ID des Buches sorgt für eine eindeutigen Namen und die Wiedererkennung
      $TxtBx.Name = "TxtBxAuthor$($Book.id)"
      $TxtBx.text = $Book.author
      $Form1.Controls.Add($TxtBx)
      $Y += 25
    }
    
    $OkButton = New-Object System.Windows.Forms.Button
    $OkButton.Location = '370, 560'
    $OkButton.Size = '122, 30'
    $OkButton.Text = 'Speichern'
    $OkButton.TabIndex = 1
    $OkButton.UseVisualStyleBackColor = $true
    $Form1.Controls.Add($OkButton)
    
    $OkButton.add_Click({
      
      # für jedes Buch in der XML das richtige Control anhand der ID finden
      ForEach($Book in $XMLFile.catalog.book) {
        
        # jedes Control in der Form durchlaufen
        ForEach($Control in $Form1.Controls) {
          # wenn der name des Controls der ID des Buches entspricht und mit 'TxtBxAuthor' beginnt
          # ist das controk vom Typ Textbox
          If($Control.Name -eq "TxtBxAuthor$($Book.id)"){
            # das control in den Typ Textbox umwandeln und auf dei eigenschaft .Text zugreifen
            # der text der textbox wird dem XML Element aus dem XML DOM zugewiesen
            $Book.author = ([Windows.Forms.TextBox]$Control).Text
          }
        }
      }
      $XMLFile.Save($XMLFilePath)
      $Form1.close()
    })
    
    
    # Form Anzeigen
    $Form1.ShowDialog()


    PowerShell Artikel, Buchtipps und kostenlose PowerShell Tutorials + E-Books
    auf der deutschsprachigen PowerShell Community

    Mein 21 Teiliger PowerShell Video Grundlehrgang
    Deutsche PowerShell Videos auf Youtube
    Folge mir auf:
    Twitter | Facebook | Google+

    Mittwoch, 3. Dezember 2014 07:51