Registriert seit: 26.09.2015
Version(en): 2013
Hallo zusammen Folgenden Code-Schnipsel, welcher im Access läuft, möchte ich gerne in Excel haben. Dabei soll nach diversen Rcordsets, Close usw. das Access heruntergefallen werden, wenn es "hängen" geblieben ist. Da untenstehender Code (64 bit) nur im Access selber läuft, hoffe ich, dass ihr mit 64 bit auch eine Möglichkeit kennt, wo vom Excel-VBA aus eine bekannte (Laufwerk und Name) Access-DB heruntergefahren werden kann, wenn sie trotz .Close nicht vollständig heruntergeladen werden könnte. Es gibt Beispiele im Internet, jedoch nur ohne PtrSafe. Vielen Dank für Eure Unterstützung. Gruss Stefan Code: Option Explicit
Private Const PROCESS_TERMINATE As Long = &H1 Private Declare PtrSafe Function GetCurrentProcess Lib "kernel32" () As LongPtr Private Declare PtrSafe Function GetCurrentProcessId Lib "kernel32" () As Long Private Declare PtrSafe Function OpenProcess Lib "kernel32" _ (ByVal dwDesireAccess As Long, _ byVal bInDecitHandle As Boolean, _ ByVal dwProcessId As Long) As LongPtr Private Declare PtrSafe Function TerminateProcess Lib "kernel32" _ (byVal hProcess AS LongPtr, ByVal uExitCode AS Long) As Boolean Private Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As longPtr) AS Boolean Private Sub TestClose() Dim processId As Long Dim processHandle As LongPtr processId = GetCurrentProcessID processHandle = OpenProcess(PROCESS_TERMINATE, False, processID) TerminateProcess processHandle, 0 CloseHandle processHandle End Sub
Registriert seit: 22.09.2024
Version(en): 2010
04.11.2024, 16:52
(Dieser Beitrag wurde zuletzt bearbeitet: 04.11.2024, 16:52 von knobbi38.)
Zitat:Dabei soll nach diversen Rcordsets, Close usw. das Access heruntergefallen werden, wenn es "hängen" geblieben ist. Der VBA-Code ist nicht Access spezifisch und kann eigentlich jeden Prozess terminieren, wenn man dazu die Berechtigung hat und die richtig ProezessID hat. Allerdings sollte man wissen, was man da macht, ansonsten kann eine Datenbank auch mal schnell beschädigt werden, wenn man den Access-Prozess einfach mal terminiert. Am einfachsten ist es, das mit dem Taskmanager zu machen oder man verwendet dafür die Kommandozeile im Admin-Modus: https://dashdot.de/2018/12/21/prozess-pe...en-killen/Dafür in Excel ein Makro zu erstellen, halte ich nicht für sinnvoll.
Registriert seit: 26.09.2015
Version(en): 2013
Auf jeden Fall schließe ich mit VBA die Recordset (SELECT ...)-Anweisung aus Excel auf dem ordentlichen Weg mit RS.Close und DB.Close sowie Set RS = Nothing und DB = Nothing. Doch Leider kommt es immer wieder mal vor, dass sich trotz sorgfältigem Schliessen der Access-Datenbank von Excel aus trotzdem nicht herunterfahren und nur in diesem Fall würde ich es gerne via dem Prozess Handle diese Access-Datenbank schliessen können. Also so sauber als möglich mit dem Risiko das erwähnt wurde. Zu diesem Zweck müsste ich allerdings die Handle-ID kennen, doch wie komme ich VBA-mäßig daran?
Registriert seit: 18.10.2020
Version(en): 365
04.11.2024, 20:10
(Dieser Beitrag wurde zuletzt bearbeitet: 04.11.2024, 20:10 von Warkings.)
(04.11.2024, 19:13)Stefan1 schrieb: ... in diesem Fall würde ich es gerne via dem Prozess Handle diese Access-Datenbank schliessen können. Also so sauber als möglich mit dem Risiko das erwähnt wurde. Zu diesem Zweck müsste ich allerdings die Handle-ID kennen, doch wie komme ich VBA-mäßig daran? Code: Option Explicit
Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" _ (ByVal hWnd As LongPtr, ByVal lpString As String, ByVal cch As Long) As Long Private Declare PtrSafe Function GetWindowThreadProcessId Lib "user32" _ (ByVal hWnd As LongPtr, lpdwProcessId As Long) As Long Private Declare PtrSafe Function EnumWindows Lib "user32" _ (ByVal lpEnumFunc As LongPtr, ByVal lParam As LongPtr) As Long
' Globale Variable für den Datenbanknamen und die Prozess-ID Private gDatabaseFileName As String Private gFoundProcessId As Long
Public Function GetAccessProcessIdByTitle(databaseFileName As String) As Long ' Setzt den Dateinamen und initialisiert die Prozess-ID gDatabaseFileName = databaseFileName gFoundProcessId = 0 ' Startet die Fenstertitel-Suche EnumWindows AddressOf EnumWindowsProc, 0 ' Gibt die gefundene Prozess-ID zurück (0, falls keine gefunden wurde) GetAccessProcessIdByTitle = gFoundProcessId End Function
Private Function EnumWindowsProc(ByVal hWnd As LongPtr, ByVal lParam As LongPtr) As Long Dim processId As Long Dim windowTitle As String * 255 Dim titleLength As Long ' Holt den Fenstertitel titleLength = GetWindowText(hWnd, windowTitle, Len(windowTitle)) windowTitle = Left(windowTitle, titleLength)
' Überprüft, ob der Datenbankname im Fenstertitel enthalten ist If InStr(1, windowTitle, gDatabaseFileName, vbTextCompare) > 0 Then ' Holt die Prozess-ID des Fensters GetWindowThreadProcessId hWnd, processId If processId > 0 Then gFoundProcessId = processId EnumWindowsProc = 0 ' Beendet die Schleife, da die Prozess-ID gefunden wurde Exit Function End If End If EnumWindowsProc = 1 ' Fortsetzen der EnumWindows-Schleife End Function
Sub TestGetAccessProcessId() Dim processId As Long processId = GetAccessProcessIdByTitle("<full database file name>") If processId > 0 Then MsgBox "Die Prozess-ID des Access-Prozesses ist: " & processId Else MsgBox "Kein Access-Prozess mit dieser Datenbank gefunden." End If End Sub
Folgende(r) 1 Nutzer sagt Danke an Warkings für diesen Beitrag:1 Nutzer sagt Danke an Warkings für diesen Beitrag 28
• Stefan1
Registriert seit: 26.09.2015
Version(en): 2013
Guten Tag Warkings Perfekt. Vielen Dank. Habe den Code etwas modifiziert und er funktioniert einwandfrei, wenn sie die Datenbank einfach nicht ordentlich schliessen lässt. Nochmals vielen Dank, einfach Super. Gruss Stefan1
Registriert seit: 22.09.2024
Version(en): 2010
05.11.2024, 14:40
(Dieser Beitrag wurde zuletzt bearbeitet: 05.11.2024, 14:40 von knobbi38.)
Hallo Stefan, Zitat:Doch Leider kommt es immer wieder mal vor, dass sich trotz sorgfältigem Schliessen der Access-Datenbank von Excel aus trotzdem nicht herunterfahren ... Also wenn das der Fall ist, ist in deinem Code auf jeden Fall ein Fehler und den solltest du beheben, anstatt im Nebel rumzustochern; alles andere kann deine DB zerstören und inkonsistent machen !!! Zitat:... in diesem Fall würde ich es gerne via dem Prozess Handle diese Access-Datenbank schliessen können. Wenn du per DAO auf die Datenbank-Datei zugreifst, gibt es keine Access-Anwendung, die du terminieren könntest. So etwas kann nur vorkommen, wenn du per Automation auf Access zugreifst. DAO läuft außerdem, anders als ADO, InProzess, womit du die Excel-Anwendung abschießt. Wer macht den sowas? Bring deinen Code i.O. und gut ist. Tip: immer alle Fehler abfangen und im Fehlerfall auch das DAO.Error Objekt auswerten. Gruß Knobbi38
Folgende(r) 1 Nutzer sagt Danke an knobbi38 für diesen Beitrag:1 Nutzer sagt Danke an knobbi38 für diesen Beitrag 28
• Stefan1
Registriert seit: 26.09.2015
Version(en): 2013
Guten Tag miteinander Es läuft jetzt einwandfrei und sehr selten. Es handelt sich um einen bekannten Fehler von Access, den man nicht beheben kann. Mit Unterstützung konnte ich jetzt die Lösung in seltenen Fällen (ich protokollere es) nun implementieren. Normalerweise reicht auch mit DAO das problemlose Schliessen von der Access-Datenbank. Jedoch in selten Fällen, die nicht kontrolliert werden können, muss der Anwender dann den Prozess forciert beenden, wenn er sich daran stösst, dass Access im Hintergrund offen bleibt. Selbst wenn der Anwendung den PC herunterfährt, kommt es letztendlich zu dieser Hammermethode. Und ja, die Datenbank kann korrupt gehen. Code: Sub TerminateAccessProcess() Dim processId As Long Dim processHandle As LongPtr processId = GetAccessProcessIdByTitle(CON_DATA_02_A_COCKPIT) If processId > 0 Then 'MsgBox "Die Prozess-ID des Access-Prozesses ist: " & processId processHandle = OpenProcess(PROCESS_TERMINATE, False, processId) TerminateProcess processHandle, 0 CloseHandle processHandle Call FehlerLog("TerminateAccessProcess") Else 'MsgBox "Kein Access-Prozess mit dieser Datenbank gefunden." End If End Sub
Registriert seit: 22.09.2024
Version(en): 2010
Zitat:Es handelt sich um einen bekannten Fehler von Access Hast du für diese Behauptung eine verlässliche Quelle, oder woher beziehst du dein Wissen? Zitat:Jedoch in selten Fällen, die nicht kontrolliert werden können, muss der Anwender dann den Prozess forciert beenden, wenn er sich daran stösst, dass Access im Hintergrund offen bleibt. Nochmal: Einen separaten Prozess "Access" gibt es bei DAO nicht! Es gibt nur einen separaten Access-Prozess, wenn du per Automation auf Access zugreifst, was aber für einen reinen Datenzugriff aus Excel heraus nicht notwendig ist - und ja, bei Automation muß man sehr vorsichtig sein, wenn man das stabil hinbekommen möchte. Da muß jedes Objekt in der richtigen Reihenfolge beendet und freigegeben werden, sonst kommt es zu dem von dir beschrieben Effekt. Also nicht einfach diese Dinge durcheinander bringen und vermischen. Die haben miteinander nichts, aber auch gar nichts zu tun. Zitat:Selbst wenn der Anwendung den PC herunterfährt, kommt es letztendlich zu dieser Hammermethode. Aber dann wirst du darauf auch hingewiesen, daß da noch ein Prozess aktiv ist. PC herunterfahren um Fehlersymptome zu beheben, sollte in der heutigen Zeit nicht mehr notwendig sein, das sind eher Relikte von früher. Gruß Knobbi38
Registriert seit: 26.09.2015
Version(en): 2013
Guten Tag knobbi38 Ich habe hier zwei Beispiele eingestellt (es gibt noch mehr): Prüfen, ob ein Task noch läuft und ggf. beenden https://www.vbarchiv.net/tipps/tipp_475-...enden.htmlWindows API in VBA – Terminate Process – Workaround für Access Hängt beim Beenden (von Better VBA 0 - Einleitung) https://www.youtube.com/watch?v=nlux9J8nWxkSelbstverständlich sollte die verwendete Programmierung so optimal wie möglich sein, doch es lässt sich nicht immer vermeiden, dass nicht nur Access quasi "hängen" bleibt. Selbst wenn Access oder auch Excel geöffnet wird und kaum VBA angewendet wird. Microsoft Office-Programme sind von Natur aus nicht immer stabil, dazu kommen Netzwerkinstabilitäten usw. Eine "abgestürzte" MS Office-Anwendung lässt sich manchmal nur noch mit dem Task-Manager beenden, da hilft einfach nichts mehr. Seit meinem Einbau dieser "Hammer"-Methode hatte ich noch kein protokollierter Fall, obwohl Excel hier sehr häufig pro Tag gebraucht wird. Ich bin also optimistisch, dass es sehr selten vorkommt. Die Access-Datenbank lässt sich einfach wiederherstellen, falls schwer beschädigt. Hoffen wir das es nie wird der Fall sein. Danke für Unterstützung. Gruss Stefan1
Registriert seit: 22.09.2024
Version(en): 2010
05.11.2024, 16:36
(Dieser Beitrag wurde zuletzt bearbeitet: 05.11.2024, 16:51 von knobbi38.)
Hallo Stefan, Zitat:Microsoft Office-Programme sind von Natur aus nicht immer stabil, dazu kommen Netzwerkinstabilitäten usw. Das ist doch MS Bashing, entbehrt jeder Grundlage und damit FAKE! Deine Quelle belegen keines Falls deine Behauptung, sondern du vergleichst hier Äpfel mit Birnen - InProzess-Zugriff mit DAO und eine Access-Anwendung. Im Übrigen ist der beschriebene Fehler aus dem 2.Link ein nachvollziehbares Verhalten unter sehr konkreten Umständen, die i.d.R. nur sehr selten eintreten. Hierbei wird der Fehler durch die Anwendung MS-Access verursacht und nicht durch einen Datenzugriff auf eine Datenbank - Datei. Bevor du so einen Workaround in deine Anwendung einbaust, solltest du dir mal alle Informationen zu dem Problem ansehen und vor allem erstmal verstehen, was da programmiert wird, wie der genaue Ablauf dabei ist und welche Auswirkungen das hat. Einfach nur einen Prozess zu terminieren, reicht hier übrigens nicht. Die entsprechenden Lockdateien müssen u.U. ebenfalls entfernt werden! Das Alles trifft in deinem Fall überhaupt nicht zu. Du kannst ja machen, was dir gefällt und das bleibt dir überlassen, aber als Admin oder IT-Verantworlicher würde wahrscheinlich so eine VBA-Programmierung bei einer QS-Prüfung/Audit niemals zur Installation freigegeben werden. Gruß Knobbi38
|