![]() |
Nach Explorer absturz
Wie kann ich am besten prüfen ob der Explorer abgestürzt ist ohne Timer?
Unter Win10 stürzt dieser leider immer öfter ab danach funktioniert mein Programm nicht mehr. (bsp. Wegen NVIDIA Control Panel) |
AW: Nach Explorer absturz
Zitat:
![]() Zitat:
Abstürze des Windows Explorer sind sehr häufig durch schlecht Programmierte Shell Extensions verursacht. Diese zu identifizieren und zu löschen löst das Problem. Evtl. findet sich ja in der Windows Ereignisanzeige zu dem Absturz ein Hinweis |
AW: Nach Explorer absturz
Zitat:
Ist das nicht eine Sache die NVIDIA beheben sollte? Mit den HOOK werde ich mir mal anschauen. Danke! |
AW: Nach Explorer absturz
Zitat:
Falls der Rechner älter ist, dann hilft ab und zu ältere Treiber-Versionen, da die neuesten nur noch "mehr schlecht als recht" für die alten Grafikkarten angepasst werden. |
AW: Nach Explorer absturz
Zitat:
Welches Interesse sollte ich haben hier Unwahrheiten zu veröffentlichen? Ja es ist der Menu Punkt um die NVIDIA Systemsteuerung aufzurufen. Es gibt eine extra APP die aus dem Store von MS installiert werden kann die funktioniert aber auch nur mehr schlecht als recht. Meistens crasht der Explorer beim ersten Aufruf des Explorer Kontext Menu nach dem Neustart und es hat nichts mit Treibern zu tun. Und dann funktioniert meine Anwendung nicht mehr weil die ProcID des Explorer sich geändert hat. Ich muss also Fehler abfangen die vom System selbst generiert werden. Stupid! Win10 ![]() Ist das meine Aufgabe? Sieht man auf das Datum dann erkennt man wie lange das Problem schon (immer noch) besteht. |
AW: Nach Explorer absturz
Zitat:
Zitat:
Zitat:
Wenn du mit ein wenig Code erklärst, was nach der Änderung der explorer.exe PID dann nicht mehr funktioniert, dann kann dir doch sicher irgendwer helfen. |
AW: Nach Explorer absturz
Zitat:
Wie kannst du helfen wenn du das Log siehst? Zitat:
Davon jedoch kann ich mit der ewigen Beta Version von WIN10 nichts erkennen. Zitat:
Wenn der Explorer abstürzt bekommt mein Programm nicht mehr mit ob dieser voll oder leer ist. Es aktualisiert also den aktuellen Status nicht mehr. Zitat:
Die Frage war also schon beantwortet. Zitat:
Das sind 2 paar Schuhe, zudem verwendet der Standard Grafiktreiber den Dienst "NVIDIA Display Container LS" gar nicht, bringt also nichts. |
AW: Nach Explorer absturz
ich blicke gerade nicht so ganz durch ob das problem behoben ist ansonsten würde ich vielleicht so vorgehen:
Delphi-Quellcode:
Sowas in der art vor deinem "Schau nach Korb" dingens rein?
function GetExplorerPID: DWORD;
var hWnd: Cardinal; PID: DWORD; begin hWnd := FindWindow('Progman', 'Program Manager'); GetWindowThreadProcessId(hWnd, @PID); Result := PID; end; |
AW: Nach Explorer absturz
Zitat:
Deine Lösung ist aber sehr weit davon entfernt. Es bringt mir nichts alle "ms" diese Aufzurufen. Danke Die frage war auch nicht wie ich an die PID komme sondern Zitat:
|
AW: Nach Explorer absturz
Nur nochmal zur Vervollständigung.
Ich registriere den Papierkorb damit das Event WM_SHELLNOTIFY ausgelöst wird.
Delphi-Quellcode:
Wenn nun der Explorer abstürzt wird das Event WM_SHELLNOTIFY nicht mehr ausgelöst da es zum vorherigen Prozess Explorer.exe nicht mehr gültig ist.
{$REGION 'procedure RegisterRecyleBin'}
procedure TMainApp.RegisterRecyleBin(WinHandle: HWND); var pidlRecycleBin: PItemIDList; stPIDL: TSHChangeNotifyEntry; hr: HRESULT; begin hr := SHGetSpecialFolderLocation(WinHandle, CSIDL_BITBUCKET, pidlRecycleBin); if Succeeded(hr) then begin stPIDL.pidl := pidlRecycleBin; stPIDL.fRecursive := True; FHNotifyRBin := SHChangeNotifyRegister(WinHandle, SHCNF_ACCEPT_INTERRUPTS or SHCNF_ACCEPT_NON_INTERRUPTS, SHCNE_ALLEVENTS, WM_SHELLNOTIFY, 1, stPIDL); if 0 = FHNotifyRBin then RaiseLastOSError(GetLastError); end else RaiseLastOSError; // Hier werde ich nun den Hook implementieren und die Anwendung entsprechend des Event neu starten. end; {$ENDREGION} Bzw. Der Papierkorb ist dann nicht mehr registriert (FHNotifyRBin = Registrations ID) ist dann ungültig. Wie gesagt es ist mir unverständlich das ein System so unzuverlässig ist und man selber eventuelle Fehler diesbezüglich abfangen muss. |
AW: Nach Explorer absturz
Hier ist jetzt die Lösung.
Delphi-Quellcode:
MainProc.
procedure WinEventProc(hWinEventHook: THandle; event: DWORD; EHandle: HWND;
idObject: Integer; idChild: Integer; idEventThread: DWord; dwmsEventTime: DWord); stdcall; begin if (event = EVENT_OBJECT_DESTROY) and (EHandle = HwndTarget) and (idObject = OBJID_WINDOW) and (idChild = INDEXID_CONTAINER) then begin if (MainApp.FHNotifyRBin <> 0) then begin if SHChangeNotifyDeregister(MainHandle) then begin SendMessage(MainHandle, WM_COMMAND, IDM_Restart, 0); MainApp.RegisterRecyleBin(MainHandle); end; end; end; end;
Delphi-Quellcode:
WM_DESTROY:
begin if (HWEH <> 0) then UnhookWinEvent(HWEH);
Delphi-Quellcode:
Aber!
{$REGION 'procedure RegisterRecyleBin'}
procedure TMainApp.RegisterRecyleBin(WinHandle: HWND); var dwProcessId: DWord; dwThreadId: DWord; pidlRecycleBin: PItemIDList; stPIDL: TSHChangeNotifyEntry; hr: HRESULT; begin HwndTarget := FindWindow('Progman', 'Program Manager'); dwThreadId := GetWindowThreadProcessId(HwndTarget, @dwProcessId); if (dwThreadId <> 0) then HWEH := SetWinEventHook(EVENT_OBJECT_DESTROY, EVENT_OBJECT_DESTROY, 0, @WinEventProc, dwProcessId, dwThreadId, WINEVENT_OUTOFCONTEXT); hr := SHGetSpecialFolderLocation(WinHandle, CSIDL_BITBUCKET, pidlRecycleBin); if Succeeded(hr) then begin stPIDL.pidl := pidlRecycleBin; stPIDL.fRecursive := True; FHNotifyRBin := SHChangeNotifyRegister(WinHandle, SHCNF_ACCEPT_INTERRUPTS or SHCNF_ACCEPT_NON_INTERRUPTS, SHCNE_ALLEVENTS, WM_SHELLNOTIFY, 1, stPIDL); if 0 = FHNotifyRBin then RaiseLastOSError(GetLastError); end else RaiseLastOSError; end; {$ENDREGION} Wie kann ich das nun zuverlässig testen? Wenn ich nun einen Hard Reset ausführe also den Prozess Explorer kille dann startet der Explorer nicht automatisch neu und dann wird das DesktopListView nicht mehr gefunden. Gibt es einen anderen weg den Explorer zu beenden so das er automatisch neustartet damit ich den Fehler gegenprüfen kann? EDIT: Es ist ja nicht die Aufgabe meiner Anwendung den Explorer neu zu starten oder? |
AW: Nach Explorer absturz
.. geht es nicht über den TaskManager Windows-Explorer markieren -> unten rechts neu starten.
Grüße Klaus |
AW: Nach Explorer absturz
Zitat:
Aber dazwischen greift ja das Event bzw. die Callback. Wenn ich danach die Anwendung neu\restarte wird das DesktopListView nicht gefunden der Explorer startet ja erst danach neu! Werde wohl einen Loop hinzufügen müssen der darauf wartet bis das Handle vom Progman wieder gefunden wird. |
AW: Nach Explorer absturz
Es gibt doch aber auch irgendwo ein Event, wenn der Explorer die Taskleiste neu gestartet wurde.
Wenn man etwas hat, was sich dort rein hängt, dann muß man eben auch auf dessen Events reagieren. Und ja, es ist krank, dass Desktop/Taskleiste und Explorer.exe ein und das Selbe sind, aber damit muß man eben leben, bis es endlich mal repariert/geändert wird. |
AW: Nach Explorer absturz
Zitat:
Habe es jetzt so geändert. Ob das elegant ist mag dahin gestellt sein.
Delphi-Quellcode:
procedure WinEventProc(hWinEventHook: THandle; event: DWORD; EHandle: HWND;
idObject: Integer; idChild: Integer; idEventThread: DWord; dwmsEventTime: DWord); stdcall; var Counter: Integer; begin if (event = EVENT_OBJECT_DESTROY) and (EHandle = HwndTarget) and (idObject = OBJID_WINDOW) and (idChild = INDEXID_CONTAINER) then begin if (MainApp.FHNotifyRBin <> 0) then begin HwndTarget := 0; Counter := 0; if SHChangeNotifyDeregister(MainHandle) then begin MainApp.FHNotifyRBin := 0; repeat HwndTarget := FindWindow('Progman', 'Program Manager'); WinProcessMessages; inc(Counter); until (HwndTarget <> 0) or (Counter = 30000); if HwndTarget <> 0 then MainApp.RegisterRecyleBin(MainHandle); end; end; end; end; |
AW: Nach Explorer absturz
Zitat:
Delphi-Quellcode:
RegisterWindowMessage('TaskbarCreated')
|
AW: Nach Explorer absturz
Zitat:
|
AW: Nach Explorer absturz
Zitat:
Das ist egal. Explorer und Taskleiste sind quasi das Gleiche. Die erste Instanz der explorer.exe ist der "Desktop", mit der Taskleiste drauf. Genauso wie (File) Explorer und Internet Exporer untrennbar zusammen gehören. Der Interactive Desktop und die WebView des Explorers ist ein Internet Explorer. Das FTP im Explorer läuft über den Intenret Explorer. :wall: (und alle runtergeladenen Dateien landen im IECache, wo auch noch die gesetzte Speichergrenze ignoriert wird) Man kann sogar über die selbe API alle Internet Explorer und (File) Explorer auslisten, mit samt ihrer URL/Pfad. |
AW: Nach Explorer absturz
[QUOTE=venice2;1473613]
Zitat:
|
AW: Nach Explorer absturz
Zitat:
Was, wie, wo soll ich ändern? bzw. Ist bei mir nicht die korrekte Implementierung. Ich habe doch ein Event HWEH := SetWinEventHook Warum soll ich jetzt noch eine Message Registrieren. RegisterWindowMessage('TaskbarCreated') Ich frage deshalb nochmal weil ich Probleme habe der HOOK greift nicht immer.
Delphi-Quellcode:
Papierkorb registrieren
if (HWEH <> 0) then
begin UnhookWinEvent(HWEH); // HOOK zerstören wenn erstellt. HWEH := 0; end; HWEH := SetWinEventHook(EVENT_OBJECT_DESTROY, EVENT_OBJECT_DESTROY, 0, @WinEventProc, dwProcessId, dwThreadId, WINEVENT_OUTOFCONTEXT); // HOOK erstellen.
Delphi-Quellcode:
Seltsamer weise incrementiert FHNotifyRBin bin mir nicht sicher ob das so sein soll.
FHNotifyRBin := SHChangeNotifyRegister(WinHandle,
SHCNF_ACCEPT_INTERRUPTS or SHCNF_ACCEPT_NON_INTERRUPTS, SHCNE_ALLEVENTS, WM_SHELLNOTIFY, 1, stPIDL); Ich deregistriere doch das Event.
Delphi-Quellcode:
if SHChangeNotifyDeregister(MainHandle) then
trotzdem wird FHNotifyRBin incrementiert |
AW: Nach Explorer absturz
Es ist das Event, wo du dein anderes Event/Notifier neu registrieren kannst/musst/solltest/darfst.
z.B. wird das auch verwendet, damit man seine TrayIcons neu registriert, nachdem die Taskleiste neu erstellt wurde. |
AW: Nach Explorer absturz
Zitat:
Habe meinen vorherigen Beitrag nochmal editiert. Könntet ihr mir vielleicht anhand meiner Implementierung zeigen was, wo ich etwas ändern soll. |
AW: Nach Explorer absturz
Würdest du dich da registrieren, bekämst do scheinbar automatisch eine Windows Botschaft sobald der Taskbar gestartet wurde, was nach einem automatischen Neustart des Explorers auch automatisch passiert. Wenn du aus diese Message triggerst, dann bräuchtest du vermutlich deine Warteschleife nicht.
Falls die Warteschleife doch unumgänglich sein sollte, schon mal dran gedacht diese mittels SLeep(1); drin etwas weniger CPU hungrig zu gestalten? |
AW: Nach Explorer absturz
Zitat:
Ich mache es anders.
Delphi-Quellcode:
siehe!repeat HwndTarget := FindWindow('Progman', 'Program Manager'); WinProcessMessages; inc(Counter); until (HwndTarget <> 0) or (Counter = 30000);
Delphi-Quellcode:
Da ist nichts CPU hungrig.
procedure WinProcessMessages;
var ProcMsg: TMsg; begin while PeekMessage(ProcMsg, 0, 0, 0, PM_REMOVE) do begin if (ProcMsg.message = WM_QUIT) then Exit; TranslateMessage(ProcMsg); DispatchMessage(ProcMsg); end; end; Alle Messagen werden weiter behandelt und sollten mit einem Sleep nicht unterbrochen werden. Zitat:
|
AW: Nach Explorer absturz
Ok jetzt verstehe ich was ihr meint.
Habe den SetWinEventHook entfernt. In WM_CREATE registriere ich jetzt die WindowMessage 'TaskbarCreated'
Delphi-Quellcode:
Und gut ist.
case Msg of
WM_CREATE: TaskbarRestart := RegisterWindowMessage('TaskbarCreated'); else if (Msg = TaskbarRestart) then begin MainApp.RegisterRecyleBin(WinHandle); SendMessage(WinHandle, WM_COMMAND, IDM_Restart, 0); end; end; Result := DefWindowProc(WinHandle, Msg, wP, lP); Benötige dann die Schleife nicht mehr. @Michael II, @himitsu Thanks! |
AW: Nach Explorer absturz
Ich weiß noch nicht seit wann
![]() Strg+Shift+F Suchwort: TaskbarCreated Dateifilter: *.pas;*.dfm;*.dpr;*.dpk;*.inc;*.txt Verzeichnisse: $(BDS) mit Unterverzeichnissen Schon findet man
Delphi-Quellcode:
und landet letztendlich z.B. bei Application.OnSettingChange oder besser noch bei ApplicationEvents.OnSettingChange .
else if Cardinal(Message.Msg) = RM_TaskbarCreated then
begin Perform(CM_WININICHANGE, 0, 0); Perform(CM_SYSCOLORCHANGE, 0, 0); Perform(CM_SYSFONTCHANGED, 0, 0); Perform(CM_PARENTCOLORCHANGED, 0, 0); Perform(CM_PARENTFONTCHANGED, 0, 0); Perform(CM_PARENTBIDIMODECHANGED, 0, 0); Perform(CM_PARENTDOUBLEBUFFEREDCHANGED, 0, 0); ... initialization InitProcs; RM_TaskBarCreated := RegisterWindowMessage('TaskbarCreated'); |
AW: Nach Explorer absturz
Cool venice2. Thema abgeschlossen :).
Nur noch eine kurze Frage himitsu... du schreibst: Zitat:
Bei meinem Delphi 14.1/Windows 10 nicht. D läuft zwar nach 'TaskbarCreated' bei vcl.forms.TCustomForm.WndProc (also "if Cardinal(Message.Msg) = RM_TaskbarCreated (TRUE)...") durch, aber nicht bei ApplicationEvents.OnSettingChange. Auch im ApplicationEvents.OnMessage kommt 'TaskbarCreated' nicht an. Was funktioniert: Im ApplicationEvents.OnMessage auf 'TaskbarButtonCreated' checken, also
Delphi-Quellcode:
wobei
procedure TForm1.ApplicationEvents1Message(var Msg: tagMSG;
var Handled: Boolean); begin if msg.message = rm_TaskbarButtonCreated then "tu etwas (zum Beispiel RegisterRecyleBin(..);)" end;
Delphi-Quellcode:
rm_TaskbarButtonCreated := RegisterWindowMessage('TaskbarButtonCreate');
|
AW: Nach Explorer absturz
Noch ein Tipp:
Windows registriert diverse Meldungen wie 'TaskbarCreated', 'TaskbarButtonCreated' und man kann auch eigene Meldungen registrieren (RegisterWindowMessage('MeineEigeneMeldung')). Einem Text wird also durch RegisterWindowMessage eine Nummer zugeordnet. Es gibt auch die Umkehrfunktion: Wenn du in deinem Programm checken willst, ob Windows solche registrierte Nummern/Meldungen M an deine App sendet, dann prüfst du dies mit GetClipboardFormatName(M, ...). In deinem Fall hättest du explorer.exe neu starten und dann in deiner App prüfen können, welche registrierten Windows Meldungen empfangen werden. Dies hätte dich auf die Spur 'TaskbarCreated' oder wenn du TApplicationEvents.OnMessage ausgewertet hättest auf 'TaskbarButtonCreated' geführt. |
AW: Nach Explorer absturz
Zitat:
Mit dem neustarten des Explorers ist so eine Sache denke mal nicht das eine Anwendung den Explorer neustarten sollte das ist eine Sache des Betriebssystem auf etwaige Probleme zu reagieren. Das mit der RegisterWindowMessage ist für mich vollkommen IO und was wichtig ist funktioniert immer. Beim setzen des Hook war das leider nicht gegeben. Nochmals Danke an euch. Hier der Test ![]() 1. Prog starten 2. erstelle imaginäre Text Datei. 3. Lösche diese (Papierkorb nicht löschen) 4. Starte den Windows Explorer neu 5. lösche den Papierkorb 5. Prüfe danach ob sich der Status des Papierkorbs von OTTB64 ändert. Darum ging es mir. EDIT: Nebenbei deine VCL-Lösung würde ich jeden empfehlen der ein Icon zum Tray addiert damit nach einem Absturz des Explorers das Programm weiterhin über das Icon bedienbar bleibt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:27 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz