windows WshShell.AppActivate 在简单的 vbs 脚本中似乎不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/23165377/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WshShell.AppActivate doesn't seem to work in simple vbs script
提问by user3550756
total vbs scripting newb here. I'm trying to automate closing a certain open window, namely a program called HostsMan. This is on Windows 8.1 Pro 64 bit, and this is what my script currently looks like:
总 vbs 脚本 newb 在这里。我正在尝试自动关闭某个打开的窗口,即一个名为 HostsMan 的程序。这是在 Windows 8.1 Pro 64 位上,这就是我的脚本目前的样子:
Set WshShell = CreateObject("WScript.Shell")
WshShell.AppActivate "HostsMan"
WshShell.SendKeys "%{F4}"
The second line doesn't seem to work. I know line 3 works because it activates the Windows shutdown menu. Is there something I'm missing?
第二行似乎不起作用。我知道第 3 行有效,因为它激活了 Windows 关机菜单。有什么我想念的吗?
Update/more info: Manually entering alt-F4 does close it, so I know this should work. I also tested this script with other open windows and they close just fine. Additionally, HostsMan is opened with Admin privileges, so I tried running the script as a task set with highest privileges to see if that would do it, and still no go. But that does work with other open windows running with Admin privileges. Frustrating!
更新/更多信息:手动输入 alt-F4 会关闭它,所以我知道这应该有效。我还用其他打开的窗口测试了这个脚本,它们关闭得很好。此外,HostsMan 以管理员权限打开,因此我尝试将脚本作为具有最高权限的任务集运行,以查看是否可以执行此操作,但仍然没有成功。但这确实适用于以管理员权限运行的其他打开的窗口。令人沮丧!
回答by Bond
I've tried it, too, and couldn't get it to work. There must be something about the window class, perhaps, where AppActivate
doesn't see it as a top-level window?
我也试过了,还是不行。一定有关于窗口类的东西,也许,哪里AppActivate
不把它看作是一个顶级窗口?
In any event, AppActivate
also lets you pass the process ID instead of the window title. When I installed HostsMan, the process name was hm.exe
, so I'll use that in my example below.
在任何情况下,AppActivate
还允许您传递进程 ID 而不是窗口标题。当我安装 HostsMan 时,进程名称是hm.exe
,所以我将在下面的示例中使用它。
Set Processes = GetObject("winmgmts:").InstancesOf("Win32_Process")
For Each Process In Processes
If StrComp(Process.Name, "hm.exe", vbTextCompare) = 0 Then
' Activate the window using its process ID...
With CreateObject("WScript.Shell")
.AppActivate Process.ProcessId
.SendKeys "%{F4}"
End With
' We found our process. No more iteration required...
Exit For
End If
Next
回答by hollopost
To solve the problem of AppActivate
you have to use loop and if condition statement to check if the active windows is the target windows or not because sometime you deselect or the system deselect the target windows before execute the sendkeys directly so you got error.
要解决AppActivate
您必须使用循环和 if 条件语句来检查活动窗口是否为目标窗口的问题,因为有时您在直接执行发送键之前取消选择或系统取消选择目标窗口,因此您会出错。
I create this tight strict way
我创造了这种严格的方式
Set WshShell = CreateObject("WScript.Shell")
for i=0 to 300 ' this loop will continue about 30 sec if this not enough increase this number
Rtn=WshShell.AppActivate("HostsMan") ' HostMan have to be the windows title of application or its process ID
If Rtn = True Then
WshShell.SendKeys "%{F4}" ' send key to click ALT+F4 to close
wscript.sleep 100 ' stop execute next line until finish close app
Rtn=WshShell.AppActivate("HostsMan")
If Rtn=False Then ' using nested If to sure of selected windows is false because its close
Exit For ' exit for loop directly and execute what after for next
End If
End If
wscript.sleep 100
Next
回答by Jim
The key here is to put a small pause after the 'run' command but before the 'appactivate' command so the application shows up in the process list.
这里的关键是在“运行”命令之后但在“appactivate”命令之前暂停一小段时间,以便应用程序显示在进程列表中。
WshShell.Run "calc"
WScript.Sleep 100
WshShell.AppActivate "Calculator"
回答by hollopost
Dim sh : Set sh =CreateObject("Wscript.Shell")
sh.Exec "calc.exe"
Wscript.Sleep 1000
sh.Exec "taskkill /f /FI ""WINDOWTITLE eq ""calc*"""
OR
或者
sh.Run "taskkill /f /im calc.exe",0,False
回答by Thierry Dalon
Alternative solution using WMIService (no loop through all processes required):
使用 WMIService 的替代解决方案(不需要循环遍历所有进程):
Set objWMIService = GetObject("winmgmts:\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery("SELECT * from Win32_Process WHERE Name = '" & ProcessName & "'")
If colItems.Count = 0 Then
WScript.Echo "Process not found"
Wscript.Quit
End If
For Each objProcess in colItems
WshShell.AppActivate(objProcess.ProcessId)
Exit For
Next