casi4711
Goto Top

CSV aus PS generiert enthält komische Zeichen

Hallo allerseits, ich habe ein Problem mit den Umlauten, es soll ein CSV generiert werden mit IP Daten, und ich habe trotz Verwendung von UTF8 kyyptische Zeichen da wo Umlaute stehen. Wie kann ic hda Abhilfe schafen. Folgendes Scipt:

$CSVFilePath = "\\dom...\inv2\Summary_Short.csv"  
$ComputersA = Get-ADComputer -Filter "Name -like 'A*'"  
$ComputersN = Get-ADComputer -Filter "Name -like 'N*'"  
$Computers = $ComputersA + $ComputersN

function ping2 {
    param(
        [Parameter(Mandatory = $true)]
        [array]$Computers,
        [int]$TimeOut = 800
    )
    $Tasks = [System.Collections.Generic.List[Object]]::new()
    foreach ($address in $Computers) {
        $Tasks.Add([pscustomobject]@{
            PC = $address.Name
            Timestamp = [DateTimeOffset]::Now.ToUnixTimeMilliseconds()
            pingTask = [System.Net.NetworkInformation.Ping]::new().SendPingAsync($address.Name, $TimeOut)
        })
    }
    $Results = foreach ($Task in $Tasks) {
        try {
            $Task.pingTask.Wait()
            $Status = $Task.pingTask.Result.Status
            $IPAddress = if ($Task.pingTask.Result.Address) { $Task.pingTask.Result.Address.IPAddressToString } else { "N/A" }  
            $Latency = $Task.pingTask.Result.RoundTripTime
            $Bytes = if ($Task.pingTask.Result.Buffer) { $Task.pingTask.Result.Buffer.Length } else { 0 }
        } catch {
            $Status = "Error"  
            $IPAddress = "N/A"  
            $Latency = 0
            $Bytes = 0
        }
        [pscustomobject]@{
            Timestamp = $Task.Timestamp
            PC = $Task.PC
            Status = $Status
            IPAddress = $IPAddress
            Latency = $Latency
            Bytes = $Bytes
        }
    }
    return $Results
}

function Get-ARPTable {
    $arpTable = @{}
    $arpOutput = arp -a
    $arpOutput | ForEach-Object {
        if ($_ -match '^\s*([0-9\.]+)\s+([0-9a-f\-]+)\s+.*$') {  
            $arpTable[$matches[1]] = $matches[2]
        }
    }
    return $arpTable
}

$PingResults = ping2 -Computers $Computers
$arpTable = Get-ARPTable
$csvData = Import-Csv -Path $CSVFilePath -Delimiter ";" -Encoding UTF8  
$PingResults | ForEach-Object {
    $description = $null
    $macAddress = $null
    foreach ($item in $csvData) {
        if ($item.Hostname -eq $_.PC) {
            $description = $item.Beschreibung
            break
        }
    }
    if ($_.IPAddress -ne "N/A" -and $_.IPAddress -ne "0.0.0.0" -and $arpTable.ContainsKey($_.IPAddress)) {  
        $macAddress = $arpTable[$_.IPAddress]
    }
    $_ | Add-Member -NotePropertyName "Description" -NotePropertyValue $description  
    $_ | Add-Member -NotePropertyName "MACAddress" -NotePropertyValue $macAddress  
}
$PingResultsFiltered = $PingResults | Where-Object { $_.IPAddress -ne "N/A" -and $_.IPAddress -ne "0.0.0.0" }  
$tempFilePath = "C:\Windows\Temp\Computers.csv"  
$PingResultsFiltered | Select-Object PC, Status, IPAddress, MACAddress, Description | Export-Csv -Path $tempFilePath -Delimiter ";" -NoTypeInformation -Encoding UTF8  

vielen liebe Dank i.V.

lg

Content-ID: 41275106009

Url: https://administrator.de/forum/csv-aus-ps-generiert-enthaelt-komische-zeichen-41275106009.html

Ausgedruckt am: 27.12.2024 um 01:12 Uhr

13034433319
13034433319 19.06.2024 aktualisiert um 11:49:33 Uhr
Goto Top
Thema kommt hier immer wieder mal. Skript unter Windows selbst als UTF-8 mit BOM (Byte Order Mark) speichern, dann klappts auch mit den Umlauten zuverlässig.
Powershell System.Xml.XmlDocument Umlaute
Powershell Variable wird mit falschem Encoding ausgegeben
Powershell, PS2EXE Umlaute falsch angezeigt

$arpOutput = arp -a
Des weiteren führst du hier einen Dos Befehl aus, deren Output ist per Default Codepage 850, diesen output musst du erst konvertieren. Ist hier aber jetzt nicht relevant da du nur die MAC daraus verwendest wo keine Umlaute vorkommen können
function Convert-CP850([string[]]$string){
    $cp850 = [System.Text.Encoding]::GetEncoding(850)
    $string | %{$cp850.GetString([System.Console]::OutputEncoding.GetBytes($_))}
}
$arpOutput = Convert-CP850 (arp -a)
Gruß
casi4711
casi4711 19.06.2024 um 14:04:27 Uhr
Goto Top
Super lieben Dank erstmal, habe das script mit norepad + unter utf mit BOM gespeichert habe aber immer noch zB statt ö diese kleinen Fragezeichen, ich habe noch 16 BE BOM und 16 LE BOM wär das besser?


lg
13034433319
Lösung 13034433319 19.06.2024 aktualisiert um 14:26:24 Uhr
Goto Top
Zitat von @casi4711:
Super lieben Dank erstmal, habe das script mit norepad +
norepad? 🙃
unter utf mit BOM gespeichert habe aber immer noch zB statt ö diese kleinen Fragezeichen,
Wo?
Dann ist deine Quell-CSV wohl schon kein echtes UTF8 sondern bspw. ANSI, dies dann beim Import mittels "Default" Encoding angeben
$csvData = Import-Csv -Path $CSVFilePath -Delimiter ";" -Encoding Default  
ich habe noch 16 BE BOM und 16 LE BOM wär das besser?
Macht für Umlaute keinen Unterschied.
casi4711
casi4711 19.06.2024 um 14:31:00 Uhr
Goto Top
ich meinte natürlich Notepad++, habe jetzt Default gemacht, jetzt hab ich nicht diese kleinen Romben Fragezeichen sondern richtige Fragezeichen;)
13034433319
13034433319 19.06.2024 aktualisiert um 15:08:57 Uhr
Goto Top
Dann die Datei wohl doch noch ein anderes Encoding ... Ermittle es gib es an oder konvertiere die Datei und dann lüppt das auch.
casi4711
casi4711 19.06.2024 um 15:29:15 Uhr
Goto Top
die Dtaei kommt jan icht vom Himmel sie wird doch vom PowershellScript selber erzeugt, ok versuch mal zu konvertieren
casi4711
casi4711 19.06.2024 um 15:32:19 Uhr
Goto Top
oh man war mein fehler hatte es beim Export gemacht, ging ja um die Importdatei, jetzt lüpt es danke Euch noch mal

und eine schöne Restwoche
casi4711
casi4711 20.06.2024 um 13:31:21 Uhr
Goto Top
Aber mal noch mal zu meinem Script generell, ich versuche mit diesem Script die Rechner in der Domöne zu filtern die wirklih online sind. Ich habe michfür ARP Ping Methode entschieden da manche Geräte (ohne ICMP) nicht zu finden sinst sonst. Leider gibt es auf dem DNS zahlreiche gleiche IPS für verschiedene PC die natürlich längst nicht mehr aktiv sind. Ich habe dann versucht nur die neuesten zu nehmen, aber auch da kann es passieren dass man Rechner gelistet bekommt die schon lange nicht mehr aktiv sind, weil nur noch eine IP in der ARP Liste war. Wie könnte ich mein Script entsprechend apassen, dass mir nur die Rechenr Angezeigt weren die wirklich aktiv sind, es sollte natürlich auch nicht allzuewig brauchen. Hat jemand ne Idee?

$CSVFilePath = "\\do.de.......\inv2\Summary_Short.csv"  
$ComputersA = Get-ADComputer -Filter "Name -like 'A*'"  
$ComputersN = Get-ADComputer -Filter "Name -like 'N*'"  
$Computers = $ComputersA + $ComputersN

function ping2 {
    param(
        [Parameter(Mandatory = $true)]
        [array]$Computers,
        [int]$TimeOut = 800
    )

    $Tasks = [System.Collections.Generic.List[Object]]::new()

    foreach ($address in $Computers) {
        $Tasks.Add([pscustomobject]@{
            PC = $address.Name
            Timestamp = [DateTimeOffset]::Now.ToUnixTimeMilliseconds()
            pingTask = [System.Net.NetworkInformation.Ping]::new().SendPingAsync($address.Name, $TimeOut)
        })
    }

    $Results = foreach ($Task in $Tasks) {
        try {
            $Task.pingTask.Wait()
            $Status = $Task.pingTask.Result.Status
            $IPAddress = if ($Task.pingTask.Result.Address) { $Task.pingTask.Result.Address.IPAddressToString } else { "N/A" }  
            $Latency = $Task.pingTask.Result.RoundTripTime
            $Bytes = if ($Task.pingTask.Result.Buffer) { $Task.pingTask.Result.Buffer.Length } else { 0 }
        } catch {
            $Status = "Error"  
            $IPAddress = "N/A"  
            $Latency = 0
            $Bytes = 0
        }

        [pscustomobject]@{
            Timestamp = $Task.Timestamp
            PC = $Task.PC
            Status = $Status
            IPAddress = $IPAddress
            Latency = $Latency
            Bytes = $Bytes
        }
    }

    return $Results
}

function Get-ARPTable {
    $arpTable = @{}
    $arpOutput = arp -a
    $arpOutput | ForEach-Object {
        if ($_ -match '^\s*([0-9\.]+)\s+([0-9a-f\-]+)\s+.*$') {  
            $arpTable[$matches[1]] = $matches[2]
        }
    }
    return $arpTable
}

$PingResults = ping2 -Computers $Computers
$arpTable = Get-ARPTable
$csvData = Import-Csv -Path $CSVFilePath -Delimiter ";" -Encoding Default  

$PingResults | ForEach-Object {
    $description = $null
    $macAddress = $null

    foreach ($item in $csvData) {
        if ($item.Hostname -eq $_.PC) {
            $description = $item.Beschreibung
            break
        }
    }

    if ($_.IPAddress -ne "N/A" -and $_.IPAddress -ne "0.0.0.0" -and $arpTable.ContainsKey($_.IPAddress)) {  
        $macAddress = $arpTable[$_.IPAddress]
    }

    $_ | Add-Member -NotePropertyName "Description" -NotePropertyValue $description  
    $_ | Add-Member -NotePropertyName "MACAddress" -NotePropertyValue $macAddress  
}

# Sortieren, um die neuesten Einträge zuerst zu haben
$PingResultsSorted = $PingResults | Where-Object { $_.IPAddress -ne "N/A" -and $_.IPAddress -ne "0.0.0.0" } | Sort-Object IPAddress, Timestamp -Descending  

# Gruppieren nach IP-Adresse und nur den neuesten Eintrag behalten
$PingResultsFiltered = $PingResultsSorted | Group-Object IPAddress | ForEach-Object { $_.Group | Select-Object -First 1 }

# Die mehrfachen Einträge erfassen
$DuplicateIPs = $PingResultsSorted | Group-Object IPAddress | Where-Object { $_.Count -gt 1 } | ForEach-Object { $_.Group | Select-Object -Skip 1 }

# Dateien speichern
$tempFilePath = "C:\Windows\Temp\Computers.csv"  
$duplicateFilePath = "C:\Windows\Temp\DuplicateComputers.csv"  

$PingResultsFiltered | Select-Object Timestamp, PC, Status, IPAddress, MACAddress, Description | Export-Csv -Path $tempFilePath -Delimiter ";" -NoTypeInformation -Encoding UTF8  
$DuplicateIPs | Select-Object Timestamp, PC, Status, IPAddress, MACAddress, Description | Export-Csv -Path $duplicateFilePath -Delimiter ";" -NoTypeInformation -Encoding UTF8  

Lg und einen schönen Abend
13034433319
13034433319 20.06.2024 aktualisiert um 14:38:29 Uhr
Goto Top
$computers = Get-ADComputer -Filter "Name -like 'A*' -or Name -like 'N*'"  
$tasks = foreach($computer in $computers){
    [pscustomobject]@{
        Name = $computer.Name
        Task = [System.Net.NetworkInformation.Ping]::new().SendPingAsync($computer.Name,800,[byte[]]0)
    }
}
[System.Threading.Tasks.Task]::WaitAll($tasks.Task)
$result = $tasks | ?{$_.Task.Result.Status -eq 'Success'} | Select Name,@{n='Address';e={$_.Task.Result.Address}},@{n='Result';e={"Online"}}  
$result
casi4711
casi4711 20.06.2024 aktualisiert um 14:32:23 Uhr
Goto Top
Danke erst mal, haut aber noch nicht so ganz hin, der F ehler:

Ausnahme beim Aufrufen von "SendPingAsync" mit 3 Argument(en): "Der Wert darf nicht NULL sein.
Parametername: address"
In C:\Users\Riegert\Desktop\neu\ActivePCuNFor.PS1:3 Zeichen:5

back-to-top[pscustomobject]@{

back-to-top~~~~~~~~~~~~~~~~~~

+ CategoryInfo : NotSpecified: (face-smile [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentNullException


wie man sieht sind immer noch doppelte IP vorhanden

Timestamp PC Status IPAddress MACAddress
1718885922190 N181114 Success 192.168.100.102 84-3a-5b-57-e1-98
1718885922188 N181129 Success 192.168.100.102 84-3a-5b-57-e1-98

lg
13034433319
13034433319 20.06.2024 aktualisiert um 14:25:38 Uhr
Goto Top
Haben deine Rechner keine FQDNs? Habe die Property mal explizit hinzugefügt, aber normalerweise ist die beim Default Output von Get-ADComputer immer mit dabei. Ansonsten halt mit Name pingen, ist aber nicht so schön.
casi4711
casi4711 20.06.2024 um 14:33:33 Uhr
Goto Top
klar habe sie eine FQDN die heissen dann so A10000.dom.xxx-xxx.de
13034433319
13034433319 20.06.2024 aktualisiert um 14:39:01 Uhr
Goto Top
Klappt hier einwandfrei ...

wie man sieht sind immer noch doppelte IP vorhanden
Timestamp PC Status IPAddress MACAddress
1718885922190 N181114 Success 192.168.100.102 84-3a-5b-57-e1-98
1718885922188 N181129 Success 192.168.100.102 84-3a-5b-57-e1-98
Das ist dein Skript nicht meins.

Meins gibt nur die Rechner aus die Online sind.
casi4711
casi4711 20.06.2024 um 15:25:07 Uhr
Goto Top
Das ist ja komisch, also ja es sind auf jeden Fall schon weniger Rechner die angezeigt werden,, wahrscheinlich sind die verbleibenden tatsächlich doppelt vergeben, oder zumindest vertauscht.
casi4711
casi4711 20.06.2024 um 15:41:17 Uhr
Goto Top
ne so komm ich nich weiter habe mindestens noch 3 gleiche IP drinface-sad
casi4711
casi4711 20.06.2024 um 16:27:55 Uhr
Goto Top
meine Idee war bei mehrfachen IPs auf dem DNS Server den Zeitstempel zu analysieren und nur den im result zu belassen der am aktuellsten ist, aber das kalppt irgendwie auch nicht