VB6:跨所有用户 session 的单实例应用程序

标签 vb6 mutex single-instance

我有一个应用程序需要是一个跨 Windows PC 上所有用户 session 的单实例应用程序。到目前为止,我的研究集中在使用互斥锁来实现这一点,但是我遇到了一个我不确定是否真的是问题的问题,我相信这确实是一个最佳实践问题。

首先是代码:

Private Const AppVer = "Global\UNIQUENAME" ' This is not what i am using but the name is unique

Public Sub Main()

    Dim mutexValue As Long

    mutexValue = CreateMutex(ByVal 0&, 1, AppVer)
    If (Err.LastDllError = ERROR_ALREADY_EXISTS) Then
        SaveTitle$ = App.Title
        App.Title = "... duplicate instance."
        MsgBox "A duplicate instance of this program exists."
        CloseHandle mutexValue
        Exit Sub
    End If
    ' Else keep on truckin'

现在,基于 this文章我相信我明白通过将 NULL 指针传递给 CreateMutex 函数,我基本上是在分配与当前登录用户关联的任何安全描述符。

如果这意味着我认为它所做的(我可能需要更多指导)告诉我登录的其他用户将无法“看到”在原始用户 session 下创建的互斥锁,他们也无法创建具有相同名称的互斥锁。

现在,经验证据似乎支持这一点。我使用一个消息框弹出我收到的“LastDLLError”,当另一个用户尝试启动该应用程序时(当它已经在另一个用户帐户下运行时),我会收到一个 ERROR_ACCESS_DENIED 代码。我可以对此进行测试以及 ERROR_ALREADY_EXISTS 代码,并且只是在任一/或上退出。但是,这感觉有点骇人听闻,我想知道是否有人可以提出替代方案。要做的“正确”的事情似乎是将正确的指针传递给 CreateMutex 函数,以便任何用户都具有查看任何现有互斥体(互斥体?)的适当权限,但我不太确定如果没有当前登录用户是管理员(这是 Not Acceptable )。非常感谢任何帮助/指导。提前致谢!

最佳答案

您不需要管理员权限来设置您自己的互斥锁的安全性。这是一个简单的演示应用程序,基本上可以让每个人/完全控制互斥锁。

Option Explicit

Private Const STANDARD_RIGHTS_REQUIRED              As Long = &HF0000
Private Const SYNCHRONIZE                           As Long = &H100000
Private Const MUTANT_QUERY_STATE                    As Long = &H1
Private Const MUTANT_ALL_ACCESS                     As Long = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or MUTANT_QUERY_STATE)
Private Const SECURITY_DESCRIPTOR_REVISION          As Long = 1
Private Const DACL_SECURITY_INFORMATION             As Long = 4

Private Declare Function CreateMutex Lib "kernel32" Alias "CreateMutexA" (lpMutexAttributes As Any, ByVal bInitialOwner As Long, ByVal lpName As String) As Long
Private Declare Function OpenMutex Lib "kernel32" Alias "OpenMutexA" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal lpName As String) As Long
Private Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Private Declare Function InitializeSecurityDescriptor Lib "advapi32.dll" (pSecurityDescriptor As Any, ByVal dwRevision As Long) As Long
Private Declare Function SetSecurityDescriptorDacl Lib "advapi32.dll" (pSecurityDescriptor As Any, ByVal bDaclPresent As Long, pDacl As Any, ByVal bDaclDefaulted As Long) As Long
Private Declare Function SetKernelObjectSecurity Lib "advapi32.dll" (ByVal Handle As Long, ByVal SecurityInformation As Long, pSecurityDescriptor As SECURITY_DESCRIPTOR) As Long

Private Type SECURITY_DESCRIPTOR
    Revision            As Byte
    Sbz1                As Byte
    Control             As Long
    Owner               As Long
    Group               As Long
    pSacl               As Long
    pDacl               As Long
End Type

Private Const MUTEX_NAME            As String = "Global\20b70e57-1c2e-4de9-99e5-20f3961e6812"

Private m_hCurrentMutex         As Long

Private Sub Form_Load()
    Dim hMutex          As Long
    Dim uSec            As SECURITY_DESCRIPTOR

    hMutex = OpenMutex(MUTANT_ALL_ACCESS, 0, MUTEX_NAME)
    If hMutex <> 0 Then
        Call CloseHandle(hMutex)
        MsgBox "Already running", vbExclamation
        Unload Me
        Exit Sub
    End If
    m_hCurrentMutex = CreateMutex(ByVal 0&, 1, MUTEX_NAME)
    Call InitializeSecurityDescriptor(uSec, SECURITY_DESCRIPTOR_REVISION)
    Call SetSecurityDescriptorDacl(uSec, 1, ByVal 0, 0)
    Call SetKernelObjectSecurity(m_hCurrentMutex, DACL_SECURITY_INFORMATION, uSec)
End Sub

Private Sub Form_Unload(Cancel As Integer)
    If m_hCurrentMutex <> 0 Then
        Call CloseHandle(m_hCurrentMutex)
        m_hCurrentMutex = 0
    End If
End Sub

关于VB6:跨所有用户 session 的单实例应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4799954/

相关文章:

c++ - 可以通过其他获取操作获取负载重新排序吗? cppreference 说只有非原子的和宽松的通过 acquire 排序

python - PyQt - 如果它已经在运行,如何检测和关闭 UI?

Android singletop singleinstance 和 singletask

C 多个进程访问的共享内存上的互斥锁

arrays - 在 VBA 中替代使用 Array() 函数?

if-statement - 如何执行相当于 "If something is not X then"的 If 语句

c# - 将函数从 c# 2008 转换为 Vb6.0 错误

linux - 为什么 gdb 中的 pthread_mutex_t 结构全为零?

wix - 是否可以同时只运行一个 WiX msi 实例?

vb6 - VB6 中的 Dir 函数 - 错误 5