Tipp: Pfadangaben nicht hardcoden.
Deine *.txt und deine Logfiles sind fest im Skript codiert. Ich würde das flexibel gestalten (mit INI oder Programmparameter)
- wenn INI vorhanden --> verwende Pfade von dort -->sonst: @ScriptDir & "\..."
Oder
- wenn Startparameter übergeben ( /txt='Pfad\Datei.txt' /log1='Pfad\Log1Datei.log' /log2='Pfad\Log2Datei.log' - oder ähnlich) --> verwende diese Pfade, sonst: s.o.
Hey BugFix - vielen Dank für deine Antwort.
Danke für den Hinweis. Habe es berücksichtigt und verwende künftig keine harten Pfadangaben
Das nächste betrifft deine Funktionen, OSList und Softwarelist. Hier hast du jeweils ein FileClose am Ende der Funktion. Aber zuvor hast du die Datei nie mit FileOpen geöffnet und du arbeitest daher auch nicht mit dem Filehandle, das von dieser Funktion zurückgegeben wird, sondern mit dem Dateipfad. Daher werden die Schritte FileOpen/FileClose bei jeder Anwendung der Funktion FileWriteLine durchgeführt. Je mehr Einträge, desto länger dauert das...
Ich bin sicher, die Korrektur dieses kleinen Fehlers macht dein Skript schon schneller. Darüber hinaus würde ich den langen, sich wiederholenden Teil der Ausgabe, am Anfang in eine Variable schreiben und diese dann benutzen. Dann wirkt der Code nicht so erschlagend.
Hier am Bsp deiner OSList-Funktion (mehr Auswirkungen hat das sicher bei Softwarelist. Da ist es aber genau gleich zu ändern.):
(Achtung: Bei FileOpen benutze ich die Konstante $FO_OVERWRITE. Entweder du schreibst stattdessen 2 oder du fügst oben im Skript #include <FileConstants.au3> ein.)
AutoIt Alles anzeigenFunc OSList() Local $sLogFileOS = @ScriptDir & "\" & @MON & "" & @MDAY & "" & @YEAR & "_" & @HOUR & "_" & @MIN & "_LogFileOS.txt" Local $hOpenLFileOS = FileOpen($sLogFileOS, $FO_OVERWRITE) ; ACHTUNG: Ab hier wird nur noch mit dem Handle $hOpenLFileOS gearbeitet. Nicht mit $sLogFileOS. If $hOpenLFileOS = -1 Then MsgBox($MB_SYSTEMMODAL, "Abbruch", $sLogFileOS & " konnte nicht geöffnet werden!") Exit EndIf FileWriteLine($hOpenLFileOS, @WDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & " " & @TAB & "Start der Betriebssystemverarbeitung") ConsoleWrite(@WDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & " " & @TAB & "Start der Betriebssystemverarbeitung" & @CRLF) Local $sDesc = "", $iPing = 0 For $i = 0 To UBound($sPC) - 1 $sDesc = @WDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & " " & @TAB & $sPC[$i] $iPing = Ping($sPC[$i], 250) Switch @error Case 1 ;MsgBox(64, @error, "Host is offline") FileWriteLine($hOpenLFileOS, $sDesc & " Error 1: " & "Host ist Offline" & @CRLF) ConsoleWrite($sDesc & " Error 1: " & "Host ist Offline" & @CRLF) Case 2 ;MsgBox(64, @error, "Host is unreachable") FileWriteLine($hOpenLFileOS, $sDesc & " Error 2: " & "Host nicht erreichbar" & @CRLF) ConsoleWrite($sDesc & " Error 2: " & "Host nicht erreichbar" & @CRLF) Case 3 ;MsgBox(64, @error, "Bad destination") FileWriteLine($hOpenLFileOS, $sDesc & " Error 3: " & "Bad destination" & @CRLF) ConsoleWrite($sDesc & " Error 3: " & "Bad destination" & @CRLF) Case 4 ;MsgBox(64, @error, "Other errors") FileWriteLine($hOpenLFileOS, $sDesc & " Error 4: " & "Kein Zugriff" & @CRLF) ConsoleWrite($sDesc & " Error 4: " & "Kein Zugriff" & @CRLF) Case Else FileWriteLine($hOpenLFileOS, $sDesc & " Status : " & "Rechner online" & @CRLF) ConsoleWrite($sDesc & " Status : " & "Rechner online" & @CRLF) ;MsgBox(64, @error, "Host is online") $oWMI = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\" & $sPC[$i] & "\root\cimv2") If IsObj($oWMI) Then $aSystem = $oWMI.ExecQuery("Select * from Win32_OperatingSystem") For $oApp In $aSystem $installdate = StringMid($oApp.InstallDate, 1, 4) & "-" & StringMid($oApp.InstallDate, 5, 2) & "-" & StringMid($oApp.InstallDate, 7, 2) ;FileWriteLine($LogFile, $sPC[$i] & "," & $oApp.Name & "," & $oApp.Version & "," & $oApp.Vendor & "," & $oApp.InstallDate & @CRLF) If $sData2 <> '' Then $sData2 = $sData2 & '~' EndIf ;('%1;%2;%3;%4;%5' %1 %2 %3 %4 %5) $sData = StringFormat('%s;%s;%s;%s;%s', $sPC[$i] & ";" & $oApp.Caption & ";" & $oApp.Version & ";" & $oApp.Manufacturer & ";" & $installdate) $sData2 = $sData2 & '~' & $sData Next Else ;FileWriteLine($LogFile, $sPC[$i] & "," & "Offline" & @CRLF) EndIf $oHTTP.Send("id=setSoftwareinventar&data=" & _URLEncode($sData2)) FileWriteLine($hOpenLFileOS, $sDesc & " Erfolg : " & "Eintraege wurden vorgenommen" & @CRLF) ConsoleWrite($sDesc & " Erfolg : " & "Eintraege wurden vorgenommen" & @CRLF) ;ConsoleWrite($sData2) EndSwitch Next FileWriteLine($hOpenLFileOS, @WDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & " " & @TAB & "Ende der Betriebssystemverarbeitung") ConsoleWrite(@WDAY & "." & @MON & "." & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC & " " & @TAB & "Ende der Betriebssystemverarbeitung" & @CRLF) FileClose($hOpenLFileOS) EndFunc ;==>OSList
Auch diesen Hinweis von dir habe ich berücksichtigt und angewandt.
Ich ging wohl einfach davon aus, dass ein FileOpen gar nicht mehr notwendig wäre, wenn man die Variable zum Pfad bzw. zum Logfile angibt.
Aber es macht alles nur Sinn was du schreibst:
Funktion starten, File öffnen, offen lassen, Schreibvorgänge vornehmen und am Ende erst wieder schließen.
Ich habe die neue Funktion auch direkt mal getestet...allerdings habe ich immer noch Schwierigkeiten mit der Performance.
Also hat es nicht unbedingt zu einer Besserung geführt, den Code aber wesentlich ordentlicher und richtiger gemacht.
Die Performance bei der OSList()-Funktion läuft problemlos und sehr schnell. Innerhalb von 3 Minuten waren 190 Rechner abgefragt.
Weiterhin habe ich weitere 28 Rechner abgefragt und eine Softwareliste erstellen lassen, hier mal die Zeiten dazu:
Uhrzeit | Status | Dauer |
10:45:54 | NDEST003 Erfolg : Eintraege wurden vorgenommen | 00:00:28 |
10:47:18 | NDEST005 Erfolg : Eintraege wurden vorgenommen | 00:01:24 |
10:47:20 | NDEST009 Erfolg : Eintraege wurden vorgenommen | 00:00:02 |
10:47:48 | NDEST044 Erfolg : Eintraege wurden vorgenommen | 00:00:28 |
10:50:36 | NDEST054 Erfolg : Eintraege wurden vorgenommen | 00:02:48 |
10:51:00 | NDEST055 Erfolg : Eintraege wurden vorgenommen | 00:00:24 |
10:51:29 | NDEST056 Erfolg : Eintraege wurden vorgenommen | 00:00:29 |
10:53:34 | NDEST058 Erfolg : Eintraege wurden vorgenommen | 00:02:05 |
10:55:24 | NDEST059 Erfolg : Eintraege wurden vorgenommen | 00:01:50 |
10:56:01 | NDEST061 Erfolg : Eintraege wurden vorgenommen | 00:00:37 |
10:57:29 | NDEST066 Erfolg : Eintraege wurden vorgenommen | 00:01:28 |
10:58:04 | NDEST071 Erfolg : Eintraege wurden vorgenommen | 00:00:35 |
10:58:30 | NDEST078 Erfolg : Eintraege wurden vorgenommen | 00:00:26 |
10:59:23 | SDESTAPP3 Erfolg : Eintraege wurden vorgenommen | 00:00:53 |
10:59:57 | SDESTAPP4 Erfolg : Eintraege wurden vorgenommen | 00:00:34 |
11:01:33 | SDESTFELIX Erfolg : Eintraege wurden vorgenommen | 00:01:36 |
11:02:14 | SDESTFIL03 Erfolg : Eintraege wurden vorgenommen | 00:00:41 |
11:02:59 | SDESTIZDQ Erfolg : Eintraege wurden vorgenommen | 00:00:45 |
11:03:37 | SDESTLSA Erfolg : Eintraege wurden vorgenommen | 00:00:38 |
11:04:20 | SDESTMXS02 Erfolg : Eintraege wurden vorgenommen | 00:00:43 |
11:04:50 | SDESTPAAPP1 Erfolg : Eintraege wurden vorgenommen | 00:00:30 |
11:05:08 | SDESTPAD1 Erfolg : Eintraege wurden vorgenommen | 00:00:18 |
11:10:00 | SDESTSQL02 Erfolg : Eintraege wurden vorgenommen | 00:04:52 |
11:11:44 | SDESTSQL03 Erfolg : Eintraege wurden vorgenommen | 00:01:44 |
11:12:47 | SDESTSQL04 Erfolg : Eintraege wurden vorgenommen | 00:01:03 |
11:15:46 | VDEST1001 Erfolg : Eintraege wurden vorgenommen | 00:02:59 |
11:17:50 | VDEST1003 Erfolg : Eintraege wurden vorgenommen | 00:02:04 |
11:19:10 | VDEST1004 Erfolg : Eintraege wurden vorgenommen | 00:01:20 |
Ich kann mir einfach noch nicht so recht erklären, wodurch diese extrem unterschiedlichen Zeiten zustande kommen.
Aber vllt. hat ja jemand von euch noch eine Idee hinsichtlich der Optimierung.
Alles anzeigenDa dein Webservice POST Daten entgegennimmt ohne vorherige Authentifizierung (hab jedenfalls beim Überfliegen nichts davon gesehn) ließe sich das ganze massiv paralelisieren.
Anstatt das Script zentral von einer Adminstation auszuführen könnte auch jeder Clientrechner im Netzwerk seine eigenen Scriptinstanz ausführen und seine Daten selbsständig an den Webservice melden. So machen das auch verbreitete "professionelle" Lösungen wie z.B. OCS Inventory und GLPI
Vorteil:
- Alle Clients melden paralell, somit extreme Zeitersparnis
- Alle Clients könnten periodisch Updates über ihre derzeitige Konfiguration versenden (z.B. über täglichen Windows Task), somit hast du stets aktuelle Daten über die Softwarekonfiguration
Nachteil bzw. Mehraufwand:
- Das Script muss einmalig auf dem Clientrechner platziert und entsprechend als Task eingerichtet werden
- Der Webservice bzw. dessen API muss im kompletten Netzwerk verfügbar sein (evtl. Probleme mit Clients die mobil und nicht immer im lokalen Netzwerk angemeldet sind)
- Missbrauchspotential, da Webservice ohne Authentifizierung ansprechbar ist -> evtl. richtige API mit Authentifizierung einsetzen
- Client Script sollte über Selbstupdate Funktion verfügen, damit du einfach und schnell alle Clients austauschen kannst wenn du eine Änderung des Clients benötigst
- Fehlermeldungen vielleicht besser unsichtbar per Email versenden anstatt per msgbox ausgeben, um Benutzer nicht zu verwirren
Hey misterspeed - dir auch vielen Dank für deine Bemühungen.
Hierzu muss ich aber noch erwähnen, dass ich nur für die Teststellung keine Authentifizierung nutze.
Leider überwiegen die Nachteile bei der von dir vorgeschlagenen Lösung.
Allerdings habe ich noch folgendes vor...dadurch, dass ja ein Webservice und eine SQL-Datenbank die ganze Geschichte unterstützt, habe ich später keine *.txt-Datei mehr in der die abzufragenden Rechner stehen, sondern eine SQL-Tabelle in der alle Rechner mittels IP-Range ermittelt werden.
Dann starte ich mein Skript als Dienst in 6-10 verschiedene Instanzen (die Anzahl muss ich mir ausprobieren) und jedesmal, wenn sich das Skript einen Rechner holt, setzt der Webservice einen Eintrag in der Datenbank, dass dieser Rechner bereits abgefragt wird. Hat die erste Instanz dann die benötigten Informationen, wird die Softwareliste in die Datenbank geschrieben und der Webservice löscht den abgefragten Rechner.
Somit erhöht sich die Performance eben um die Anzahl der Instanzen/Dienste die gestartet werden.