12

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:

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?

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!

user3550756
  • 123
  • 1
  • 1
  • 5
  • What's the exact title of the window (in the caption bar) that you're trying to close? Does it just say "HostsMan"? – Bond Apr 19 '14 at 13:27
  • Yeah, it just says "HostsMan". In Task Manager its listed as "HostsMan (32 bit)", which I also tried. No dice. – user3550756 Apr 19 '14 at 16:48

5 Answers5

13

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?

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.

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
Bond
  • 16,071
  • 6
  • 30
  • 53
  • Thanks! Before I try your solution, does this mean that it will kill the process? If so, it won't work for my needs. I have HostsMan set to run in the tray upon close, which I need it to do, so what I really need is just a way to auto close it. – user3550756 Apr 20 '14 at 20:23
  • No, it just determines the process *ID* so that it can pass it to `AppActivate`. – Bond Apr 20 '14 at 21:43
  • Understood. I tried using your code above, but all it appears to do is bring HostMan's window to the top. Am I supposed to add my existing code to it somewhere for it to then close the window? PS - thanks for your patience with me on this. – user3550756 Apr 20 '14 at 22:28
  • Right, I was just trying to help with your `AppActivate` issue. With the window at the top, however, you should now be able to use `SendKeys` to send your "close" command (or any other key combination). I just updated my code to add the `SendKeys` statement. – Bond Apr 20 '14 at 22:40
  • Works perfect! Thanks a ton, Bond. Sure learned a lot on this one. – user3550756 Apr 21 '14 at 01:31
  • Somehow I also have the issue that AppActivate does not work using the ProcessName but does work with the ProcessId (e.g. with Powerpoint application=POWERPNT.EXE) – Thierry Dalon Aug 04 '16 at 06:28
1

Alternative solution using WMIService (no loop through all processes required):

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
Thierry Dalon
  • 779
  • 5
  • 21
1

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.

     WshShell.Run "calc"
     WScript.Sleep 100
     WshShell.AppActivate "Calculator"
Jim
  • 11
  • 1
1

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.

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
hollopost
  • 569
  • 9
  • 28
0
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
hollopost
  • 569
  • 9
  • 28