Jump to content

Powershell - Liste von "eignen" Objekten erstellen


Direkt zur Lösung Gelöst von testperson,

Empfohlene Beiträge

Hallo und einen schönen guten Tag an alle.

 

Ich stehe vor einem kleinem Problem und finde nicht die Lösung/den Fehler.

Zur Aufgabenstellung:

Ich habe eine CSV-Datei die ich in eine Variable/Objekt/Array packe.

$Inhalt = Import-csv -path $Ort -Delimiter ";" - Encoding UTF 8

Ausserdem habe ich eine Klasse erstellt, die sich User nennt und mit Personalnummer, Vorname, Nachname etc. bestückt ist.

 

class User {
[int]$Personalnummer
[string]$Vorname
[string]$Nachname
[int]$Kostenstelle
[string]$Abteilung
}

Jetzt möchte ich gerne ein Array/Objekt/Liste vom Typ User haben.

Habe ich so gelöst :

$Userliste = New-Object System.Collections.Generic.List[user]

Und nun füge ich an einer anderen Stelle in einer Funktion die auf die globale $Userliste zugreift mit 

$Userliste.Add($Userobjekt)

$Userobjekt hinzu, wobei diese vom Typ User sind.

Deklariert habe ich das so

$Userobjekt = New-Object -TypeName User

 

Das bescheuerte an der Sache ist, ich sehe dass das $userobjekt mit den richtigen werten hinzugefügt wird und die Liste

wird auch länger, aber die Liste "aktualisiert" sich immer mit dem letzten Userobjekt....also es steht dann n-Mal immer

das Letzte Objekt drin und natürlich n mal nur der eine User.

 

Ich würde ja sagen, da wird irgendwie nur ein Zeiger in die Liste gesetzt und der steht immer auf dem Inhalt des zu Letzt hinzugefügtem Objekt.

Aber warum ist das so...wieso steht an jeder Stelle der $Userliste scheinbar das "selbe" Objekt.

 

 

Vielleicht hat ja jemand nen Tipp vielen Dank und so long der Velmor

 

 

bearbeitet von Velmor
Link zu diesem Kommentar

Hallo und willkommen im MCSEboard.

 

Ich hab nicht wirklich Erfahrung mit Klassen in PowerShell, aber ohne etwas mehr von Deinem Code zu sehen, wird es meiner Meinung nach schwer, etwas Sinnvolles zu empfehlen.

 

vor einer Stunde schrieb Velmor:

Und nun füge ich an einer anderen Stelle in einer Funktion die auf die globale $Userliste zugreift mit 

$Userliste.Add($Userobjekt)

$Userobjekt hinzu, wobei diese vom Typ User sind.

Bist Du an der Stelle sicher, dass Du verschiedene Objekte hinzufügst?

 

Davon unabhängig - was ist denn das Ziel DES GANZEN ... also was soll am Ende dabei rauskommen? Warum ne Klasse dafür benutzen?

Link zu diesem Kommentar
  • Beste Lösung
Geschrieben (bearbeitet)

Hi,

 

ich vermute, du erstellt einmalig dein Userobjekt und änderst dieses immer wieder mit neuen Daten aus der CSV. Dann ist das AFAIK by Design. Du wirst ja vermutlich die importierte CSV Datei per foreach-Schleife durchlaufen und so der Userliste deine Userobjekte hinzufügen. _Vermutlich_ erstellst du _vor_ der Schleife das Userobjekt und nicht _in_ der Schleife:

 

# Vermutlich so / "falsch"
$Inhalt = Import-Csv ....
$Userliste = ...
$Userobjekt = New-Object -TypeName User
foreach($i in $Inhalt){

	$Userobjekt.Vorname = $i.Vorname
	...
	$Userliste.Add($UserObject)
}

# Sollte vermutlich zu deinen Erwartungen führen:
$Inhalt = Import-Csv ....
$Userliste = ...
foreach($i in $Inhalt){
	
	$Userobjekt = New-Object -TypeName User
	$Userobjekt.Vorname = $i.Vorname
	...
	$Userliste.Add($UserObject)
}

 

Gruß

Jan

bearbeitet von testperson
Link zu diesem Kommentar

Vielen Dank schon mal für die Anwort, und die Begrüssung, klar kann ich mehr Code liefern :).

Dachte das hier sind die Entscheidenden Stellen. Und warum mit Klassen....weil ich

es mal ausprobieren wollte :)

 

Hier der Code, wobei die write-host Zeilen für mich nur zum Testen waren.

In der Variable $Inhalt steht die CSV drin. 

Die Variable $Userobjekt habe ich zum testen hier in der Funktion immer wieder neu erstellen lassen....um

auch Sicher zu sein, dass es immer wieder ein neues Objekt ist :)

 

 

Die CSV sieht so aus
 

Personalnummer;Nachname;Vorname;Abteilung

12;Kohl;Helmut;3256;Handwerker

 

function array2liste ($Inhalt)
{
	$Userobjekt = New-Object -TypeName User
	$i=0
	foreach ($Feld in $Inhalt)
	{
		
		$i++
		$Userobjekt.Personalnummer = $Feld.Personalnummer
		$Userobjekt.Vorname=$Feld.Vorname
		$Userobjekt.Nachname=$Feld.Nachname
		$Userobjekt.Kostenstelle=$Feld.Kostenstelle
		$Userobjekt.Abteilung = $Feld.Abteilung
		
		
		$Userliste.Add($Userobjekt)
	#	Write-Host "*************************************"
#		foreach ($eintrag in $Userliste)#
		#{
			
		#	Write-Host $i
		#	Write-Host $Index
		#	Write-Host $eintrag.Personalnummer
		#	Write-Host $eintrag.Vorname
		#	Write-Host $eintrag.Nachname
			
			
		#}
		
		
	}
	Write-Host "*************************************"
	Write-Host $Userliste[0].Personalnummer
	Write-Host 	$Userliste[0].Vorname
	
	Write-Host $Userliste[1].Personalnummer
	Write-Host $Userliste[1].Vorname
	
	Write-Host $Userliste[2].Personalnummer
	Write-Host $Userliste[2].Vorname
	
	Write-Host $Userliste[3].Personalnummer
	Write-Host $Userliste[3].Vorname
	
	
}

 

@Testperson 

 

Vielen Dank,

 

die Lösung von Dir kam schneller als meine Antwort.

Wobei ich es nicht verstehe...ich gebe dem Objekt doch immer wieder neue Werte und wenn ich diese Abfrage zeigt

es mir auch immer wieder die neuen Werte an...nur beim Übertragen schlägt es dann "fehl".

Ist es wie vermutet, dass ich nur einen Zeiger auf die Werte in meine Liste bringe ?

 

Könntest Du mir das nochmal genauer erklären ?

 

Vielen Dank der Velmor

Link zu diesem Kommentar

Meine Zeit, wo ich "viel" programmiert habe ist schon was länger rum und war noch in der vor PowerShell Zeit. Würde es aber laienhaft genau wie du beschreiben:

 

Du erstellt das Userobjekt einmalig und fügst dann nur eine Referenz / einen Zeiger in die Userliste hinzu. Wenn du jetzt das Objekt änderst, zeigt der Pointer in der Userliste an allen Stellen ja auf das eine Objekt.

Link zu diesem Kommentar

Wenn Du das $userobject erstellst, hast Du ein Objekt. Das fügst Du Deinem Array hinzu. Dann änderst Du Eigenschaften davon - im Array ist aber immer noch das eigentliche Objekt. Und wenn Du das erneut hinzufügst, ist es jetzt halt zweimal drin. Du mußt schon bei jedem neuen User eine neue Instanz erstellen...

 

Insofern: @testperson hat's schon richtig beschrieben.

Nachtrag: Das gleiche "Problem" hat man auch, wenn man Kopien von Objekten erstellen möchte.

$MyObject = [PSCustomObject]@{
    Name = "Test"
}
$MyCopy = $MyObject
$MyCopy.Name = "Geändert"

$MyObject.Name

$MyCopy2 = $MyObject.PSObject.Copy()
$MyCopy2.Name = "Geändert"

$MyObject.Name

 

Viele glauben, daß $MyObject.Name immer noch "Test" wäre. Ist es aber nicht, denn $MyObject ist identisch mit $MyCopy. In der Variablen steckt das gleiche Objekt. Du mußt ein neues Objekt erstellen, entweder wie in meinem Beispiel durch Kopieren oder wie bei Dir durch ::new()

Link zu diesem Kommentar

Schreibe einen Kommentar

Du kannst jetzt antworten und Dich später registrieren. Falls Du bereits ein Mitglied bist, logge Dich jetzt ein.

Gast
Auf dieses Thema antworten...

×   Du hast formatierten Text eingefügt.   Formatierung jetzt entfernen

  Only 75 emoji are allowed.

×   Dein Link wurde automatisch eingebettet.   Einbetten rückgängig machen und als Link darstellen

×   Dein vorheriger Inhalt wurde wiederhergestellt.   Editor-Fenster leeren

×   Du kannst Bilder nicht direkt einfügen. Lade Bilder hoch oder lade sie von einer URL.

×
×
  • Neu erstellen...