CMutexEx Class for Safer & Cooperative Mutex Handling
CMutexEx — A Safe, Cooperative, Cancellable Win32 Mutex Wrapper for VB6 - cross-process coordination made simple
CMutexEx is a small, production-ready class that wraps Windows named mutexes with a clean VB6/twinBASIC API: blocking or cancellable waits, timeouts, short-circuit detection, abandoned owner detection, and optional SDDL-based security. Namespaces map to the real Win32 object namespaces: Global (system-wide) and Local (session-scoped).
Why this class?
Win32 mutex APIs are powerful but tricky (namespaces, UI pumping, abandoned states, security). CMutexEx gives you a small, well-documented surface that “does the right thing” by default—and still lets you opt into advanced features when you need them.
Highlights
Namespaces:Global (machine-wide) or Local (current logon session)
Wait modes: blocking (classic) or cancellable (UI stays responsive via message pump)
Timeouts: INFINITE, finite ms, or zero-wait (“try once”)
Short-circuits: abort acquisition if any named mutex from a list exists (e.g., “Shutdown”)
Abandoned detection: signals when prior owner crashed (WAIT_ABANDONED_0)
Security (optional): pass SDDL to build a DACL (e.g., allow all users to synchronize only)
Events:Acquiring(ByRef Cancel As Boolean), Acquired(IsAbandoned As Boolean), Failed(IsExpected As Boolean)
Timed: finite wait — retry loops, background syncs that should skip when busy
Perpetual: Zero-wait, acquired permanently for the app process lifetime.
? Quick Start
Blocking, infinite wait with short-circuit (critical section):
Code:
Sub Main()
If DbMigrationNeeded Then
With NewCriticalSystemMutex("Database_Migration", "Database_Migration_Complete") ' Get Database Migration mutex or short-circuit if another process performs the migration
If .IsShortCircuited Then
' Database migration completed successfully by another process, continue as normal
ElseIf .IsAcquired Then
' Mutex acquired - perform database migration
MigrateDatabase
Else
' Something else happened! Should abort!!
Err.Raise vbObjectError, , "Migration error!"
End If
End With ' auto-release mutex
End If
End Sub
Private Sub MigrateDatabase()
' DoDatabaseMigrationWorkHere
If NewPerpetualSystemMutex("Database_Migration_Completed") Then ' Perpetual mutexes will NEVER be released until app process terminates
' Migration Completed OK and we acquired a perpetual mutex to signal that no further migrations should be attempted
Else
' Uhoh! Could not acquire mutex!!
Err.Raise vbObjectError, , "Could not acquire migration complete mutex!!
End If
End Sub
Cancellable wait (responsive UI):
Code:
Private WithEvents m As CMutexEx
Private Sub StartWork()
Set m = NewReactiveSystemMutex("Report_Generation")
If m.IsAcquired Then RunReport
End Sub
Private Sub m_Acquiring(Cancel As Boolean)
If UserPressedCancel Then Cancel = True
End Sub
Zero-wait “try once” (single-instance guard):
Code:
Private Sub Form_Load()
With NewZeroWaitSessionMutex("App_Main")
If Not .IsAcquired Then
MsgBox "Already running!", vbExclamation
Unload Me
End If
End With
End Sub
Short-circuit if “Shutdown” mutex exists:
Code:
With NewCriticalSystemIndex("Reindex", Array("Global\Shutdown"))
If .IsShortCircuited Then Exit Sub
If .IsAcquired Then DoReindex
End With
v1.01 — Fixed a bug in short-circuiting logic (using wrong Mutex Name variable).
v1.02 — Fixed a bug with too early LocalFree call - would obfuscate Err.LastDllError result of CreateMutex call and erroneous report error creating mutex instead of waiting for acquire.
v1.03 — Improvements to the demo app to prevent re-entrancy in Cancellable mode. Also add improved comments and messages to the demo.
v2.0 — Major refactor with lots of changes to the available methods, and new CMutexEx factory with helpers for common use cases, improvements to the demo, and some bug fixes.