Pikus1234 0 Geschrieben 11. Oktober 2017 Melden Teilen Geschrieben 11. Oktober 2017 Hallo, Ich bin gerade dabei eine umfangreiche Inventory für Hardwareabfragen zu basteln. Jetzt komme ich leider nicht weiter und hoffe auf eure Hilfe. Im Script wird durch eine WMI-Abfrage eben ein Monitor-Array von bis zu 4 Monitoren abgefragt und erstellt. Das läuft auch, sofern der WMI der Remotemaschine läuft und Daten liefert Aber wenn der WMI nicht läuft und keine Daten liefert, bekomme ich entsprechende Fehlermeldungen, welche ich nun abfangen bzw. durch Ersatz auffüllen muss. Wer kann da helfen.... Weitere Fehler sind natürlich durch den nicht erfolgten Zugriff auf die WMI möglich.....viell. habe ich auch einen Denkfehler beim Aufbau drin. Ich bin noch nicht so fit in Powershell, weshalb ich eure Hilfe benötige. $testcomputers = '#Name des Remote-PC' # normal wird hier eine bestimmte txt.Datei eingelesen, welche mir die Namen liefert foreach ($computer in $testcomputers) { if (Test-Connection -ComputerName $computer -Quiet -count 1){ Add-Content -value $computer -Force "$PSScriptRoot\livePCs.txt" }else{ Add-Content -value $computer -Force "$PSScriptRoot\deadPCs.txt" } } $computers = #die PC-Namen aus der Liste "livePCs.txt" oder '#Name des Remote-PC' $Inventory = foreach ($computer in $computers) { $Bios = Get-WmiObject win32_bios -Computername $computer $Hardware = Get-WmiObject Win32_computerSystem -Computername $computer $Sysbuild = Get-WmiObject Win32_WmiSetting -Computername $computer $OS = Get-WmiObject Win32_OperatingSystem -Computername $computer $GUID = Get-wmiobject Win32_ComputerSystemProduct -Computername $computer | Select-Object -ExpandProperty UUID $Networks = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $computer | Where-Object {$_.IPEnabled} $driveSpace = Get-WmiObject win32_volume -Computername $Computer -Filter 'drivetype = 3' | Select-Object PScomputerName, driveletter, label, @{LABEL='GBfreespace';EXPRESSION={'{0:N2}' -f($_.freespace/1GB)} } | Where-Object { $_.driveletter -match 'C:' } $cpu = Get-WmiObject Win32_Processor -Computername $computer $CDROM = Get-WmiObject win32_CDROMDrive -ComputerName $computer $Video = Get-WmiObject Win32_Videocontroller -ComputerName $computer -Filter "NOT name LIKE '%DameWare%'" |Select-Object 'Name*' $username = Get-ChildItem "\\$computer\c$\Users" | Sort-Object LastWriteTime -Descending | Select-Object Name, LastWriteTime -first 1 #hier muss der Fehler abgefangen werden, dass es bei scheitern keine Daten gibt - es muss ersatzdaten geben::::::: [ARRAY]$MonitorList = $null $ MonitorList = $ null [ARRAY]$MonitorList = Get-WmiObject -Class WmiMonitorID -Namespace root\wmi -ComputerName $computer $PrinterHP = Get-WmiObject -Class Win32_Printer -ComputerName $Computer |Where-Object { $_.Local -like 'True' -and $_.Name -like 'HP*'}| Select-Object Name $PrinterSamsung = Get-WmiObject -Class Win32_Printer -ComputerName $Computer |Where-Object { $_.Local -like 'True' -and $_.Name -like 'Samsung*'}| Select-Object Name $PrinterCanon = Get-WmiObject -Class Win32_Printer -ComputerName $Computer |Where-Object { $_.Local -like 'True' -and $_.Name -like 'Canon*'}| Select-Object Name [PSCustomObject]@{ ComputerName = $Computer.ToUpper() Manufacturer = $Hardware.Manufacturer Model = $Hardware.Model Serial_Number = $Bios.serialnumber MAC_Address = $Networks.MACAddress Netboot_GUID = $GUID IP_Address = $Networks.IpAddress[0] Processor_Type = $cpu.Name System_Type = $Hardware.SystemType Total_Memory_GB = [math]::round($Hardware.TotalPhysicalMemory/1024/1024/1024, 2) CDROM_Drive = $CDROM.Caption Graphics = $Video.Name Last_User = $username.Name User_Last_Login = $username.LastWriteTime 'C:_FreeSpace_GB' = $driveSpace.GBfreespace Last_ReBoot = $OS.ConvertToDateTime($OS.LastBootUpTime) Operating_System = $OS.Caption Operating_System_Version = $OS.version Operating_System_BuildVersion = $SysBuild.BuildVersion Monitor1Hersteller = If($MonitorList[0]){($MonitorList[0].ManufacturerName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} Monitor1Typ = If($MonitorList[0]){($MonitorList[0].UserFriendlyName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} Monitor1Seriennummer = If($MonitorList[0]){($MonitorList[0].SerialNumberID -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} Monitor2Hersteller = If($MonitorList[1]){($MonitorList[1].ManufacturerName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} Monitor2Typ = If($MonitorList[1]){($MonitorList[1].UserFriendlyName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} Monitor2Seriennummer = If($MonitorList[1]){($MonitorList[1].SerialNumberID -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} Monitor3Hersteller = If($MonitorList[2]){($MonitorList[2].ManufacturerName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} Monitor3Typ = If($MonitorList[2]){($MonitorList[2].UserFriendlyName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} Monitor3Seriennummer = If($MonitorList[2]){($MonitorList[2].SerialNumberID -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} Drucker_HP = $PrinterHP.Name Drucker_Samsung = $PrinterSamsung.Name Drucker_Canon = $PrinterCanon.Name } ### End PSCustomObject } ### End Foreach Computer $Inventory #Wie erwähnt wird nun beim [ARRAY]$MonitorList = Get-WmiObject -Class WmiMonitorID #-Namespace root\wmi -ComputerName $computer ein Fehler gezeigt. #Get-WmiObject : Nicht unterstützt #At C:\Test\fehlerabfangen.ps1:25 char:31 #+ ... nitorList = Get-WmiObject -Class WmiMonitorID -Namespace root\wmi -Co ... #+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + CategoryInfo : InvalidOperation: (:) [Get-WmiObject], ManagementException # + FullyQualifiedErrorId : #GetWMIManagementException,Microsoft.PowerShell.Commands.GetWmiObjectCommand # #Cannot index into a null array. #At C:\Test\fehlerabfangen.ps1:50 char:41 #+ Monitor1Hersteller = If($MonitorList[0]){($MonitorLis ... #+ ~~~~~~~~~~~~~~~ # + CategoryInfo : InvalidOperation: (:) [], RuntimeException # + FullyQualifiedErrorId : NullArray Unterste Zeilen im Code stellen die Fehlermeldung im Script dar. Danke für eure Unterstützung :thumb1: :) Pikus Zitieren Link zu diesem Kommentar
Dukel 454 Geschrieben 11. Oktober 2017 Melden Teilen Geschrieben 11. Oktober 2017 Wieso zwei Foreach Schleifen, die das selbe machen? foreach($computer in $testcomputer){ if(test-connection){ # Nicht in eine Datei schreiben sondern weiteremachen! get-wmiobject ... } } Zum Problem: Fehler abfangen kannst du mit try / Catch oder einfach mit if. Zitieren Link zu diesem Kommentar
zahni 554 Geschrieben 11. Oktober 2017 Melden Teilen Geschrieben 11. Oktober 2017 Schau mal hier: https://kevinmarquette.github.io/2017-04-10-Powershell-exceptions-everything-you-ever-wanted-to-know/ 1 Zitieren Link zu diesem Kommentar
tesso 375 Geschrieben 11. Oktober 2017 Melden Teilen Geschrieben 11. Oktober 2017 Schau dir mal das Konstrukt "try" "catch" an. Das dürfte in deinem Fall helfen. Zitieren Link zu diesem Kommentar
Pikus1234 0 Geschrieben 11. Oktober 2017 Autor Melden Teilen Geschrieben 11. Oktober 2017 Erst mal danke für die Antwort, welche ja blitzschnell kam :p . Nun Ich habe die Dateien extra ausgegeben, damit ich die nicht erreichten PC´s und Online-PC trennen kann. diese PC´s können dann gesondert betrachtet, eingeschaltet und später abgefragt werden, ohne dass ich alle wiederholen müsste. Die Abfragemenge variiert schon stark je nach Anforderung. :) Und zum Fehler selbst lese ich mich natürlich ein. Über ein Beispiel in diesem speziellen Fall würde ich mich freuen, da ich sonst alle Hilfethemen sehr abstrakt finde und oftmals Verständnisprobleme dabei habe. Danke :jau: Zitieren Link zu diesem Kommentar
Cybquest 36 Geschrieben 11. Oktober 2017 Melden Teilen Geschrieben 11. Oktober 2017 Statt Fehler abfangen evtl. einfach dieses If($MonitorList[0] ersetzen durch sowas: ForEach ($Monitor in $MonitorList) { ... Zitieren Link zu diesem Kommentar
Dukel 454 Geschrieben 11. Oktober 2017 Melden Teilen Geschrieben 11. Oktober 2017 das kannst du ja trotzdem machen: foreach($computer in $testcomputer){ if(test-connection){ #In Datei schreiben und weiter machen $computer | add-content ... get-wmiobject ... }else{ $computer | add-content ... } } Angenommen du hast 5000 Computer. Er pingt alle 5000 Computer und schreibt diese in eine Datei und liesst dann erst die Infos aus, dann sind sicher die ersten PC's schon wieder aus. Und das Auslesen braucht auch eine gewisse Zeit. 1 Zitieren Link zu diesem Kommentar
Pikus1234 0 Geschrieben 11. Oktober 2017 Autor Melden Teilen Geschrieben 11. Oktober 2017 Schau mal hier: https://kevinmarquette.github.io/2017-04-10-Powershell-exceptions-everything-you-ever-wanted-to-know/ Danke für diese Seite, welche sehr aufschlussreich ist. Ich probiere mich aus. Super :thumb1: das kannst du ja trotzdem machen: foreach($computer in $testcomputer){ if(test-connection){ #In Datei schreiben und weiter machen $computer | add-content ... get-wmiobject ... }else{ $computer | add-content ... } } Angenommen du hast 5000 Computer. Er pingt alle 5000 Computer und schreibt diese in eine Datei und liesst dann erst die Infos aus, dann sind sicher die ersten PC's schon wieder aus. Und das Auslesen braucht auch eine gewisse Zeit. jetzt wo du es mir so erklärst klingt es doch schlüssig. Ich werde deinen Ansatz mal versuchen umzusetzen. Danke für den Tipp..... :thumb1: Ich lasse dich wissen ob ich es auch hinbekommen habe..... :D Zitieren Link zu diesem Kommentar
Pikus1234 0 Geschrieben 18. Oktober 2017 Autor Melden Teilen Geschrieben 18. Oktober 2017 das kannst du ja trotzdem machen: foreach($computer in $testcomputer){ if(test-connection){ #In Datei schreiben und weiter machen $computer | add-content ... get-wmiobject ... }else{ $computer | add-content ... } } Angenommen du hast 5000 Computer. Er pingt alle 5000 Computer und schreibt diese in eine Datei und liesst dann erst die Infos aus, dann sind sicher die ersten PC's schon wieder aus. Und das Auslesen braucht auch eine gewisse Zeit. Also ich stelle mich bei deiner Idee zu b***d an, da fehlt mir doch noch einiges Wissen offensichtlich. Ich erhalte nachfolgende Fehlermeldung.: Add-Content : The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input. Ich hab es wie folgt versucht umzusetzen (streng an deinen Vorschlag) foreach ($computer in $testcomputers) { if (Test-Connection -ComputerName $computer -Quiet -count 1){ #hier liegt der Fehler weil das $computer ja wohl offensichtlich hier nicht verwendet werden kann. $computer| Add-Content -Value $computer "$PSScriptRoot\livePCs.txt" $Inventory = foreach ($computer in $computers) { $Bios = Get-WmiObject win32_bios -Computername $Computer} Wie gesagt das Ziel ist das Speichern der Live-PC in eine Datei um anschließend die Inventur mit diesen PC´s durchzuführen. Aber Wie? Zitieren Link zu diesem Kommentar
Dukel 454 Geschrieben 18. Oktober 2017 Melden Teilen Geschrieben 18. Oktober 2017 $computer| Add-Content -Value $computer "$PSScriptRoot\livePCs.txt" Der Inhalt ist doppelt. Entweder vor die Pipe oder als Parameter. Add-Content -Value $computer "$PSScriptRoot\livePCs.txt" Oder $computer| Add-Content "$PSScriptRoot\livePCs.txt" Zitieren Link zu diesem Kommentar
Beste Lösung Pikus1234 0 Geschrieben 19. Oktober 2017 Autor Beste Lösung Melden Teilen Geschrieben 19. Oktober 2017 $computer| Add-Content -Value $computer "$PSScriptRoot\livePCs.txt" Der Inhalt ist doppelt. Entweder vor die Pipe oder als Parameter. Add-Content -Value $computer "$PSScriptRoot\livePCs.txt" Oder $computer| Add-Content "$PSScriptRoot\livePCs.txt" Leider klappt dieser Schritt nicht zufriedenstellend. Add-Content -Value....klappt aber die Ausgabe ist nicht wie gewünscht. PS scheint also alle PC entsprechend zu verarbeiten, als nur die Online-PC. Oder die Zuordnung bei der Dateispeicherung klemmt. Kurz gesagt.... Ich lasse also lieber doch die Schleifen und lese die PC wieder ein. Denn ehrlich gesagt dauert dieser Schritt gar nicht so lange. Schlimmer wird es ja in der Abfrageschleife $Inventory.... Hier habe ich, auch mit Hilfe von Euch ein Monitor-Array erstellt, um die bis zu 4 angeschlossene Monitore per WMI auslesen zu können. Das Problem ist jetzt: Wenn der PC einen WMI-Fehler aufweist und die Abfrage nicht klappt, muss ich diesen Fehler abfangen. Ihr hattet hier den Tipp gegeben es mit Try und Catch zu tun. Ich habe mich mal ausprobiert und versucht den Fehler in nachfolgender Form abzufangen.... Ideenratgeber war dazu: https://kevinmarquette.github.io/2017-04-10-Powershell-exceptions-everything-you-ever-wanted-to-know/#trycatch try {[ARRAY]$MonitorList = Get-WmiObject -Class WMIMonitorID -Namespace root\wmi -ComputerName $computer} catch {Write-Output $computer "kein Monitor erkannt"} Aber natürlich klappt das nur bedingt.....Das Script läuft zwar weiter durch (arbeitet alle PC ab) Aber wie kann ich jetzt noch dem "catch" mitteilen, dass ich dennoch zur CSV-Ausgabe eine Zeile mit dem PC-Namen erhalten will? Die anderen PC erzeugen ja entsprechende Ausgaben, welche anschließend in eine CSV-Datei gespeichert werden?! Nur 1 PC erzeugt also Fehler bei der WMI-Abfrage und in der Folge bei der Monitorarrayerstellung und erzeugt keine Zeile im CSV. Der PC fehlt mir in der CSV schlichtweg. Dennoch will ich auch diesen PC erfasst wissen. Mir würde also der Eintrag reichen : PCName ($Computer); "keine WMI-Abfrage möglich" oder ähnliches? Mhhh....Ich weiß = viele Fragen aber ich hoffe auf eure Hilfe hier und darf mich für die vielen schnellen Antworten bisher bedanken..... :thumb1: :) Hier nochmal die ganze Inventory-Abfrage und die erzeugten Fehlermeldung des 1. PC aus dieser Abfrage: $Inventory = foreach ($computer in $computers) { 12. $Bios = Get-WmiObject win32_bios -Computername $computer 13. $Hardware = Get-WmiObject Win32_computerSystem -Computername $computer 14. $Sysbuild = Get-WmiObject Win32_WmiSetting -Computername $computer 15. $OS = Get-WmiObject Win32_OperatingSystem -Computername $computer 16. $GUID = Get-wmiobject Win32_ComputerSystemProduct -Computername $computer | Select-Object -ExpandProperty UUID 17. $Networks = Get-WmiObject Win32_NetworkAdapterConfiguration -ComputerName $computer | Where-Object {$_.IPEnabled} 18. $driveSpace = Get-WmiObject win32_volume -Computername $Computer -Filter 'drivetype = 3' | 19. Select-Object PScomputerName, driveletter, label, @{LABEL='GBfreespace';EXPRESSION={'{0:N2}' -f($_.freespace/1GB)} } | 20. Where-Object { $_.driveletter -match 'C:' } 21. $cpu = Get-WmiObject Win32_Processor -Computername $computer 22. $CDROM = Get-WmiObject win32_CDROMDrive -ComputerName $computer 23. $Video = Get-WmiObject Win32_Videocontroller -ComputerName $computer -Filter "NOT name LIKE '%DameWare%'" |Select-Object 'Name*' 24. $username = Get-ChildItem "\\$computer\c$\Users" | Sort-Object LastWriteTime -Descending | Select-Object Name, LastWriteTime -first 1 25.#Fehler abfangen mit try und catch?! 26. try{[ARRAY]$MonitorList = Get-WmiObject -Class WmiMonitorID -Namespace root\wmi -ComputerName $Computer}catch{write-Output $Computer "keine WMI-Abfrage möglich"} 27. $PrinterHP = Get-WmiObject -Class Win32_Printer -ComputerName $Computer |Where-Object { $_.Local -like 'True' -and $_.Name -like 'HP*'}| Select-Object Name 28. $PrinterSamsung = Get-WmiObject -Class Win32_Printer -ComputerName $Computer |Where-Object { $_.Local -like 'True' -and $_.Name -like 'Samsung*'}| Select-Object Name 29. $PrinterCanon = Get-WmiObject -Class Win32_Printer -ComputerName $Computer |Where-Object { $_.Local -like 'True' -and $_.Name -like 'Canon*'}| Select-Object Name 30. 31. [PSCustomObject]@{ 32. ComputerName = $Computer.ToUpper() 33. Manufacturer = $Hardware.Manufacturer 34. Model = $Hardware.Model 35. Serial_Number = $Bios.serialnumber 36. MAC_Address = $Networks.MACAddress 37. Netboot_GUID = $GUID 38. IP_Address = $Networks.IpAddress[0] 39. Processor_Type = $cpu.Name 40. System_Type = $Hardware.SystemType 41. Total_Memory_GB = [math]::round($Hardware.TotalPhysicalMemory/1024/1024/1024, 2) 42. CDROM_Drive = $CDROM.Caption 43. Graphics = $Video.Name 44. Last_User = $username.Name 45. User_Last_Login = $username.LastWriteTime 46. 'C:_FreeSpace_GB' = $driveSpace.GBfreespace 47. Last_ReBoot = $OS.ConvertToDateTime($OS.LastBootUpTime) 48. Operating_System = $OS.Caption 49. Operating_System_Version = $OS.version 50. Operating_System_BuildVersion = $SysBuild.BuildVersion 51.# Fehler Abfangen wegen des Null-Arrays wenn die WMI-Abfrage nicht klappt 52. Monitor1Hersteller = If($MonitorList[0]){($MonitorList[0].ManufacturerName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} 52. Monitor1Typ = If($MonitorList[0]){($MonitorList[0].UserFriendlyName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} 53. Monitor1Seriennummer = If($MonitorList[0]){($MonitorList[0].SerialNumberID -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} 54. Monitor2Hersteller = If($MonitorList[1]){($MonitorList[1].ManufacturerName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} 55. Monitor2Typ = If($MonitorList[1]){($MonitorList[1].UserFriendlyName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} 56. Monitor2Seriennummer = If($MonitorList[1]){($MonitorList[1].SerialNumberID -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} 57. Monitor3Hersteller = If($MonitorList[2]){($MonitorList[2].ManufacturerName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} 58. Monitor3Typ = If($MonitorList[2]){($MonitorList[2].UserFriendlyName -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} 59. Monitor3Seriennummer = If($MonitorList[2]){($MonitorList[2].SerialNumberID -notmatch '^0$' | ForEach-Object {[CHAR]$_}) -join ''}Else{'N/A'} 60. Drucker_HP = $PrinterHP.Name 61. Drucker_Samsung = $PrinterSamsung.Name 62. Drucker_Canon = $PrinterCanon.Name 63. } ### End PSCustomObject 64. 65.} ### End Foreach Computer 66. 67.$Inventory Fehler 1: Get-WmiObject : Nicht unterstützt At C:\test.ps1:26 char:36 + ... nitorList = Get-WmiObject -Class WMIMonitorID -Namespace root\wmi -Co ... Fehler 2: Cannot index into a null array. At C:\test.ps1:52 char:41 + Monitor1Hersteller = If($MonitorList[0]){($MonitorLis ... Ich hoffe nun auf eure Vorschläge.....Bedenkt bitte ich bin echter Newbie in Sachen Power Shell. Zitieren Link zu diesem Kommentar
Dukel 454 Geschrieben 19. Oktober 2017 Melden Teilen Geschrieben 19. Oktober 2017 Fang doch einfach an. Lies z.B. nur den Computername und den Hesteller aus und schreibe dies in die gewünschte Datei in die gewünschte Form. Dann erweiterest du das ganze. Außerdem finde ich das sehr komplex. Wenn du plötzlich ein weiteren Wert brauchst musst du dies an zig Stellen im Script anpassen. Mach das Modular. 1 Zitieren Link zu diesem Kommentar
Empfohlene Beiträge
Schreibe einen Kommentar
Du kannst jetzt antworten und Dich später registrieren. Falls Du bereits ein Mitglied bist, logge Dich jetzt ein.