如何限制单个 Windows 会话中运行的应用程序实例的数量?

发布于 2024-12-16 12:57:43 字数 2947 浏览 0 评论 0原文

前段时间我问过限制 Windows 中同时运行的 Excel 实例的数量

感谢我在 StackOverflow.com 上获得的帮助,我能够组合以下函数,如果已经有另一个 Excel 实例正在运行,则可以关闭启动的任何 Excel 实例。

Private Function KillDuplicateProcesses() As Boolean

    Dim objWMIService As Object
    Dim colItems As Variant
    Dim objItem As Object
    Dim intCount As Integer

    Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
    Set colItems = objWMIService.InstancesOf("Win32_Process")
    For Each objItem In colItems
        intCount = intCount + Abs(LCase(objItem.Name) = "excel.exe")
        If intCount > 1 Then
            MsgBox "Excel is already running." & vbCrLf & vbCrLf & _
            "To open a file use " & IIf(Application.Version >= 12, "Office Button", "File") & " > Open (Ctrl + O).", vbCritical
            KillDuplicateProcesses = True
            Application.Quit
            Exit For
        End If
    Next

End Function

问题是,如果用户以管理员身份登录远程桌面会话,则该用户帐户可以看到所有其他用户以及他们正在运行的进程。因此,如果另一个用户登录到同一台计算机并正在运行 Excel,该函数也会对这些实例进行计数,并关闭刚刚启动的 Excel 实例。

我需要将该函数的范围限制为当前正在运行的会话。根据 MSDN 文档 有一个名为 SessionID 的类属性。我可以使用该属性并将其与当前会话的 ID 进行比较以限制函数的计数,还是有更好的方法来做到这一点?

任何建议将不胜感激。

谢谢!

下面是根据 Tim 建议的解决方案代码。注意我将 GetOwner 属性与 Environ UserName 和 UserDomain 进行比较。 Environ 被认为是不可靠的,因为它可以由用户更改。

Private Function KillDuplicateProcesses() As Boolean

    Dim objWMIService As Object
    Dim colItems As Variant
    Dim objItem As Object
    Dim intCount As Integer
    Dim strProcessUser As Variant
    Dim strProcessDomain As Variant

    Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
    Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'excel.exe'")

    If colItems.Count > 1 Then

        For Each objItem In colItems

            strProcessUser = ""
            strProcessDomain = ""
            objItem.GetOwner strProcessUser, strProcessDomain
            If IsNull(strProcessUser) Then strProcessUser = ""
            If IsNull(strProcessDomain) Then strProcessDomain = ""

            intCount = intCount + Abs(strProcessUser = Environ("UserName") _
                And strProcessDomain = Environ("UserDomain"))
            If intCount > 1 Then
                MsgBox "You cannot run more than one instance of Excel while iTools is activated." & vbCrLf & vbCrLf & _
                "To open a file use " & IIf(Application.Version >= 12, "Office Button", "File") & " > Open (Ctrl + O).", vbCritical
                KillDuplicateProcesses = True
                Application.Quit
                Exit For
            End If

        Next

    End If

End Function

Some time ago on I asked about limiting the number of instances of Excel being run concurrently in Windows.

Thanks to the help I got on StackOverflow.com I was able to put together the following function that shuts down any instance of Excel that is launched if there is already another instance of Excel running.

Private Function KillDuplicateProcesses() As Boolean

    Dim objWMIService As Object
    Dim colItems As Variant
    Dim objItem As Object
    Dim intCount As Integer

    Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
    Set colItems = objWMIService.InstancesOf("Win32_Process")
    For Each objItem In colItems
        intCount = intCount + Abs(LCase(objItem.Name) = "excel.exe")
        If intCount > 1 Then
            MsgBox "Excel is already running." & vbCrLf & vbCrLf & _
            "To open a file use " & IIf(Application.Version >= 12, "Office Button", "File") & " > Open (Ctrl + O).", vbCritical
            KillDuplicateProcesses = True
            Application.Quit
            Exit For
        End If
    Next

End Function

The problem is that if a user is logged onto a remote desktop session as an administrator, that user account can see all of the other users and the processes that they have running. So if another user is logged onto the same machine and is running Excel, the function counts those instances as well and shuts down the instance of Excel that has just been launched.

I need to limit the scope of that function to the currently running session. According to MSDN documentation there is a class property called SessionID. Can I use that property and compare it against the current session's ID to limit what the function counts, or is there a better way to do it?

Any suggestions would be greatly appreciated.

Thanks!

Below is the solution code per Tim's suggestion. Note I am comparing the GetOwner properties against Environ UserName and UserDomain. Environ is considered unreliable because it can be changed by the user.

Private Function KillDuplicateProcesses() As Boolean

    Dim objWMIService As Object
    Dim colItems As Variant
    Dim objItem As Object
    Dim intCount As Integer
    Dim strProcessUser As Variant
    Dim strProcessDomain As Variant

    Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
    Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'excel.exe'")

    If colItems.Count > 1 Then

        For Each objItem In colItems

            strProcessUser = ""
            strProcessDomain = ""
            objItem.GetOwner strProcessUser, strProcessDomain
            If IsNull(strProcessUser) Then strProcessUser = ""
            If IsNull(strProcessDomain) Then strProcessDomain = ""

            intCount = intCount + Abs(strProcessUser = Environ("UserName") _
                And strProcessDomain = Environ("UserDomain"))
            If intCount > 1 Then
                MsgBox "You cannot run more than one instance of Excel while iTools is activated." & vbCrLf & vbCrLf & _
                "To open a file use " & IIf(Application.Version >= 12, "Office Button", "File") & " > Open (Ctrl + O).", vbCritical
                KillDuplicateProcesses = True
                Application.Quit
                Exit For
            End If

        Next

    End If

End Function

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

々眼睛长脚气 2024-12-23 12:57:43
'get process owner username and domain
Dim strUser, strDomain
objItem.getOwner strUser, strDomain
MsgBox strUser & ", " & strDomain
'get process owner username and domain
Dim strUser, strDomain
objItem.getOwner strUser, strDomain
MsgBox strUser & ", " & strDomain
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文