Probleme mit ObjCreate('Scripting.FileSystemObject') unter Win10

  • Hallo zusammen,

    seit unsere Arbeitsrechner auf Windows 10 umgestellt worden sind, schmiert vereinzelt die TreeView Funtion bei uns ab, was vorher unter Win7 ewig absolut fehlerfrei lief.

    Fehler ist "The requested action with this object has failed.:" und zwar moniert er folgendes:

    Das ist eine angepasste Variante von Oscar 's TreeView.

    Er moniert zwischendurch mal (nicht immer, daher bin ich da auch verwundert) die Zeilen:

    Code
    $read_reservierung = FileReadLine($sPath & $Files.Name, 13)
    $read_important = FileReadLine($sPath & $Files.Name, 14)
    $read_liefertermin = FileReadLine($sPath & $Files.Name, 15)

    Speziell hängt er sich am Parameter .Name auf.

    Die Meldung tritt mal gar nicht auf, mal etliche Male am Tag (meine Treeview wird alle 5 Minuten neu erstellt/aktualisiert) - und dies erst seit der Umstellung auf Windows 10.

    Da unsere Win10 Rechner um einiges schneller sind habe ich die Vermutung (mehr ist es aber auch nicht), dass er einfach die Dateien noch nicht alle "durchgelesen" hat und er mit der TreeView erstellen schneller wäre als das durchlesen der ganzen Dateien und er daher den Fehler aufwirft.

    Wie kann ich das umgehen? Denn das Tool stürzt natürlich vollständig ab, sobald er über diesen Fehler stolpert.

    Ich hoffe diese Codezeilen reichen aus.

    LG

    Mirko

    Mein AutoIT Smartphone GUI >>hier<<

    Der Mensch ist das einzige Tier, dass arbeiten muss.

    • Offizieller Beitrag

    Warum wird das Treeview alle 5 Minuten neu erstellt/aktualisiert?

    Greift da ein anderes Programm auch auf die Dateien zu?

    Das was Du bei $read_reservierung, $read_important und $read_liefertermin machst, ist schlecht, weil dort die Datei geöffnet wird, bis zu der angegebenen Zeilennummer gesprungen wird, die Zeile eingelesen und dann die Datei wieder geschlossen wird und das Ganze 3 Mal hintereinander.

    Wenn Du mehrere Zeilen aus einer Datei auslesen willst, dann immer erst die Datei öffnen (mit "FileOpen"), dann die Zeilen mit dem FileHandle auslesen: "FileReadLine($handle, Zeilennummer)" und am Schluss die Datei wieder schließen "FileClose($handle)".

  • Nee es arbeiten ca 30 Mitarbeiter bei uns mit dem Tool und die Dateien in der Ansicht (dort werden Tickets aufgelistet) muss ständig aktuell sein. Damit ich nicht im Sekundentakt die Ansicht aktualisieren lasse habe ich ne Abfrage auf 5 Minuten gesetzt - es muss halt zwingend die Dateiansicht aktuell sein, geht leider nicht anders.

    mit dem zweiten Hinweis werde ich mal einbauen... evtl reduziert das ja schon die "Leselast" damit es nicht mehr zu diesem Fehler kommt :)

    Mein AutoIT Smartphone GUI >>hier<<

    Der Mensch ist das einzige Tier, dass arbeiten muss.

  • Zwei DInge würde ich ändern:

    • Fehlerprüfungen nach Verwendung von Objekten bzw. Aufruf von Funktionen. Dann kriegst Du nämlich mit, wo ein Fehler tatsächlich auftritt und nicht erst, wenn Du das nächste Mal auf das Ergebnis des fehlerhaften Aufrufs zugreifen willst.
    • Füge einen COM error handler ein. Der gibt dir genau Informationen, was bei der Arbeit mit Objekten falsch lief. Beispiel findest Du in der Hilfe.
  • Ok hab mal zusätzlich den COM handler eingebaut:


    Mal schauen ob der Fehler wieder auftritt und was der Handler auswirft ;)

    Mein AutoIT Smartphone GUI >>hier<<

    Der Mensch ist das einzige Tier, dass arbeiten muss.

  • Damit ich nicht im Sekundentakt die Ansicht aktualisieren lasse habe ich ne Abfrage auf 5 Minuten gesetzt - es muss halt zwingend die Dateiansicht aktuell sein, geht leider nicht anders.

    Schau dir doch mal die Funktion _WinAPI_ShellChangeNotifyRegister an...

  • Wenn Du uns mehr Info geben kannst, wie die Dateien entstehen (sprich: hast Du das Programm geschrieben, das die Dateien erzeugt?), dann können wir auch entsprechende Vorschläge posten.

  • Bitnugger

    Hab mal in die Hilfe für die Funktion geschaut.... da bin ich ehrlich doch etwas mit überfordert, zumal die Hilfe für diese Funktion hier leider nur in Englisch zur Verfügung steht :(

    water

    Ja das Programm habe ich selber geschrieben, weiß also natürlich wie die Dateien aufgebaut sind :)

    Es ist generell so, dass in den Dateien in den Zeilen 13, 14 und 15 immer entweder der Wert 1 oder 4 steht (wird beim erstellen der Datei der Wert einer Checkbox eingetragen - also entweder Checkbox ausgewählt oder halt nicht).

    Wie gesagt, grundsätzlich funktioniert das ganze ja auch Reibungslos, nur seit der Umstellung auf Win10 kommt es manchmal zu den besagten Fehlern.

    Mein AutoIT Smartphone GUI >>hier<<

    Der Mensch ist das einzige Tier, dass arbeiten muss.

  • Hab mal in die Hilfe für die Funktion geschaut.... da bin ich ehrlich doch etwas mit überfordert, zumal die Hilfe für diese Funktion hier leider nur in Englisch zur Verfügung steht

    Ok, das ist eine ehrliche Aussage.

    Mit dieser Funktion kannst du dich von Windows benachrichtigen lassen, wenn sich etwas an oder in den zu überwachenden Verzeichnissen geändert hat.

    Das hat den riesigen Vorteil, dass sich dadurch die Dateizugriffe in deinem Script drastisch reduzieren lassen.

    Sage mir doch einfach mal, was du gerne an Änderungen überwachen würdest und ich schreibe dir dazu die passende Funktion.

    Welches Verzeichnis (können auch mehrere sein) willst du überwachen (inkl. Unterverzeichnisse? (rekursiv)) und welche Dateien (oder Muster, z.B. *.txt oder Rechnung.*) sollen darin gemeldet werden, wenn sich was geändert hat?

    Hier eine Liste aller Ereignisse, über die du benachrichtigt werden kannst... die für dich ganz sicher nicht relevanten habe ich mit einem * markiert - welche brauchst du davon?

  • Hallo Bitnugger

    das ist sehr sehr freundlich von Dir :)

    Ich habe mir mal die Liste angeschaut. Zeile 20: $SHCNE_UPDATEDIR - das wäre meines Erachtens das richtige.

    Zur Erklärung: In meinem Tool werden Tickets erstellt (einfachte *.txt-Dateien mit durch mir festgelegten Inhalt). Diese werden in einem festen Ordner erstellt und dieser Ordner wird durch Treeview Ansicht dargestellt, dass derjenige der diese Tickets bearbeitet, natürlich immer sieht, welche Tickets derzeit existieren. Die TreeView Ansicht lasse ich derzeit in bestimmten Dingen aktualisieren:

    Automatisch alle 5 Minuten durch einen eingebauten Countdown oder sobald ein Ticket vom Bearbeiter bearbeitet und geschlossen wurde. Dann wird lediglich die Funktion aufgerufen, die den Treeview aufbaut (siehe gepostete Funktion oben in meinem ersten Post).

    Das bearbeitete/geschlossene Ticket wird tatsächlich dann nur in einen Unterordner verschoben, damit man dieses später bei Bedarf jederzeit nochmal aufrufen kann.

    Brauchst Du noch mehr, bzw genauere Infos? Der Pfad bzw der Ordner der bei mir in der TreeView Ansicht angezeigt wird ist dieser: "\\BER04APPMM4-1\allgemein\Mailer\". Fertige Tickets werden dann lediglich in "\\BER04APPMM4-1\allgemein\Mailer\erledigt" verschoben (dort gibt es zwar noch weitere Unterordner sortiert nach Datum und anderen Kriterien, das ist aber erstmal uninteressant).

    Viele Grüße,

    Mirko

    Mein AutoIT Smartphone GUI >>hier<<

    Der Mensch ist das einzige Tier, dass arbeiten muss.

    Einmal editiert, zuletzt von mirko2002 (28. Dezember 2018 um 11:31)

  • Ich habe mir mal die Liste angeschaut. Zeile 20: $SHCNE_UPDATEDIR - das wäre meines Erachtens das richtige.

    Dieses Event wird allerdings nur ausgelöst, wenn sich in dem zu überwachenden Verzeichnis in einem der Unterverzeichnisse etwas geändert hat oder ein neues Unterverzeichnis erstellt wurde... und so wie ich es verstehe, interessieren dich aber nur die Ticket-Dateien in dem zu überwachendem Verzeichnis?! Doch auch wenn es so wäre, wie du vermutet hast, wüsstest du durch diesen Event aber nicht, was sich da getan hat.

    Dieses Event könnte man zwar nehmen... dann müsste allerdings das übergeordnete Verzeichnis "\\BER04APPMM4-1\allgemein\" überwacht werden. Wirklich Sinn macht das aber nicht, weil du dann für alle Unterverzeichnisse in \Mailer\ ein Event bekommst.

    Ich denke mal, du willst eigentlich nur wissen, ob sich in dem zu überwachendem Verzeichnis "\\BER04APPMM4-1\allgemein\Mailer\" etwas an den Dateien (Tickets) geändert hat:

    • Wurde in dem zu überwachenden Verzeichnis ein neues Ticket erstellt?
    • Wurde in dem zu überwachenden Verzeichnis der Inhalt eines Tickets geändert?
    • Wurde in dem zu überwachenden Verzeichnis ein Ticket gelöscht?
    • Wurde in dem zu überwachenden Verzeichnis ein Ticket umbenannt?

    Dafür bräuchten wir dann die Events: $SHCNE_CREATE, $SHCNE_UPDATEITEM, $SHCNE_DELETE und $SHCNE_RENAMEITEM, falls sie auch umbenannt werden. Bei $SHCNE_UPDATEITEM müssten wir dann noch überprüfen, ob das Item ein Verzeichnis oder eine Datei (Ticket) war.

    Wenn ich dich richtig verstehe, dann willst du bei allen Events die Funktion _GUICtrlTreeView_CreateDirectory aufrufen und das TreeView dann immer neu erstellen... das geht natürlich auch, doch das ist dann definitiv eine sehr unfeine Holzhammermethode.

    Code: Holzhammer
    $SHCNE_CREATE     --> _GUICtrlTreeView_CreateDirectory(...)
    $SHCNE_UPDATEITEM --> _GUICtrlTreeView_CreateDirectory(...)
    $SHCNE_DELETE     --> _GUICtrlTreeView_CreateDirectory(...)
    $SHCNE_RENAMEITEM --> _GUICtrlTreeView_CreateDirectory(...)

    Viel eleganter wäre, wenn du für jedes Event eine spezielle Funktion aufrufst und nur genau das machst, was nötig ist... hier mal ein Beispiel:

    Code: Skalpell
    $SHCNE_CREATE     --> _SH_Notify_TreeView_InsertItem(...)
    $SHCNE_UPDATEITEM --> _SH_Notify_TreeView_SetText(...)
    $SHCNE_DELETE     --> _SH_Notify_TreeView_Delete(...)
    $SHCNE_RENAMEITEM --> _SH_Notify_TreeView_SetText(...)

    Wie willst du es nun angehen - Holzhammer oder Skalpell? ;)

  • Du hast das Problem eigentlich schon zu 100% getroffen. Die Ansicht soll sich nur aktualisieren, wenn ein neues Ticket erstellt oder gelöscht/verschoben wurde. Umbenennen der Tickets wird nicht passieren. Und ein inhaltliches Update in den Tickets ist egal - da muss die TreeView Ansicht nicht extra aktualisiert werden, da das Ticket eh ausgelesen wird sobald man es in der TreeView anklickt.

    Bisher ist es tatsächlich so, das durch den Countdown alle 5 Minuten einfach die Funktion _GUICtrlTreeView_CreateDirectory durchgejagt wird oder wenn ein Ticket erstellt wurde - weil auch danach soll die TreeView Ansicht ja aktuell sein, sonst taucht das neue Ticket ja nicht auf.

    Ansich kann ich mich über die TreeView Variante nicht beschweren. Seit ca 1 Jahr hab ich das Programm hier im Einsatz und es läuft soweit eigentlich super (mit Ausnahme jetzt auf Win10). Wenn es aber natürlich zu verbessern geht hab ich da gerne offene Ohren für :)

    Mein AutoIT Smartphone GUI >>hier<<

    Der Mensch ist das einzige Tier, dass arbeiten muss.

  • Was die Performance sicher auch noch erhöhen würde, wäre, wenn die Icons nicht für jeden Eintrag aus der Icon Datei '\\allgemein\TicketTool\settings\icons.dll' herausgesucht werden müsste.
    Die Icons 1x laden und dann aus dem Memory heraus verwenden.
    Siehe in der Hilfe: _GUICtrlTreeView_Add ab Zeile _GUIImageList_Create.

  • Dieses Q&D zusammengeschnitzte Beispiel läuft mit der ImageList in 0,2 Sekunden bei 500 Einträgen im TreeView, während Dein Ansatz über eine Sekunde benötigt:

  • Er moniert zwischendurch mal (nicht immer, daher bin ich da auch verwundert) die Zeilen:


    Code
    $read_reservierung = FileReadLine($sPath & $Files.Name, 13)
    $read_important = FileReadLine($sPath & $Files.Name, 14)
    $read_liefertermin = FileReadLine($sPath & $Files.Name, 15)

    Mit moniert meinst du dann sicher, dass dein Script dann abschmiert?! Viel hilfreicher wäre, wenn du uns die "unzensierte" Fehlermeldung nennen würdest... die dann z.B. etwa so aussehen könnte:

    ".\_GUICtrlTreeView_CreateDirectory.au3" (27) : ==> The requested action with this object has failed.:

    $Folder = $oFSO.GetFolder($sPath)

    $Folder = $oFSO^ ERROR

    Denn mit "Er moniert" kann man nicht wirklich was anfangen... und wer ist übrigens "Er"? ;)

    Speziell hängt er sich am Parameter .Name auf.

    $Files.Name kann nur funktionieren, wenn $Folder ein Objekt ist!

    Das dein Script abstürzt, wenn es auf $Files.Name trifft, liegt mit sehr hoher Wahrscheinlichkeit also daran, dass $Folder kein Objekt ist und du keinen COM-ERROR-HANDLER installiert hast, der diesen Fehler abfängt!

    Denn hättest du einen installiert, würdest du lediglich eine Fehlermeldung angezeigt bekommen und das Script würde dann aber weiterlaufen!

    Wie man einen COM-ERROR-HANDLER installiert, kannst du in der AutoIt-Hilfe in dem ersten Beispiel zu ObjEvent sehen.

    Eine wacklige Netzwerkverbindung kann in deinem Fall übrigens auch der Grund sein, warum dein Script ohne COM-ERROR-HANDLER abschmiert!

    Du hast das Problem eigentlich schon zu 100% getroffen. Die Ansicht soll sich nur aktualisieren, wenn ein neues Ticket erstellt oder gelöscht/verschoben wurde.

    Ok, nun habe ich jedoch registriert, dass dein zu überwachendes Verzeichnis "\\BER04APPMM4-1\allgemein\Mailer\" evtl. kein lokales Verzeichnis ist... _WinAPI_ShellChangeNotifyRegister funktioniert aber leider nur mit lokalen Verzeichnissen! :(

    Jetzt gibt es zwei Möglichkeiten:

    1. Dein Script wird auf demselben PC/SERVER ausgeführt, auf dem sich das zu überwachende Verzeichnis befindet - dann kannst du anstelle des Netzwerkpfades bei _WinAPI_ShellChangeNotifyRegister den lokalen Pfad angeben und es würde funktionieren.
    2. Dein Script wird NICHT auf demselben PC/SERVER ausgeführt, auf dem sich das zu überwachende Verzeichnis befindet - dann müsste ein (kompiliertes) Script auf dem anderen PC/SERVER ausgeführt werden, dass dieses lokale Verzeichnis überwacht und wenn ein Event ausgelöst wird, eine Nachricht an dein Script sendet, z.B. via UDP/TCP.
  • Guten Morgen Bitnugger

    mir gefällt Deine Schreibweise :)

    Tatsächlich ist die Fehlermeldung fast richtig:

    "TicketTool.au3" (1714) : ==> The requested action with this object has failed.:

    $read_reservierung = FileReadLine($sPath & $Files.Name, 13)

    $read_reservierung = FileReadLine($sPath & $Files^ ERROR

    "Er" ist übrigens mein kleiner PC. Ich mag ihn - auch wenn er nicht immer das macht was ich möchte :)

    Mit der wackligen Internetverbindung kann schon sein, manchmal haben wir hier Probleme mit. Was mich aber wundert ist, dass dieser Fehler nur bei Rechnern auftritt die bereits auf Win10 umgestellt sind. Unsere Win7 Rechner laufen wie eine Eins. Und selbst bei den Win10 Rechnern taucht es ja nur sporadisch auf. Mal einen ganzen Tag überhaupt nicht, mal im 10 Minuten Takt.

    Mit dem Verzeichnis hast Du Recht - es ist ein Ordner auf unserem Server.

    Nicht desto trotz habe ich inzwischen einen COM-ERROR-Handler eingebaut und die neue Version ist heute online gegangen. Ich werde das ganze mal damit beobachten.

    Deine beiden vorgeschlagenen Varianten sind leider beide nicht möglich, das macht unsere IT nicht mit.

    Mein AutoIT Smartphone GUI >>hier<<

    Der Mensch ist das einzige Tier, dass arbeiten muss.

  • Ein COM-ERROR-Handler sorgt zwar dafür, dass dein Script nicht mehr abstürzt, wenn du mit Objekten hantierst, doch du solltest trotzdem vor der weiteren Verarbeitung mit If @error oder IsObj() prüfen, ob das Object erstellt werden konnte.

    Hier machst du es...

    Code
    Local $oFSO = ObjCreate('Scripting.FileSystemObject')
    If @error Then Return SetError(2, 0, 0)

    hier aber nicht...

    Code
    $Folder = $oFSO.GetFolder($sPath)
    _CreateDirectoryRecursive($hTreeView, $Folder, $hTreeViewItem, $bFiles, $aCount)

    deshalb ist dein Script ohne COM-ERROR-Handler hier abgeschmiert , wenn $Folder kein Objekt ist!

    Code
    If $bFiles Then
        For $Files In $Folder.Files
            $read_reservierung = FileReadLine($sPath & $Files.Name, 13) ; <-- +++
  • Ok ich konnte das Problem schon gut beheben... sobald das ganze durch einen Fehler in den COM-Error Handler gehen würde weil $Folder kein Objekt ist, wird die Treeview einfach nochmal neu erstellt.

    Gesundes Neues wünsche ich übrigens noch :)

    Mein AutoIT Smartphone GUI >>hier<<

    Der Mensch ist das einzige Tier, dass arbeiten muss.