tobiased
Goto Top

Verbindung von mehreren Hash-Tabellen

Hallo community,

ich habe ein Problem mit meinem Powershell Skript. Dieses soll es möglich machen Daten aus einer Internetseite herraus zu lesen und als CSV Datei abzuspeichern. Dies funktioniert auch soweit, aber da das Script so dynamisch wie möglich sein soll, frage ich in einer Schleife ab, welche Spaltennahmen den später die CSV Datei haben soll.
(Kurz zur erklärung die Abfrage geschied über eine URL in dem man mit ?columns=name,address,... die ausgabe filtern kann. Diese Ausgabe erfolg in JSON.)
Jetzt ist nicht das Problem die richtige URL zu erzeugen, sondern das die Spalten auch manchmal ein Array sein können (z.b. services). Um dieses Problem zu beheben, wandle ich das Array mit hilfer dieses Befehls in einen String um:

@{Name='$services';Expression={[string]::join(",",($_.$services))}}.

Auch das klapt noch ohne Probleme, nur wie gesagt das Skript soll Dynamsich sein und am Ende meiner Ausgabe soll es nicht so wie es jetzt ist stehen

$ausgabe | select name, address,@{Name='services';Expression={[string]::join(",",($_.services))}} | export-csv $path

sondern in einer Art wie dies:

$ausgabe | select $anordnung | export-csv $pfad

So, versucht zu lösen hab ich es momentag in einer schleife die den User immer wieder fragt ob er weitere "Spaltennahmen" eingeben will. Diese eingabe wird in der Variablen $temp gespeichert und zusammen mit den folgenden 2 Befehlen inder der Schleife laufen gelassen.

$anordnungtemp = @{Name='$temp';Expression={[string]::join(",",($_.$temp))}}
$anordnung = $anordnung + "," + $anordnungtemp

(das "," benötige ich um die eingaben beim select Befehl zu trennen)

Und da ist das Problem, solange ich nur ein "Spaltennamen" eingebe funktioniert alles einwandfrei aber wenn ich einen zweiten eingebe kommt immer die Fehlermeldung:
"Das Element wurde bereits hinzugefügt. Schlüssel im Wörterbuch: "Expression". Hinzuzufügender Schlüssel: "Expression""

Ich habe auch schon versucht, die Werte in den Variablen in Anführungszeichen zu setzten, dass die Typumwandlungsbefehele nicht sofort ausgeführt werden, sonder erst in der letzten Zeile, also in der ausgabe. Dann bekomme ich zwar keine Fehlermeldung mehr, aber meine CSV Datei enthält keine Werte.

Ich hoffe ich habe mir halbwegs verständlich ausgedrück im Grunde geht es mir darum in der Zeile:

$ausgabe | select $anordnung | export-csv $pfad

anstelle von $anordnung so etwas zu bekommen

@{Name='name';Expression={[string]::join(",",($_.name))}}, @{Name='address';Expression={[string]::join(",",($_.address))}}, @{Name='services';Expression={[string]::join(",",($_.services))}}

wie, spielt dabei keine rolle, nur es muss halt dynamisch sein.

Mit freundlichen Grüßen

Tobias

Content-Key: 263198

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

Printed on: April 27, 2024 at 10:04 o'clock

Member: colinardo
Solution colinardo Feb 12, 2015, updated at Feb 13, 2015 at 10:29:52 (UTC)
Goto Top
Hallo Tobias, Willlkommen auf Administrator.de!
Ich würde das anders angehen und die Daten vorher schon korrekt in die Spalten des Objects $ausgabe schreiben oder korrigieren, dann musst du nicht mit einer Expression in einem Select "nachkorrigieren".
Also alle Spalten von $ausgabe durchlaufen und die Arrays in Strings umwandeln.
Zum Schluss lässt du den Anwender dann die gewünschten Spalten eingeben und machst mit dieser Variable einen select auf dein Ausgabe-Objekt.

Hier ein einfaches Beispiel:
# Nur für einen Test Demodaten erzeugen
$ausgabe = new-object PSObject -Property @{"Name"="Testzeile";"Wert1"=@("Test1","Test2","Test3");"Wert2"=@("BlaA","BlaB","BlaC")}  

# Alle Spaltenname des Objekts extrahieren
$spalten = $ausgabe | gm -MemberType NoteProperty | select -ExpandProperty Name

# Alle Daten in den Spalten des Objects in Strings wandeln
foreach($line in $ausgabe){
    $spalten | %{$line.$_ = $line.$_ -join ','}  
}

# User die Spalten eingeben lassen (im Format Spalte1,Spalte2,Spalte3,SpalteN)
$auswahl = (Read-host "Geben sie die Spaltennamen an mit Komma getrennt an").Split(",")  

# CSV Ausgabe
$ausgabe | select $auswahl | export-csv "C:\temp\test.csv" -Delimiter ";" -NoType  

Grüße Uwe
Member: Tobiased
Tobiased Feb 12, 2015 at 15:47:59 (UTC)
Goto Top
Hallo Uwe,

erst einmal danke für deine schnelle Antwort, nur leider löst sie mein Problem nicht.
Wenn ich es so mache, wie du Vorgeschlagen hast, habe ich wieder das Problem, dass die Arrays nicht richtig umgewandelt werden, welches ich mit:

@{Name='services';Expression={[string]::join(",",($_.services))}}

behoben hatte. Die CSV Datei sah wieder so aus:

"name","address","services"
"AP-01","192.168.123.25","System.Object"

und nicht so

"name","address","services"
"AP-01","192.168.123.25","Service1,Service2,Service3,..."

Hier einmal mein komplettes Skript, vielleicht habe ich auch nur einen Fehler gemacht, bei der Implementierung deines Skriptes:

$ausgabe = new-object PSObject -Property @{"Name"="Testzeile";"Wert1"=@("Test1","Test2","Test3");"Wert2"=@("BlaA","BlaB","BlaC")}

#Abfrage der benötigten Informationen
$Username = Read-Host "Bitte geben Sie den Nutzernamen an"
$Password = Read-Host "Bitte geben Sie das Passwort an"
$url = read-host "Bitte geben Sie die gewüncht URL ein, ohne die Einträge '?columns=...'"
$spalten = $ausgabe | gm -MemberType NoteProperty | select -ExpandProperty Name
foreach($line in $ausgabe){
$spalten | %{$line.$_ = $line.$_ -join ','}
}
$auswahl = (Read-host "Geben sie die Spaltennamen an mit Komma getrennt an").Split(",")
$url = $url + "?columns=" + $auswahl

$path = Read-Host "Bitte geben Sie den Zeilpfad der Output Datei an"


#Umwandlung der Zugangsdaten für die Internetseite
$Zugangsdaten = $Username + ":" + $Password
$bytes = [System.Text.Encoding]::ASCII.GetBytes($zugangsdaten)
$base64 = [System.Convert]::ToBase64String($bytes)
$basicAuthValue = "Basic $base64"
$headers = @{ Authorization = $basicAuthValue }


#Funktion zum Ignorieren der Wahrnung des fehlenden Sicherheitszertifikat
add-type @"
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy


#Einlesen der Daten sowie deren Ausgabe als CSV Datei
$Daten = Invoke-WebRequest -uri "$url" -Headers $headers
$ausgabe = $Daten | ConvertFrom-Json
$ausgabe | select $auswahl | export-csv $path

PS: Ich würde mich auch freuen, wenn mir jemand den Trick verraten würde, wie ich den Code als Tabelle ausgeben kann ;P

Grüße Tobias
Member: colinardo
Solution colinardo Feb 12, 2015, updated at Feb 13, 2015 at 10:30:00 (UTC)
Goto Top
Hier einmal mein komplettes Skript, vielleicht habe ich auch nur einen Fehler gemacht, bei der Implementierung deines Skriptes:
Das hast du leider nicht richtig in dein Script implementiert, alles etwas an der falschen Stelle plaziert, deswegen auch keine Änderung deiner Ausgabe face-wink
Bitte nutze in Zukunft Code-Tags für deinen Quellcode: <code> Quellcode </code>. Merci.
#Abfrage der benötigten Informationen
$Username = Read-Host "Bitte geben Sie den Nutzernamen an"  
$Password = Read-Host "Bitte geben Sie das Passwort an"  
$url = read-host "Bitte geben Sie die gewüncht URL ein, ohne die Einträge '?columns=...'"  
$auswahl = Read-host "Geben sie die Spaltennamen an mit Komma getrennt an"  
$url = $url + "?columns=" + $auswahl  

$path = Read-Host "Bitte geben Sie den Zeilpfad der Output Datei an"  

#Umwandlung der Zugangsdaten für die Internetseite
$Zugangsdaten = $Username + ":" + $Password  
$bytes = [System.Text.Encoding]::ASCII.GetBytes($zugangsdaten)
$base64 = [System.Convert]::ToBase64String($bytes)
$basicAuthValue = "Basic $base64"  
$headers = @{ Authorization = $basicAuthValue }


#Funktion zum Ignorieren der Wahrnung des fehlenden Sicherheitszertifikat
add-type @"  
using System.Net;
using System.Security.Cryptography.X509Certificates;
public class TrustAllCertsPolicy : ICertificatePolicy {
public bool CheckValidationResult(
ServicePoint srvPoint, X509Certificate certificate,
WebRequest request, int certificateProblem) {
return true;
}
}
"@  
[System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy


#Einlesen der Daten sowie deren Ausgabe als CSV Datei
$Daten = Invoke-WebRequest -uri "$url" -Headers $headers  
$ausgabe = $Daten | ConvertFrom-Json

# Bearbeiten der extrahierten Daten (Umwandlung der Arrays)
$spalten = $ausgabe | gm -MemberType NoteProperty | select -ExpandProperty Name
foreach($line in $ausgabe){
    $spalten | %{$line.$_ = $line.$_ -join ','}  
}

$ausgabe | select $auswahl.Split(",") | export-csv $path -Delimiter ";" -NoType -Encoding UTF8  

PS: Ich würde mich auch freuen, wenn mir jemand den Trick verraten würde, wie ich den Code als Tabelle ausgeben kann ;P
Was meinst du damit, meinst du format-table oder was meinst du sonst mit Tabelle ? Spezifiziere mal genau wie und in welchem Format was wohin soll.

Etwa sowas ?:
$ausgabe | select $auswahl.Split(",") | format-table -AutoSize -Wrap | out-file 'C:\test.txt'
oder als HTML-Tabelle so:
$ausgabe | select $auswahl.Split(",") | Convertto-HTML | out-file 'C:\test.html'
Wie man die Daten mit einer HTML-Tabelle individuell gestalten kann kannst du in diesem Thread nachlesen:
Bestimmte Werte aus CSV Datei automatisch in HTML Datei einfügen

Grüße Uwe
Member: Tobiased
Tobiased Feb 13, 2015 at 07:56:18 (UTC)
Goto Top
Hallo Uwe,

vielen vielen dank es funktioniert Super!
Und ich meinte damit eigenlich das hier:
 Quellcode 
;P