VB6:跨所有用户会话的单实例应用程序
我有一个应用程序需要成为 Windows PC 上所有用户会话的单实例应用程序。到目前为止,我的研究主要集中在使用互斥锁来完成此任务,但我遇到了一个问题,我不确定这是否真的是一个问题,我相信这确实是一个最佳实践问题。
首先是代码:
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'
现在,基于 这篇文章我相信我明白,通过将 NULL 指针传递给上面的 CreateMutex 函数,我基本上是在分配与当前登录用户关联的任何安全描述符。
如果这意味着我认为它的作用(我可能需要更多指导),这告诉我登录的其他用户将无法“看到”在原始用户会话下创建的互斥体,也无法创建互斥体同名的互斥体。
现在,经验证据似乎支持了这一点。我使用消息框弹出我收到的“LastDLLError”,当另一个用户尝试启动该应用程序时(虽然它已经在另一个用户帐户下运行),我会收到 ERROR_ACCESS_DENIED 代码。我可以对此进行测试以及 ERROR_ALREADY_EXISTS 代码,并且只需退出即可。然而,这感觉有点黑客,我想知道是否有人可以提出替代方案。 “正确”的做法似乎是将正确的指针传递给 CreateMutex 函数,以便任何用户都有适当的权限来查看任何现有的互斥体(mutices?),但我不太确定如果没有当前的互斥体,这是否可能登录用户是管理员(这是不可接受的)。非常感谢任何帮助/指导。提前致谢!
I have an application that needs to be a single-instance app across all user sessions on a Windows PC. My research thus far has centered around using a mutex to accomplish this, but I am having an issue that I am not sure is really an issue, this is really a best-practice question I believe.
Here's the code first of all:
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'
Now, based on this article I believe I understand that by passing the NULL pointer to the CreateMutex function as I am above I'm basically assigning whatever security descriptor is associated with the currently logged in user.
If that means what I think it does (I may need more guidance here) that tells me that other users who log in will not be able to "see" the mutex created under the original user's session, nor will they be able to create a mutex with the same name.
Now, emperical evidence seems to back this up. I used a message box to pop the "LastDLLError" I was receiving, and when another user attempted to launch the application (while it was already running under another user account) I would receive an ERROR_ACCESS_DENIED code. I am OK with testing against this along with the ERROR_ALREADY_EXISTS code and just exiting on either/or. However, this feels sort of hackish and I'm wondering if someone can suggest an alternative. The "right" thing to do seems to be to pass the proper pointer to the CreateMutex function such that any user has the proper permissions to view any existing mutexes (mutices?), but I'm not so sure this is possible without the currently logged in user being an admin (which is unacceptible). Any assistance/guidance is greatly appreciated. Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您不需要管理员权限即可为自己的互斥体设置安全性。这是一个简单的演示应用程序,基本上为每个人/完全控制互斥体。
You don't need admin priveleges to set security on you own mutexes. Here is a simple demo app that basicly gives Everyone/Full control to the mutex.
去年年底我在 VB6 中寻找类似的解决方案。当时我找不到任何 VB6 应用程序跨用户边界通信的示例,因此我不得不编写自己的示例。
请参阅:通过信号量进行进程间通信
您可以使用该类来创建和检查全局信号量,它会告诉您您的应用程序是否已在任何用户下运行。我没有查看 Mutex API,但它们的用法非常相似。如果您已经编写了一些互斥体代码,则您需要转置 GetSecurityDescriptor 函数。
I was looking for a similar solution in VB6 late last year. At the time I was unable to find any examples of VB6 apps communicating across the user boundary, so I had to write my own.
See: Interprocess Communication via Semaphores
You can use the class to create and check for a global semaphore which will tell you if your app is already running under any user. I didn't look at the Mutex APIs but their usage is very similar. The GetSecurityDescriptor function is what you'll want to transpose if you've already got some Mutex code written.
我认为你的直觉是完全正确的。我不知道为什么从 ERROR_ACCESS_DENIED 推断其他进程具有互斥体是不安全的,因此实际上它与 ERROR_ALREADY_EXISTS 相同(在这种情况下)。但同时,它感觉不完全正确。
正如您所建议的,设置适当的安全描述符确实是正确的方法。 MSDN 表示,授予 MUTEX_ALL_ACCESS 权限会增加用户必须成为管理员的风险,我认为您确实需要 MUTEX_ALL_ACCESS。但根据我的经验,它对于非管理员来说效果很好。
你的问题引起了我的足够兴趣,做了一个快速测试。这意味着我有一些源代码,所以它是:
I think your instincts are exactly right. I don't know any reason why it wouldn't be safe to infer from ERROR_ACCESS_DENIED that some other process has the mutex, so effectively it's the same as ERROR_ALREADY_EXISTS (in this context.) But at the same time, it doesn't feel quite right.
As you suggest, setting a proper security descriptor is indeed the right way to do it. MSDN says that granting MUTEX_ALL_ACCESS privileges increases the risk that the user will have to be an admin, and I think you do need MUTEX_ALL_ACCESS. But in my experience it works fine for non-admins.
Your question intrigued me enough do a quick test. That means I have some source code, and so here it is: