andy645934
Goto Top

Batch Script, Rechner anpingen und sortieren inklusive IP Adresse

Hallo Forum,

ich habe ein kleines Problem und bräuchte Eure Hilfe:

Ich würde gerne eine Rechner Liste, die in einem Text File vorliegt, mit einem Batch Script pingen.
Die Rechner, die ein- bzw. ausgeschaltet sind, sollten dann in einem jeweils separaten, Text File ausgegeben werden.
Natürlich mit dem Hinweis, ob der Rechner gerade läuft oder auch nicht.

ich habe eine "clients.txt", in der untereinander die Rechnernamen eingetragen sind.

Mit folgenen Script Befehlen habe ich es hinbekommen, dass zwei Text Files erzeugt werden:

@echo off

set host=clients.txt

for /f %%i in (%host%) do (ping -n 1 %%i | find "Antwort" > nul) && (@echo %%i = online>>pingergebnis_online.txt) || (@echo %%i = offline>>pingergebnis_offline.txt)  



Und zwar die Files "pingergebnis_online.txt" und "pingergebnis_offline.txt".
Die Formatierung sieht dann folgendermaßen aus:

Im File "pingergebnis_online.txt":
Rechnername = online

Im File "pingergebnis_offline.txt":
Rechnername = offline

Jetzt zu meiner Frage:
Ich würde gerne, zusätzlich zu den vorhandenen Informationen, die IP Adresse und evtl. auch die MAC Adresse mit ausgeben.
Die Formatierung sollte dann in etwa so aussehen:

Rechnername = online / IP Adresse / Mac Adresse.
oder eben auch
Rechnername = offline / IP Adresse / Mac Adresse.

Wie kann ich das denn realisieren bzw. wie muss ich die Befehlszeile abändern? Ich komme nicht weiter und würde mich über jede Hilfe von Euch wirklich freuen.

Viele Grüße und schon mal Danke!
Andy

Content-Key: 652509

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

Printed on: April 26, 2024 at 08:04 o'clock

Mitglied: 147448
147448 Feb 15, 2021 at 17:33:09 (UTC)
Goto Top
Nmap nutzen gibts auch für Windows

Ausgabe erfolgt dann im Batch !

Nmap xxx.xxx.xxx.xxx/nm > PC-Liste.txt
Member: Doskias
Doskias Feb 16, 2021 at 06:41:27 (UTC)
Goto Top
Moin,

in meinen Augen alles kein Problem, aber wieso mit Batch? Ich persönlich würde Powershell nutzen. Aus folgenden Gründen:

Der Befehl test-connection -quiet gibt die bei erfolgreichen Ping True, bei fehlgeschlagenem Ping false zurück. Das kannst du abfangen und dann entsprechen trennen in welche Datei es umgeleitet werden soll. Die IP zu dem Rechnernamen zu ermitteln ist ebenfalls kein Problem, aber bei der MAC-Adresse ist es schwierig. Wie soll ein Befehl von einem ausgeschalteten Gerät die physische Adresse bekommen. Die ist (lasse mich gerne korrigieren) in deiner Konstellation lediglich in deinem DHCP Server gespeichert, Klar online Geräte kannst du direkt abfragen aber bei Offline-Geräten musst du den DHCP kontaktieren und diese dort auslesen. Und da bin ich ehrlich, keine Ahnung wie das per Batch geht. Mit Powershell kein Problem.

Und mit den Infos die ich dir hier geschrieben habe und der Suche von Mr. Google solltest du eine Lösung erarbeiten können.

Gruß
Doskias
Member: chkdsk
Solution chkdsk Feb 16, 2021 updated at 07:04:33 (UTC)
Goto Top
Probiere mal folgendes. Geht bestimmt auch mit weniger Zeilen face-smile ich hatte eine ähnliche Anforderung vor einer ganzen Weile mal selbst und habe mein Skript nochmal rausgekramt.

Function scan-range
{
	[CmdletBinding(
		SupportsShouldProcess=$True,
		ConfirmImpact="Low"   
	)]	
	param(
		[parameter(Mandatory=$true)]
		[System.Net.IPAddress]$StartScanIP,
		[System.Net.IPAddress]$EndScanIP,
		[Int]$MaxJobs = 20,
		[Int[]]$Ports,
		[Switch]$ShowAll,
		[Switch]$ShowInstantly,
		[Int]$SleepTime = 5,
		[Int]$TimeOut = 90
	)



	Begin{}

	Process
	{
		if ($pscmdlet.ShouldProcess("$StartScanIP $EndScanIP" ,"Scan IP range for active machines"))  
		{
			if(Get-Job -name *.*.*.*)
			{
				Write-Verbose "Removing old jobs."  
				Get-Job -name *.*.*.* | Remove-Job -Force
			}
			
			$ScanIPRange = @()
			if($EndScanIP -ne $null)
			{
				Write-Verbose "Generating IP range list."  
				# Many thanks to Dr. Tobias Weltner, MVP PowerShell and Grant Ward for IP range generator
				$StartIP = $StartScanIP -split '\.'  
	  			[Array]::Reverse($StartIP)  
	  			$StartIP = ([System.Net.IPAddress]($StartIP -join '.')).Address   
				
				$EndIP = $EndScanIP -split '\.'  
	  			[Array]::Reverse($EndIP)  
	  			$EndIP = ([System.Net.IPAddress]($EndIP -join '.')).Address   
				
				For ($x=$StartIP; $x -le $EndIP; $x++) {    
					$IP = [System.Net.IPAddress]$x -split '\.'  
					[Array]::Reverse($IP)   
					$ScanIPRange += $IP -join '.'   
				}
			
			}
			else
			{
				$ScanIPRange = $StartScanIP
			}

			Write-Verbose "Creating own list class."  
			$Class = @"  
			public class SubNetItem {
				public bool Active;
				public string Host;
				public System.Net.IPAddress IP;
				public string MAC;
				public System.Object Ports;
				public string OS_Name;
				public string OS_Ver;
				public bool WMI;
				public bool WinRM;
			}
"@		  

			Write-Verbose "Start scaning..."	  
			$ScanResult = @()
			$ScanCount = 0
			Write-Progress -Activity "Scan IP Range $StartScanIP $EndScanIP" -Status "Scaning:" -Percentcomplete (0)  
			Foreach($IP in $ScanIPRange)
			{
	 			Write-Verbose "Starting job ($((Get-Job -name *.*.*.* | Measure-Object).Count+1)/$MaxJobs) for $IP."  
				Start-Job -Name $IP -ArgumentList $IP,$Ports,$Class -ScriptBlock{ 
				
					param
					(
					[System.Net.IPAddress]$IP = $IP,
					[Int[]]$Ports = $Ports,
					$Class = $Class 
					)
					
					Add-Type -TypeDefinition $Class
					
					if(Test-Connection -ComputerName $IP -Quiet)
					{
						#Get Hostname
						Try
						{
							$HostName = [System.Net.Dns]::GetHostbyAddress($IP).HostName
						}
						Catch
						{
							$HostName = $null
						}
						
						#Get WMI Access, OS Name and version via WMI
						Try
						{
							#I don't use Get-WMIObject because it havent TimeOut options.  
							$WMIObj = [WMISearcher]''    
							$WMIObj.options.timeout = '0:0:10'   
							$WMIObj.scope.path = "\\$IP\root\cimv2"    
							$WMIObj.query = "SELECT * FROM Win32_OperatingSystem"    
							$Result = $WMIObj.get()  

							if($Result -ne $null)
							{
								$OS_Name = $Result | Select-Object -ExpandProperty Caption
								$OS_Ver = $Result | Select-Object -ExpandProperty Version
								$OS_CSDVer = $Result | Select-Object -ExpandProperty CSDVersion
								$OS_Ver += " $OS_CSDVer"  
								$WMIAccess = $true					
							}
							else
							{
								$WMIAccess = $false	
							}
						}	
						catch
						{
							$WMIAccess = $false					
						}
						
						#Get WinRM Access, OS Name and version via WinRM
						if($HostName)
						{
							$Result = Invoke-Command -ComputerName $HostName -ScriptBlock {systeminfo} -ErrorAction SilentlyContinue 
						}
						else
						{
							$Result = Invoke-Command -ComputerName $IP -ScriptBlock {systeminfo} -ErrorAction SilentlyContinue 
						}
						
						if($Result -ne $null)
						{
							if($OS_Name -eq $null)
							{
								$OS_Name = ($Result[2..3] -split ":\s+")[1]  
								$OS_Ver = ($Result[2..3] -split ":\s+")[3]  
							}	
							$WinRMAccess = $true
						}
						else
						{
							$WinRMAccess = $false
						}
						
						#Get MAC Address
						Try
						{
							$result= nbtstat -A $IP | select-string "MAC"  
							$MAC = [string]([Regex]::Matches($result, "([0-9A-F][0-9A-F]-){5}([0-9A-F][0-9A-F])"))  
						}
						Catch
						{
							$MAC = $null
						}
						
						#Get ports status
						$PortsStatus = @()
						ForEach($Port in $Ports)
						{
							Try
							{							
								$TCPClient = new-object Net.Sockets.TcpClient
								$TCPClient.Connect($IP, $Port)
								$TCPClient.Close()
								
								$PortStatus = New-Object PSObject -Property @{            
		        					Port		= $Port
									Status      = $true
								}
								$PortsStatus += $PortStatus
							}	
							Catch
							{
								$PortStatus = New-Object PSObject -Property @{            
		        					Port		= $Port
									Status      = $false
								}	
								$PortsStatus += $PortStatus
							}
						}

						
						$HostObj = New-Object SubNetItem -Property @{            
		        					Active		= $true
									Host        = $HostName
									IP          = $IP 
									MAC         = $MAC
									Ports       = $PortsStatus
		        					OS_Name     = $OS_Name
									OS_Ver      = $OS_Ver               
		        					WMI         = $WMIAccess      
		        					WinRM       = $WinRMAccess      
		        		}
						$HostObj
					}
					else
					{
						$HostObj = New-Object SubNetItem -Property @{            
		        					Active		= $false
									Host        = $null
									IP          = $IP  
									MAC         = $null
									Ports       = $null
		        					OS_Name     = $null
									OS_Ver      = $null               
		        					WMI         = $null      
		        					WinRM       = $null      
		        		}
						$HostObj
					}
				} | Out-Null
				$ScanCount++
				Write-Progress -Activity "Scan IP Range $StartScanIP $EndScanIP" -Status "Scaning:" -Percentcomplete ([int](($ScanCount+$ScanResult.Count)/(($ScanIPRange | Measure-Object).Count) * 50))  
				
				do
				{
					Write-Verbose "Trying get part of data."  
					Get-Job -State Completed | Foreach {
						Write-Verbose "Geting job $($_.Name) result."  
						$JobResult = Receive-Job -Id ($_.Id)

						if($ShowAll)
						{
							if($ShowInstantly)
							{
								if($JobResult.Active -eq $true)
								{
									Write-Host "$($JobResult.IP) is active." -ForegroundColor Green  
								}
								else
								{
									Write-Host "$($JobResult.IP) is inactive." -ForegroundColor Red  
								}
							}
							
							$ScanResult += $JobResult	
						}
						else
						{
							if($JobResult.Active -eq $true)
							{
								if($ShowInstantly)
								{
									Write-Host "$($JobResult.IP) is active." -ForegroundColor Green  
								}
								$ScanResult += $JobResult
							}
						}
						Write-Verbose "Removing job $($_.Name)."  
						Remove-Job -Id ($_.Id)
						Write-Progress -Activity "Scan IP Range $StartScanIP $EndScanIP" -Status "Scaning:" -Percentcomplete ([int](($ScanCount+$ScanResult.Count)/(($ScanIPRange | Measure-Object).Count) * 50))  
					}
					
					if((Get-Job -name *.*.*.*).Count -eq $MaxJobs)
					{
						Write-Verbose "Jobs are not completed ($((Get-Job -name *.*.*.* | Measure-Object).Count)/$MaxJobs), please wait..."  
						Sleep $SleepTime
					}
				}
				while((Get-Job -name *.*.*.*).Count -eq $MaxJobs)
			}
			
			$timeOutCounter = 0
			do
			{
				Write-Verbose "Trying get last part of data."  
				Get-Job -State Completed | Foreach {
					Write-Verbose "Geting job $($_.Name) result."  
					$JobResult = Receive-Job -Id ($_.Id)

					if($ShowAll)
					{
						if($ShowInstantly)
						{
							if($JobResult.Active -eq $true)
							{
								Write-Host "$($JobResult.IP) is active." -ForegroundColor Green  
							}
							else
							{
								Write-Host "$($JobResult.IP) is inactive." -ForegroundColor Red  
							}
						}
						
						$ScanResult += $JobResult	
					}
					else
					{
						if($JobResult.Active -eq $true)
						{
							if($ShowInstantly)
							{
								Write-Host "$($JobResult.IP) is active." -ForegroundColor Green  
							}
							$ScanResult += $JobResult
						}
					}
					Write-Verbose "Removing job $($_.Name)."  
					Remove-Job -Id ($_.Id)
					Write-Progress -Activity "Scan IP Range $StartScanIP $EndScanIP" -Status "Scaning:" -Percentcomplete ([int](($ScanCount+$ScanResult.Count)/(($ScanIPRange | Measure-Object).Count) * 50))  
				}
				
				if(Get-Job -name *.*.*.*)
				{
					Write-Verbose "All jobs are not completed ($((Get-Job -name *.*.*.* | Measure-Object).Count)/$MaxJobs), please wait... ($timeOutCounter)"  
					Sleep $SleepTime
					$timeOutCounter += $SleepTime				

					if($timeOutCounter -ge $TimeOut)
					{
						Write-Verbose "Time out... $TimeOut. Can't finish some jobs  ($((Get-Job -name *.*.*.* | Measure-Object).Count)/$MaxJobs) try remove it manualy."  
						Break
					}
				}
			}
			while(Get-Job -name *.*.*.*)
			
			Write-Verbose "Scan finished."  
			Return $ScanResult 
		}
	}
	
	End{}
}

$file = get-content -path "C:\temp\pc.csv"  

foreach($pc in $file) {
$Result = scan-range $pc -ShowInstantly -ShowAll 
$Result | Select-Object IP, Host, MAC
}

In der pc.csv trägst du deine PC Namen ein.
Member: andy645934
andy645934 Feb 17, 2021 updated at 07:42:15 (UTC)
Goto Top
Hey. Danke für Eure schnelle Hilfe.

Powershell ist wahrscheinlich die bessere Lösung. Mit Powershell habe ich noch keine Erfahrung. face-smile
Die Ausgabe der MAC Adresse ist nur optional, falls einfach lösbar.

Das Skript werde ich ausprobieren.. Ich melde mich nochmal.
Member: andy645934
andy645934 Feb 18, 2021 at 11:04:13 (UTC)
Goto Top
@chkdsk: Ich habe Dein Script auf Anhieb nicht zum laufen gebracht. Beim Ausführen tut sich gar nix.


Um nochmal auf folgende Zeile einzugehen:
for /f %%i in (%host%) do (ping -n 1 %%i | find "Antwort" > nul) && (@echo %%i = online>>pingergebnis_online.txt) || (@echo %%i = offline>>pingergebnis_offline.txt)  

Es würde eigentlich schon reichen, wenn anstatt der Rechnername die IP ausgegeben wird.
Geht das? Wenn ja, wie müsste die Zeile dann aussehen?
Member: chkdsk
chkdsk Feb 18, 2021 updated at 11:18:50 (UTC)
Goto Top
Lege dir im Verzeichnis C:\temp eine CSV Datei mit dem Namen pc.csv an, in welcher OHNE HEADER alle PC Namen untereinander stehen.
Starte die Powershell ISE mal als Admin und copy & paste mein Skript da rein. Dann feuer frei.
Evtl musst du Powershell erst aktivieren. Ich würde keine Energie mehr in Batch investieren.
Member: andy645934
andy645934 Feb 19, 2021 at 10:34:03 (UTC)
Goto Top
Hallo Chkdsk,

Sorry für die späte Antwort. Ich habe mich erst ein wenig in Powershell einlesen müssen. face-smile

Das Script funktioniert gut. Genau das was ich brauche. Vielen Dank.
Member: chkdsk
chkdsk Feb 19, 2021 at 10:40:37 (UTC)
Goto Top
Dann bitte noch die passende Antwort als Lösung markieren.