【问题标题】:How can I limit the number of instances of an application being run in a single Windows session?如何限制在单个 Windows 会话中运行的应用程序实例的数量?
【发布时间】:2011-11-15 19:10:26
【问题描述】:

前段时间我问过limiting the number of instances of Excel being run concurrently in Windows

感谢我在 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 documentation,有一个名为 SessionID 的类属性。我可以使用该属性并将其与当前会话的 ID 进行比较以限制函数的计数,还是有更好的方法来做到这一点?

任何建议将不胜感激。

谢谢!

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

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

【问题讨论】:

    标签: windows excel vba


    【解决方案1】:
    'get process owner username and domain
    Dim strUser, strDomain
    objItem.getOwner strUser, strDomain
    MsgBox strUser & ", " & strDomain
    

    【讨论】:

    • 感谢蒂姆的建议。我正在尝试并与 Environ.UserName 和 Environ.UserDomainName 进行比较。似乎可以工作,但我需要进行更多测试。
    • 根据您的建议,我发布了 air code(未经测试)作为对我的问题的更新。
    • 您的建议有效,尽管为每个进程调用 GetOwner 非常慢,因此我通过添加 where 子句来限制 Win32_Process 查询,使其仅返回 Name = "excel.exe" 的进程,从而显着提高性能。我将解决方案代码放在更新的问题中。谢谢蒂姆。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 2012-01-27
    • 2011-09-02
    相关资源
    最近更新 更多