Setup für Access-Applikationen, Restarbeiten

Autor: Christoph Jüngling, https://www.juengling-edv.de

In diesem Teil widmen wir uns einigen Restarbeiten für das Erstellen eines Setups für Access-Applikationen. Diese Arbeiten sind zwar keineswegs unbedingt notwendig, runden aber unser Setup ab und sorgen daher beim Anwender oder Administrator für ein “gutes Gefühl”. Wir wollen zunächst sicherstellen, dass unsere Applikation nicht läuft, wenn wir sie updaten wollen. Dann unterscheiden wir bei der Installation zwischen Beta- und finaler Version. Und letztlich wollen wir unser Setup dann noch digital signieren.

Läuft die Applikation

Wie können wir sicherstellen, dass die Access-Applikation nicht läuft, wenn wir sie updaten wollen

Prinzip eines “Mutex”

Sicher haben Sie schon bei Setups bemerkt, dass eine Meldung wie diese kam:

Das Setup hat festgestellt, dass die Applikation Xyz noch läuft. Bitte beenden Sie diese und starten Sie dann das Setup erneut.

Dem Anwender ist das natürlich egal, aber der Entwickler fragt sich unweigerlich: “Woher weiß das Setup das eigentlich” Die Frage ist berechtigt, denn einfach mal “nachschauen” ist halt für eine Software nicht ganz so einfach wie für uns.

Das Geheimnis heißt “Mutex”. Das ist die Kurzform von “mutual exclusion”, auf Deutsch “gegenseitiger Ausschluss”, eine beeindruckend gute Bezeichnung für diesen Mechanismus.

Denn die Setupdurchführung und das laufende Programm schließen sich gegenseitig aus. Während die ACCDB aktiv ist, sollte man sie nicht per Setup austauschen.

Um dies zu nutzen, benötigen wir also sowohl in der Applikation als auch im Setup jeweils einen Mechanismus, der den Mutex setzen, löschen und überprüfen kann. Unsere Access-Applikation erzeugt den Mutex beim Start und löscht ihn kurz vor dem Ende.

Das Setup wiederum überprüft nur, ob es ihn gibt. Falls ja, kommt eine Meldung wie oben gezeigt, falls nein, läuft das Setup einfach weiter.

Das lässt sich in InnoSetup sogar soweit automatisieren, dass ein von der Accdb angestoßenes Update automatisch abläuft.

Mutex-Klasse (VBA)

Mit Hilfe eines kurzen Codesegments schaffen wir es, den Mutex beim Starten unserer Access-Applikation zu erzeugen. Das übernimmt in meinen Projekten immer eine Klasse, die ich eigens dafür geschrieben habe.

Es müsste natürlich keine Klasse sein, eine Sub-Prozedur täte es auch, aber mit der Klasse haben wir den Vorteil, dass wir mit einer Einheit beide Aktionen erledigen können: Erzeugen und Löschen des Mutex wird innerhalb der Klasse durchgeführt – und zwar über den Konstruktor Initialize und den Destruktor Terminate der Klasse.

Zur Integration in die Applikation müssen neben der Klasse selbst nur noch eine Deklaration und zwei Zeilen Code eingefügt werden.

Schauen wir uns zunächst die Mutex-Klasse an. Besonders aufwändig ist sie nicht (siehe Listing 1).

''''
'' Manage an Application Mutex for the current application
'' @remarks  Mutex name = APP_MUTEX
'' @author   Christoph Juengling <christoph@juengling-edv.de>
'' @link   https://gitlab.com/juengling/vb-and-vba-code-library
Option Explicit
#If VBA7 Then
Private Declare PtrSafe Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Any, _
      ByVal bInitialOwner As Long, ByVal lpName As String) As LongPtr
Private Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As LongPtr) As Long
Private Declare PtrSafe Function ReleaseMutex Lib "kernel32" (ByVal hMutex As LongPtr) As Long
#Else
Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Any, _
     ByVal bInitialOwner As Long, ByVal lpName As String) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function ReleaseMutex Lib "kernel32" (ByVal hMutex As Long) As Long
#End If
Private m_lMutexHandle As Long
Private Sub Class_Initialize()
     m_lMutexHandle = 0
     CreateMyMutex
End Sub
Private Sub Class_Terminate()
     ReleaseMyMutex
End Sub
'' CreateMutex the Mutex
Public Sub CreateMyMutex()
     m_lMutexHandle = CreateMutex(ByVal CLng(0), CLng(1), APP_MUTEX)
End Sub
''''
'' ReleaseMutex the Mutex and close handle
''
Public Sub ReleaseMyMutex()
     If m_lMutexHandle > 0 Then
         ReleaseMutex m_lMutexHandle
         CloseHandle m_lMutexHandle
         m_lMutexHandle = 0
     End If
End Sub

Listing 1: Klasse zum Nutzen eines Mutex

Die Erzeugung passiert in Class_Initialize, die Zerstörung in Class_Terminate. Der einzige Bezug in unsere Applikation ist hier die Nutzung der globalen Konstanten APP_MUTEX. Diese deklariert den Namen des Mutex:

Public Const APP_MUTEX = "Mein Name ist Hase"

Die Bezeichnung sollte sinnvollerweise dem Namen der Applikation entsprechen, so dass man natürlich auch APP_NAME verwenden kann.

Wichtig ist die Einzigartigkeit im Hinblick auf andere Applikationen! Eine solche Deklaration muss natürlich namensgleich später auch im InnoSetup-Skript enthalten sein, damit Setup und Applikation über dieselbe Bezeichnung verfügen.

Nun müssen wir nur noch dafür sorgen, dass

  • eine Modul-Variable für die Instanz der Klasse existiert,
  • diese beim Start instanziiert wird und
  • vor dem Beenden der Applikation zerstört wird.

Das ist ebenfalls trivial. In einem Modul, in dem vielleicht noch weitere globale Deklarationen stehen, fügen wir diese Zeile ein:

Public mutex As clsMutex

In dem Code für die Initialisierung:

Set mutex = New clsMutex

Und für das Beenden:

Set mutex = Nothing

Das war doch einfach, oder Streng genommen ist die letzte Aktion nicht nötig, da der Mutex mit dem Beenden der Applikation automatisch gelöscht wird.

Den Mutex in InnoSetup eintragen

In InnoSetup ist die Sache sogar noch einfacher, denn der ganze Mechanismus zum Überprüfen und Reagieren ist dort bereits enthalten, Code müssen wir dafür nicht schreiben.

Wir müssen nur dafür sorgen, dass InnoSetup den Namen des Mutex erfährt. Wie schon erwähnt, muss diese Deklaration natürlich identisch mit der Konstanten aus unserer Applikation sein, und das betrifft auch die Groß-/Kleinschreibung!

Sie haben das Ende des frei verfügbaren Textes erreicht. Möchten Sie ...

TestzugangOder bist Du bereits Abonnent? Dann logge Dich gleich hier ein. Die Zugangsdaten findest Du entweder in der aktuellen Print-Ausgabe auf Seite U2 oder beim Online-Abo in der E-Mail, die Du als Abonnent regelmäßig erhältst:

Schreibe einen Kommentar