Aktive AD PC scannen
Hallo liebe Powersehell Gemeinde. Ich habe einen Weg ausgearbeitet um in meiner Domäne aktive PC zu scanen. Gibt es eine Möglichkeit diese noch zu beschleunigen? Was ich bisher habe:
lg und schönes Wochenende
casi
$Computers = Get-ADComputer -Filter {Name -like 'A*' -or Name -like 'N*'}
$Jobs = @()
foreach ($Computer in $Computers) {
if ($Computer.Name -ne $null -and $Computer.Name -ne '') {
$Jobs += Start-Job -ScriptBlock {
param($Computer)
if (Test-Connection -ComputerName $Computer.Name -Count 1 -Quiet) {
$Computer.Name } } -ArgumentList $Computer } else {}}
$Results = $Jobs | ForEach-Object {$_ | Wait-Job | Receive-Job}
$OnlineComputers = $Results | Where-Object { $_ -ne $null }
$OutputFilePath = "$PSScriptRoot\computers.txt"
if ($OnlineComputers) {$OnlineComputers | Out-File -FilePath $OutputFilePath -Force} else {}
lg und schönes Wochenende
casi
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 31024645931
Url: https://administrator.de/forum/aktive-ad-pc-scannen-31024645931.html
Ausgedruckt am: 22.12.2024 um 10:12 Uhr
14 Kommentare
Neuester Kommentar
Ansatz Host Alive Scan:
Parallel Execution als Job mit.
Variable mit $using:xyz an die neuen Sub-Jobs übergeben. Bei MS findest du Bsp. zu -Parallel und den Script Blöcken. Kann auch mehr als einen geben. Auch wie man $begin und $end dann ausklammert.
Ist aber hier nicht nötig. PS 7 unter Windows und Linux.
Function TestTCP { Param($address, $port, $timeout=2000)
$socket=New-Object System.Net.Sockets.TcpClient
try {
$result=$socket.BeginConnect($address, $port, $NULL, $NULL)
if (!$result.AsyncWaitHandle.WaitOne($timeout, $False)) {
throw [System.Exception]::new('Connection Timeout')
}
$socket.EndConnect($result) | Out-Null
$socket.Connected
}
finally {
$socket.Close()
}
}
Parallel Execution als Job mit.
Variable mit $using:xyz an die neuen Sub-Jobs übergeben. Bei MS findest du Bsp. zu -Parallel und den Script Blöcken. Kann auch mehr als einen geben. Auch wie man $begin und $end dann ausklammert.
Ist aber hier nicht nötig. PS 7 unter Windows und Linux.
$localdir="/data/ftp/"
$rsync_job = Get-ChildItem -Path $backupLoc -Filter "*.OK" | ForEach-Object -Parallel {
try {
$dirExists = "$using:localdir$VMname"
} catch {}
} -ThrottleLimit 4 -AsJob
$rsync_job | Wait-Job
$rsync_job.ChildJobs | ForEach-Object { $_ | Select-Object JobStateInfo,Id,PSBeginTime,PSEndTime,Output,Error,Warning,Information,State | Out-File -FilePath "/home/immuftp/jobchild.txt" -Append}
Zitat von @13034433319:
Multi-Threading nutzen und Ping statt Test-Connection:
Per Powershell mehrere IP-Adressen prüfen
Gruß
Multi-Threading nutzen und Ping statt Test-Connection:
Per Powershell mehrere IP-Adressen prüfen
Gruß
Generell zu den guten alten Commands unter Windows und Linux:
$LastExitCode
Der ist bei fehlerfreien Aufruf 0. Bei rsync unter Linux und z.B. durch immutable Flag gesetzten Schreibschutz wäre er 23.
"Successfully finished" <- man kann so auch zwar Rückgabewerte analysieren aber $LastExitCode ist da schneller und eindeutiger.
ping LastAdministrator.de
$LastExitCode
Ping-Anforderung konnte Host "LastAdministrator.de" nicht finden. Überprüfen Sie den Namen, und versuchen Sie es erneut.
1
0 Ping ok, 1 nicht OK.
Falls es mal Probleme mit der Success-Bestimmung gibt. Bei Ping geht es auch so und kürzer. Bei anderen Commands bekommt so komplettes Error Handling hin.
$socket.EndConnect($result) | Out-Null
$socket.Connected
Da hat aber einer bei der Reihenfolge geschlampt 😁$socket.Connected
Das Ding macht ja auch nix außer als eine Variable zuzuweisen . Link oben lesen hilft, da stehts ja auf dem Silbertablett ...
Zitat von @13034433319:
Das Ding macht ja auch nix außer als eine Variable zuzuweisen . Link oben lesen hilft, da stehts ja auf dem Silbertablett ...
Das Ding macht ja auch nix außer als eine Variable zuzuweisen . Link oben lesen hilft, da stehts ja auf dem Silbertablett ...
Was soll es auch sonst tuen? Nur ein Snippet.
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell ...
In deinen Link mündet es ja auch in ForEach-Object -Parallel
In einem "Workflow" funktioniert das aber auch mit der Powershell 5 im Gegensatz zum nativen foreach-object -parallel das es erst ab PS 7 gibt.
Mit PS7 ist ja auch kein Hexenwerk, da dem TO offensichtlich die Interpretationsgabe fehlt hier ein Beispiel:
Mit PS7 ist ja auch kein Hexenwerk, da dem TO offensichtlich die Interpretationsgabe fehlt hier ein Beispiel:
Get-ADComputer -Filter {Name -like 'A*' -or Name -like 'N*'} | foreach-object -ThrottleLimit 10 -Parallel {
[pscustomobject]@{
Hostname = $_.DNSHostName
Online = [System.Net.Networkinformation.Ping]::new().Send($_.DNSHostName,200).Status -eq 'Success'
}
} | ? Online | Select-object -ExpandProperty Hostname | set-content .\online.txt
Zitat von @13034433319:
Mit PS7 ist ja auch kein Hexenwerk, da dem TO offensichtlich die Interpretationsgabe fehlt hier ein Beispiel:
Mit PS7 ist ja auch kein Hexenwerk, da dem TO offensichtlich die Interpretationsgabe fehlt hier ein Beispiel:
Alles gut. Dachte ich kürz es ab und werfe nur -Parallel in den Raum und es macht klick
Hab für meine Scripte auch mal länger gebraucht. In ISE und VScode braucht es irgendwie Job-Wait nicht. Über die pwsh bin ich dann auf die Schnautze geflogen. Immer ging 1 Objekt verloren oder nach Anpassungen sogar mehrere. War echt unschön, zumal es im Studio sauber lief.
PowerShell parallel Script Block schluckt erstes Objekt
Ja aber du hast schon recht. Hier hinterfragen die Leute teils zu wenig. Man könnte ja auch was "böses" in den Code schreiben....
Moin,
dann geb ich auch mal meinen Senf hierzu ab. Aus einem Script, das eine WoL-Seite erstellt, angepasst um in eine computers.txt auszugeben:
Nutzt SendPingAsync um auch in PS5 parallel zu arbeiten.
dann geb ich auch mal meinen Senf hierzu ab. Aus einem Script, das eine WoL-Seite erstellt, angepasst um in eine computers.txt auszugeben:
$hosts = Get-ADComputer -Filter {Name -like 'A*' -or Name -like 'N*'} | Select-Object -ExpandProperty DNSHostName
$OutputFilePath = "$PSScriptRoot\computers.txt"
# ping all in parallel, hostname = index
$tasks = @{}
foreach ($h in $hosts) { $tasks[$h] = [System.Net.NetworkInformation.Ping]::new().SendPingAsync($h) }
# wait for all pings to complete
[Threading.Tasks.Task]::WaitAll()
# only need hostname and online/offline
$pingresult = foreach ($h in $hosts) {
$res = $tasks[$h].Result
[PSCustomObject]@{
Online = $res.Status -eq "Success"
Hostname = $h
}
}
# write online host names to file
$pingresult | Where-Object Online -eq $true | Select-Object -ExpandProperty HostName | Out-File $OutputFilePath -Force
Nutzt SendPingAsync um auch in PS5 parallel zu arbeiten.
VBS Script benutzen
Mach eine Datei script.vbs (txt File mit .vbs dateiendung statt .txt)
dieses VBS Startet dein ps1, wartet aber nicht auf die beendigung und läuft hidden im hintergrund.
Wenn man das beim Loginscript so einbaut, muss der user nicht warten bis das loginscript durchgelaufen ist.
Das VBS Script startest du in ner .bat datei:
und für den output wo du die daten speichern willst erstellst du ein Share auf nem Fileserver.
Machst aber spezielle optionen, und zwar authenticated users bekommen spezial right,
nämlich write, aber KEIN read somit kann keiner die dateien listen.
Admins berechtigst du normal mir Read/Write usw...
Dann sammeln die clients immer beim login ihre daten.
Wenn du willst schreibst du das file auch gleich mit Datum in Dateinamen, und schon siehst du wann sich der PC das letzte mal angemeldet hat. ggf. kann man dann so leichen filtern.
ich hab sowas deutlich komplexer gemacht und am ende jeden abend in SQL eingelesen die Daten.
dann war das hantieren und sortieren deutlich einfacher unter SQL.
Mach eine Datei script.vbs (txt File mit .vbs dateiendung statt .txt)
On Error Resume Next
SetLocale("de-de")
Set objShell = WScript.CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
sSystemRoot = objShell.ExpandEnvironmentStrings("%SystemRoot%")
CommandLine = """" & sSystemRoot & "\System32\WindowsPowerShell\v1.0\powershell.exe" & """" & " -executionpolicy Unrestricted -File " & """" & "C:\test3543.ps1" & """"
'wscript.echo CommandLine
objShell.run(CommandLine),0,false
dieses VBS Startet dein ps1, wartet aber nicht auf die beendigung und läuft hidden im hintergrund.
Wenn man das beim Loginscript so einbaut, muss der user nicht warten bis das loginscript durchgelaufen ist.
Das VBS Script startest du in ner .bat datei:
cscript.exe "\\Servername\Share\script.vbs"
und für den output wo du die daten speichern willst erstellst du ein Share auf nem Fileserver.
Machst aber spezielle optionen, und zwar authenticated users bekommen spezial right,
nämlich write, aber KEIN read somit kann keiner die dateien listen.
Admins berechtigst du normal mir Read/Write usw...
Dann sammeln die clients immer beim login ihre daten.
Wenn du willst schreibst du das file auch gleich mit Datum in Dateinamen, und schon siehst du wann sich der PC das letzte mal angemeldet hat. ggf. kann man dann so leichen filtern.
ich hab sowas deutlich komplexer gemacht und am ende jeden abend in SQL eingelesen die Daten.
dann war das hantieren und sortieren deutlich einfacher unter SQL.
Wozu? Zum normalne Starten OK - damit das Fenster verschleiert wird.
Wenn es eh daten sammenln soll warum dann nicht gleich als geplanter Task? Auch da ist es möglich Dateien wegzuschreiben ....
@ThePinky777 Du bist im falschen Thread ...