前段时间,我问过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实例。
我需要将该函数的范围限制为当前正在运行的会话。根据{{3}},有一个名为SessionID的类属性。我可以使用该属性并将其与当前会话的ID进行比较,以限制函数的计数,或者有更好的方法吗?
任何建议都将不胜感激。
谢谢!
以下是蒂姆建议的解决方案代码。注意我将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
答案 0 :(得分:2)
'get process owner username and domain
Dim strUser, strDomain
objItem.getOwner strUser, strDomain
MsgBox strUser & ", " & strDomain