|
|
Запрет на повторный запуск Приложения (API)
Option Compare Database
Option Explicit
Private Declare Function GetWindow Lib "user32" (ByVal hwnd As Long, ByVal wCmd As Long) As Long
Private Declare Function IsWindowVisible Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" _
(ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Public Sub AppRunOnceOnlyTest()
On Error GoTo AppRunOnceOnlyTest_Err
Dim l As Integer
Dim s As String
s = Trim(CurrentDb.Properties("AppTitle"))
l = GetCountOfWindows(hWndAccessApp, s)
If l > 1 Then
MsgBox "Приложение: [" & s & "] - уже открыто на вашем компьютере !!!"
Application.Quit acQuitSaveNone
End If
AppRunOnceOnlyTest_Bye:
Exit Sub
AppRunOnceOnlyTest_Err:
If Err.Number = 3270 Then
Else
MsgBox "Error " & Err.Number & vbCrLf & Err.Description & vbCrLf & _
"in procedure AppRunOnceOnlyTest", vbCritical, "Error!"
End If
Resume AppRunOnceOnlyTest_Bye
End Sub
Private Function GetCountOfWindows(lHwnd As Long, sApplicationCaption As String) As Integer
Dim lResult As Long
Dim iCount As Integer
Dim StrAppName As String
On Error GoTo GetCountOfWindows_Err
lResult = GetWindow(lHwnd, 0)
Do Until lResult = 0
If IsWindowVisible(lResult) Then
StrAppName = GetAppName(lResult)
If InStr(1, StrAppName, sApplicationCaption) Then
iCount = iCount + 1
End If
End If
lResult = GetWindow(lResult, 2)
Loop
GetCountOfWindows = iCount
GetCountOfWindows_Bye:
Exit Function
GetCountOfWindows_Err:
MsgBox "Error " & Err.Number & vbCrLf & Err.Description & vbCrLf & _
"in procedure GetCountOfWindows", vbCritical, "Error!"
Resume GetCountOfWindows_Bye
End Function
Private Function GetAppName(lHwnd As Long) As String
Dim LngResult As Long
Dim StrWinText As String * 255
On Error GoTo GetAppName_Err
LngResult = GetWindowText(lHwnd, StrWinText, 255)
GetAppName = Left(StrWinText, LngResult)
GetAppName_Bye:
Exit Function
GetAppName_Err:
MsgBox "Error " & Err.Number & vbCrLf & Err.Description & vbCrLf & _
"in procedure GetAppName", vbCritical, "Error!"
Resume GetAppName_Bye
End Function
Ответил Долгополов Роман в конференции на MAUG
Все достаточно просто решается с использованием Win API ....
Здесь в конструкторе создается скрытое окно с уникальным заголовком, а в деструкторе оно уничтожается.
Теперь там, где хочешь проверить загружена твоя база или нет пиши
Set g_objAccLoaded = New CCheckDBLoaded
Если это первая копия базы, то все пройдет нормально, но если вторая то вылетит ошибка E_DATABASE_ALREADYLOADED.
В обработчике ошибок выведи юзерам какое-нибудь злобное сообщение и завершай программу.
При завершении программы наш глобальный объект g_objAccLoaded будет разрушен и скрытое окно следовательно то-же.
Вся эта стратегия позволяет запускать несколько копий Access, но только одну копию каждой базы. Для каждой базы нужно только
задать уникальное значение в константу UNIQUE_CAPTION. В принципе можно писать любую ахинею в эту константу, я же люблю использовать для таких вещей GUID.
Его можно создать программой GUIDGEN из Visual Studio.
Вроде все.
С уважением Долгополов Роман.
Public Const E_DATABASE_ALREADYLOADED = vbObjectError + 1000
Public g_objAccLoaded AS CCheckDBLoaded
Делаем модуль класса c названием: "CCheckDBLoaded"
Это его текст:
Option Compare Database
Option Explicit
Private Const UNIQUE_CAPTION = "{DE427338-F933-4cf7-9D9F-B15999D7FF66}"
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function CreateWindowEx Lib "user32" Alias "CreateWindowExA" (ByVal dwExStyle As Long, ByVal lpClassName As String, ByVal lpWindowName As String, ByVal dwStyle As Long, ByVal x As Long, ByVal y As Long, ByVal nWidth As Long, ByVal nHeight As Long, ByVal hWndParent As Long, ByVal hMenu As Long, ByVal hInstance As Long, lpParam As Any) As Long
Private Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Private Declare Function DestroyWindow Lib "user32" (ByVal hWnd As Long) As Long
Private Const GWL_HINSTANCE = (-6)
Dim hWnd As Long
Private Sub Class_Initialize()
Dim bLoaded As Boolean
Dim hInstance As Long
If FindWindow(vbNullString, UNIQUE_CAPTION) <> 0 Then
Err.Raise E_DATABASE_ALREADYLOADED, "", "База данных уже загружена"
End If
hInstance = GetWindowLong(Application.hWndAccessApp, GWL_HINSTANCE)
hWnd = CreateWindowEx(0, "BUTTON", UNIQUE_CAPTION, 0, 0, 0, 1, 1, 0, 0, hInstance, 0)
End Sub
Private Sub Class_Terminate()
If hWnd <> 0 Then
DestroyWindow hWnd
End If
End Sub
|
|