casi4711
Goto Top

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:

$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

Content-ID: 31024645931

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

Ausgedruckt am: 21.11.2024 um 13:11 Uhr

13034433319
13034433319 25.05.2024 um 14:06:48 Uhr
Goto Top
Multi-Threading nutzen und Ping statt Test-Connection:

Per Powershell mehrere IP-Adressen prüfen

Gruß
Crusher79
Crusher79 25.05.2024 um 14:42:54 Uhr
Goto Top
Ansatz Host Alive Scan:

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}  
Crusher79
Crusher79 25.05.2024 aktualisiert um 14:56:28 Uhr
Goto Top
Zitat von @13034433319:

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.
13034433319
13034433319 25.05.2024 um 15:36:49 Uhr
Goto Top
$socket.EndConnect($result) | Out-Null
$socket.Connected
Da hat aber einer bei der Reihenfolge geschlampt 😁
casi4711
casi4711 25.05.2024 aktualisiert um 17:41:35 Uhr
Goto Top
Danke erst mal, aber es sieht irgendwie nicht so aus als ob etwas passiert, ich erhalte zumindestr keine txt mit den entsprechenden Rechnernamen, habe mir erlaubt den linuxPfad anzupassen:

Ich sehe auch keinerlei Ping Anweisung, wahrscheinlich haben wir aneinadervorbeigeredet. Mein Script macht bislang ja folgendes, es holt vom AD sämtliche Rechner die es gibt (mit Filter) und testet dann ob die Rechner vorhanden sind

$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 "jobchild.txt" -Append}    

lg und schönes we noch
13034433319
13034433319 25.05.2024 aktualisiert um 18:20:04 Uhr
Goto Top
Das Ding macht ja auch nix außer als eine Variable zuzuweisen face-big-smile. Link oben lesen hilft, da stehts ja auf dem Silbertablett ...
Crusher79
Crusher79 25.05.2024 um 18:59:39 Uhr
Goto Top
Zitat von @13034433319:

Das Ding macht ja auch nix außer als eine Variable zuzuweisen face-big-smile. 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 face-wink
13034433319
13034433319 25.05.2024 aktualisiert um 19:50:58 Uhr
Goto Top
Zitat von @Crusher79:
In deinen Link mündet es ja auch in ForEach-Object -Parallel face-wink
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:
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
Crusher79
Crusher79 25.05.2024 um 21:55:54 Uhr
Goto Top
Zitat von @13034433319:

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 face-big-smile

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....
casi4711
casi4711 26.05.2024 um 02:25:56 Uhr
Goto Top
sorry hatte ich nicht gesehen, das das nur nen allgemeiner Workflow ist, hinterfragt habe ich das ganze jedoch schon, ich sagte ja dass hier kein Ping drin war;)

Na dann schau ich mal dass ich meinen Code da einbaue, bin ich mal gespannt


lg und schönen Sonntag
CamelCase
CamelCase 26.05.2024 aktualisiert um 07:29:44 Uhr
Goto Top
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:

$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.
ThePinky777
ThePinky777 28.05.2024 aktualisiert um 17:48:06 Uhr
Goto Top
VBS Script benutzen face-smile

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 face-smile 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.
Crusher79
Crusher79 28.05.2024 um 17:58:10 Uhr
Goto Top
Zitat von @ThePinky777:

VBS Script benutzen face-smile

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 ....
13034433319
13034433319 28.05.2024 aktualisiert um 18:02:59 Uhr
Goto Top
@ThePinky777 Du bist im falschen Thread ...