Powershell CustomObject richtig verwenden und Verhalten von Variablen bei geschweiften Klammern
Hi zusammen,
vorne weg - ich bin noch am lernen von PS ....
Im Rahmen der Useranlage möchte ich mir ein CustomObject erstellen , in das ich relevante Werte schreibe.
Feste Werte sind die ID und die Email Adresse, welche aus einer CSV eingelesen werden. Mit einer Schleife arbeite ich das ganze ab und erzeuge die User. Nun ich möchte nun pro User ein zufälliges Passwort, dass ich später an bestimmte Personen als Email aus dem Script verschicke.
Das hätte ich nun gerne so wie ich die Daten aus den CSVs lade, nämlich tabellarisch, damit ich die gezielt ansprechen kann.
Soweit so gut. Aber wie schreibe ich jetzt pro Runde in der ein User angelegt wird die neuen Daten in eine neue Zeile? Ich habe mir schon einen Wolfgesucht aber nix gefunden ...
Außerdem verstehe ich nicht, warum ich nur noch Statische Werte erhalte, wenn ich den Block oben in {}-Klammern setze:
Ich dachte die Variablen wären global ....
Thx
Nagus
vorne weg - ich bin noch am lernen von PS ....
Im Rahmen der Useranlage möchte ich mir ein CustomObject erstellen , in das ich relevante Werte schreibe.
Feste Werte sind die ID und die Email Adresse, welche aus einer CSV eingelesen werden. Mit einer Schleife arbeite ich das ganze ab und erzeuge die User. Nun ich möchte nun pro User ein zufälliges Passwort, dass ich später an bestimmte Personen als Email aus dem Script verschicke.
Das hätte ich nun gerne so wie ich die Daten aus den CSVs lade, nämlich tabellarisch, damit ich die gezielt ansprechen kann.
$mail = 'max.mustermann@world.de'
function Get-RandomCharacters($length, $characters) {
$random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
$private:ofs=""
return [String]$characters[$random]
}
function Scramble-String([string]$inputString){
$characterArray = $inputString.ToCharArray()
$scrambledStringArray = $characterArray | Get-Random -Count $characterArray.Length
$outputString = -join $scrambledStringArray
return $outputString
}
$password = Get-RandomCharacters -length 7 -characters 'abcdefghiklmnoprstuvwxyz'
$password += Get-RandomCharacters -length 2 -characters 'ABCDEFGHKLMNOPRSTUVWXYZ'
$password += Get-RandomCharacters -length 1 -characters '1234567890'
$password += Get-RandomCharacters -length 1 -characters '!§$%&()=?@#*+-'
$password = Scramble-String $password
function Get-RandomCharacters($length, $characters) {
$random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
$private:ofs=""
return [String]$characters[$random]
}
function Scramble-String([string]$inputString){
$characterArray = $inputString.ToCharArray()
$scrambledStringArray = $characterArray | Get-Random -Count $characterArray.Length
$outputString = -join $scrambledStringArray
return $outputString
}
$userid = Get-RandomCharacters -length 4 -characters 'ABCDEFGHKLMNOPRSTUVWXYZ'
$userid += Get-RandomCharacters -length 2 -characters '1234567890'
$userid = Scramble-String $userid
$PasswortListeTemp = [PSCustomObject]@{
PSTypeName = 'PasswortListe.Temp'
UserID = $UserId
EmailEmpfaenger = 'bla.bla@world.de'
Passwort = $password
}
$PasswortListeTemp
Soweit so gut. Aber wie schreibe ich jetzt pro Runde in der ein User angelegt wird die neuen Daten in eine neue Zeile? Ich habe mir schon einen Wolfgesucht aber nix gefunden ...
Außerdem verstehe ich nicht, warum ich nur noch Statische Werte erhalte, wenn ich den Block oben in {}-Klammern setze:
$mail = 'max.mustermann@world.de'
{
function Get-RandomCharacters($length, $characters) {
$random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
$private:ofs=""
return [String]$characters[$random]
}
function Scramble-String([string]$inputString){
$characterArray = $inputString.ToCharArray()
$scrambledStringArray = $characterArray | Get-Random -Count $characterArray.Length
$outputString = -join $scrambledStringArray
return $outputString
}
$password = Get-RandomCharacters -length 7 -characters 'abcdefghiklmnoprstuvwxyz'
$password += Get-RandomCharacters -length 2 -characters 'ABCDEFGHKLMNOPRSTUVWXYZ'
$password += Get-RandomCharacters -length 1 -characters '1234567890'
$password += Get-RandomCharacters -length 1 -characters '!§$%&()=?@#*+-'
$password = Scramble-String $password
function Get-RandomCharacters($length, $characters) {
$random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
$private:ofs=""
return [String]$characters[$random]
}
function Scramble-String([string]$inputString){
$characterArray = $inputString.ToCharArray()
$scrambledStringArray = $characterArray | Get-Random -Count $characterArray.Length
$outputString = -join $scrambledStringArray
return $outputString
}
$userid = Get-RandomCharacters -length 4 -characters 'ABCDEFGHKLMNOPRSTUVWXYZ'
$userid += Get-RandomCharacters -length 2 -characters '1234567890'
$userid = Scramble-String $userid
$PasswortListeTemp = [PSCustomObject]@{
PSTypeName = 'PasswortListe.Temp'
UserID = $UserId
EmailEmpfaenger = 'bla.bla@world.de'
Passwort = $password
}
}
$PasswortListeTemp
Ich dachte die Variablen wären global ....
Thx
Nagus
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 614368
Url: https://administrator.de/forum/powershell-customobject-richtig-verwenden-und-verhalten-von-variablen-bei-geschweiften-klammern-614368.html
Ausgedruckt am: 22.12.2024 um 11:12 Uhr
4 Kommentare
Neuester Kommentar
waren sie, bis Powershell 4.0
Vor ein paar Jahren kam dann die Revolution, Variablen hatten plötzlich einen Scope und Subroutinen / Funktionen erfordern zwingend eine Übergabe von allen Parametern.
Ich meine mit Windows 2016 CTP kam PS 5.0 und diese Version konnte das dann endlich... bzw. ich war auch sehr angepisst, denn daß Microsoft in einer Skritpsprache, die es von überallher zusammengeklaut hat, dann so grundsätzliche Dinge ändert, das fand ich schon mal gelinde gesagt gemein.
Damit mein Skript - das diverse Features in OS zwishcen Windows 7 und 2019 aktiviert und dann im IIS ein paar Sites erzeugt - portabel blieb mußte ich die als Parameter übergebenen Variablen umbenennen damit es auf PS4 und PS5 läuft.
Vor ein paar Jahren kam dann die Revolution, Variablen hatten plötzlich einen Scope und Subroutinen / Funktionen erfordern zwingend eine Übergabe von allen Parametern.
Ich meine mit Windows 2016 CTP kam PS 5.0 und diese Version konnte das dann endlich... bzw. ich war auch sehr angepisst, denn daß Microsoft in einer Skritpsprache, die es von überallher zusammengeklaut hat, dann so grundsätzliche Dinge ändert, das fand ich schon mal gelinde gesagt gemein.
Damit mein Skript - das diverse Features in OS zwishcen Windows 7 und 2019 aktiviert und dann im IIS ein paar Sites erzeugt - portabel blieb mußte ich die als Parameter übergebenen Variablen umbenennen damit es auf PS4 und PS5 läuft.
Moin,
warum definierst du die Funktionen Get-RandomCharacters & Scramble-String im Script doppelt? Das ist unnötig, einmal definiert kannst du eine Funktion so oft aufrufen wie du willst.
Das funktioniert so zwar, aber hier ein kleiner Tipp, der direkt beide Funktionen vereint:
Hinweis: das % ist ein Alias für Foreach-Object
Alternativ kannst du jedoch auch mit Select-Object einfach Spalten an einem Object ergänzen, was in deinem Fall mit bestehender CSV-Datei wohl die bessere Wahl wäre.
Die ergänzten Spalten müssen nur folgendem Muster entsprechen:
Hinweis: Name & Expression kann man auch einfach mit n & e abkürzen.
Gehe ich Recht in der Annahme, dass PSTypeName immer gleich sein soll? Das sähe dann am Ende so aus:
Wenn du in deiner Csv-Datei ein anderes Trennzeichen als ein Semikolon verwendest, musst du -Delimiter natürlich anpassen. Darüber hinaus muss du, sofern du keine Spaltenüberschreiften in deiner CSV-Datei hast, noch -Header UserID,EmailEmpfaenger ergänzen.
Jedoch können die Variablen auch auf unterschiedliche Weise gesetz werden:
siehe hierzu auch
Gruß Thomas
warum definierst du die Funktionen Get-RandomCharacters & Scramble-String im Script doppelt? Das ist unnötig, einmal definiert kannst du eine Funktion so oft aufrufen wie du willst.
Zitat von @Nagus:
function Get-RandomCharacters($length, $characters) {
$random = 1..$length | ForEach-Object { Get-Random -Maximum $characters.length }
$private:ofs=""
return [String]$characters[$random]
}
function Scramble-String([string]$inputString){
$characterArray = $inputString.ToCharArray()
$scrambledStringArray = $characterArray | Get-Random -Count $characterArray.Length
$outputString = -join $scrambledStringArray
return $outputString
}
$password = Get-RandomCharacters -length 7 -characters 'abcdefghiklmnoprstuvwxyz'
$password += Get-RandomCharacters -length 2 -characters 'ABCDEFGHKLMNOPRSTUVWXYZ'
$password += Get-RandomCharacters -length 1 -characters '1234567890'
$password += Get-RandomCharacters -length 1 -characters '!§$%&()=?@#*+-'
$password = Scramble-String $password
Das funktioniert so zwar, aber hier ein kleiner Tipp, der direkt beide Funktionen vereint:
$lower='abcdefghiklmnoprstuvwxyz'.ToCharArray()
$upper='ABCDEFGHKLMNOPRSTUVWXYZ'.ToCharArray()
$digit='1234567890'.ToCharArray()
$punct='!§$%&()=?@#*+-'.ToCharArray()
function Get-RandomPassword {
$Password = @(
1..7 | %{ $lower | Get-Random } # 7 zufällige kleine Buchstaben
1..2 | %{ $upper | Get-Random } # 2 zufällige Großbuchstaben
$digit | get-random # 1 zufällige Zahl
$punct | get-random # 1 zufälliges Sonderzeichen
)
$Password = ( $Password | Get-Random -Count $Password.count ) -Join ''
return $Password
}
Soweit so gut. Aber wie schreibe ich jetzt pro Runde in der ein User angelegt wird die neuen Daten in eine neue Zeile?
Wenn du es mit Foreach--Object machst, musst du halt für jede Zeile das PSCustomObject mit den entsprechenden Werten neu erstellen.Alternativ kannst du jedoch auch mit Select-Object einfach Spalten an einem Object ergänzen, was in deinem Fall mit bestehender CSV-Datei wohl die bessere Wahl wäre.
Die ergänzten Spalten müssen nur folgendem Muster entsprechen:
@{ Name = "Spaltenname" ; Expression = { <# Code zur Ermittlung des Wertes #> }}
Gehe ich Recht in der Annahme, dass PSTypeName immer gleich sein soll? Das sähe dann am Ende so aus:
$CSV = 'C:\Pfad\Datei.csv'
Import-Csv -path $CSV -Delimiter ';' | Select-Object @{n='PSTypeName';e={'PasswortListe.Temp'}},UserID,EmailEmpfaenger,@{n='Passwort';e={Get-RandomPassword}}
Außerdem verstehe ich nicht, warum ich nur noch Statische Werte erhalte, wenn ich den Block oben in {}-Klammern setze
Was in Geschweiften Klammern steht wird zum Codeblock und muss dann mit & davor aufgerufen werden, sofern es ausgeführt werden soll. Macht in deinem Fall jedoch wenig Sinn und eine weiterführende Erklärung wäre hier wohl erst mal zu viel Input. Ich dachte die Variablen wären global ....
Wie ist diese Aussage zu verstehen? Variablen sind per default zum Glück nicht global - so ist es möglich, in Funktionen teils die selben Variablennamen zu nutzen ohne sich Gegenseitig zu stören.Jedoch können die Variablen auch auf unterschiedliche Weise gesetz werden:
$Variable = 'xxx' # Lokale Variable, gilt nur innerhalb eines Moduls
$Local:Variable = 'xxx' # Selbes wie oben, nur mit Bereichsangabe
$Global:Variable = 'xxx' # Globale Variable, gilt Skriptübergreifend in der kompletten Instanz
$Script:Variable = 'xxx' # Gilt im gesamten Skript
$Private:Variable = 'xxx' # Private Variable gilt nur innerhalb eines Bereichs
help about_scopes
Gruß Thomas
Zitat von @Nagus:
Kann ich die eigentlich an beliebiger stelle im Script ablegen und benutzen? Also beispielweise alle Funktionen am Anfang erstellen und dann später nur noch aufrufen?
Ja, sie müssen halt nur zu dem Zeitpunkt, an dem du sie aufrufen möchtest, bereits definiert sein - alle Funktionen am Anfang erstellen geht also wunderbar, alle Funktionen ans Ende des Skripts stellen geht jedoch nicht.Kann ich die eigentlich an beliebiger stelle im Script ablegen und benutzen? Also beispielweise alle Funktionen am Anfang erstellen und dann später nur noch aufrufen?
Aber Vielleicht kannst Du mir ja noch einen Hinweis zum CustomObject geben: wofür ist der PSTypeName?
Deiner Frage nach zu urteilen: Für nichts 🤣.Da du diese Spalte bei dir im Code so definiert hattest, habe ich sie übernommen. Ich habe ja extra oben gefragt, ob die in jeder Zeile den gleichen Inhalt haben soll.
Wenn du diese Spalte also nicht brauchst, lass sie einfach weg.