WshShell.AppActivate doesn't seem to work in simple vbs script - windows

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!

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

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

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"

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

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

Related

Is it possible to write a Windows 10 script opening speaker settings?

I want to write a windows 10 batch script to change my microphone's output volume, as Skype apparently is not able to provide me with consistent settings. Can you point me in the right direction on how to achieve this?
To change the volume You can build 2 vbs files :
soundown.vbs
Set WshShell = CreateObject("WScript.Shell")
WshShell.SendKeys "{" & chr(174) & " 5}"
soundup.vbs
Set WshShell = CreateObject("WScript.Shell")
WshShell.SendKeys "{" & chr(175) & " 20}"
and then call them from your .batfile :
#echo off
cscript.exe /nologo soundown.vbs
or the same with soundup.vbs
EDIT:
You can modify the steps it will modify the volume by modifing the value 5 and 20 in the VBSfiles

stopping VBScript exec from flashing on screen [duplicate]

I'm trying to execute this simple test script, but a command shell window is appearing after I execute the script.:
Set objShell = WScript.CreateObject("WScript.Shell")
strCommand = "cmd /C tasklist"
Set objExecObject = objShell.Exec(strCommand)
wscript.echo "Test"
How can I prevent it from showing up?
Update
I was able to improve it with this code change:
strCommand = "cmd /C /Q tasklist"
Now the window only shows up for a split second. But I don't want it to show up at all.
You're always going to get a window flash with Exec(). You can use Run() instead to execute the command in a hidden window. But you can't directly capture the command's output with Run(). You'd have to redirect the output to a temporary file that your VBScript could then open, read, and delete.
For example:
With CreateObject("WScript.Shell")
' Pass 0 as the second parameter to hide the window...
.Run "cmd /c tasklist.exe > c:\out.txt", 0, True
End With
' Read the output and remove the file when done...
Dim strOutput
With CreateObject("Scripting.FileSystemObject")
strOutput = .OpenTextFile("c:\out.txt").ReadAll()
.DeleteFile "c:\out.txt"
End With
The FileSystemObject class has methods like GetSpecialFolder() to retrieve the path of Windows temp folder and GetTempName() to generate a temporary filename that you can use instead of hardcoding an output filename as I've done above.
Also note that you can use the /FO CSV argument with tasklist.exe to create a CSV file which should make parsing it much easier.
Finally, there are VBScript "native" ways to retrieve the list of running processes. WMI's Win32_Process class, for example, can do this without the need for Run/Exec.
Edit:
For the sake of completeness, I should mention that your script can relaunch itself in a hidden console window where you can run Exec() silently. Unfortunately, this hidden console window will also hide your output from functions like WScript.Echo(). Aside from that, however, you probably won't notice any differences running your script under cscript vs wscript. Here's an example of this method:
' If running under wscript.exe, relaunch under cscript.exe in a hidden window...
If InStr(1, WScript.FullName, "wscript.exe", vbTextCompare) > 0 Then
With CreateObject("WScript.Shell")
WScript.Quit .Run("cscript.exe """ & WScript.ScriptFullName & """", 0, True)
End With
End If
' "Real" start of script. We can run Exec() hidden now...
Dim strOutput
strOutput = CreateObject("WScript.Shell").Exec("tasklist.exe").StdOut.ReadAll()
' Need to use MsgBox() since WScript.Echo() is sent to hidden console window...
MsgBox strOutput
Of course, if your script expects command-line parameters, those would need to be forwarded when relaunching your script as well.
Edit 2:
Yet another possibility is to use the Windows clipboard. You can pipe the output of your command to the clip.exe utility. Then, retrieve the text via any number of available COM objects that can access the contents of the clipboard. For example:
' Using a hidden window, pipe the output of the command to the CLIP.EXE utility...
CreateObject("WScript.Shell").Run "cmd /c tasklist.exe | clip", 0, True
' Now read the clipboard text...
Dim strOutput
strOutput = CreateObject("htmlfile").ParentWindow.ClipboardData.GetData("text")
You can use .Exec() method, without console window flash, temp files and unexpected WScript.Echo output muting. The method is slightly tricky, and requires to launch secondary linked script, so I added the comments:
Option Explicit
Dim objDummy, strSignature, objPrimary, objSecondary, objContainer, objWshShell, objWshShellExec, strResult
' this block is executed only in the secondary script flow, after primary script runs cscript
If WScript.Arguments.Named.Exists("signature") Then
' retrieve signature string from argument
strSignature = WScript.Arguments.Named("signature")
Do
' loop through all explorer windows
For Each objContainer In CreateObject("Shell.Application").Windows
' check if the explorer's property with signature name contains the reference to the live script
If ChkVBScriptTypeInfo(objContainer.getProperty(strSignature)) Then
Exit Do
End If
Next
WScript.Sleep 10
Loop
' create shell object within secondary script
Set objWshShell = CreateObject("WScript.Shell")
' retrieve the primary script me object reference from explorer's property with signature name
Set objPrimary = objContainer.getProperty(strSignature)
' quit explorer window to release memory as it's no longer needed
objContainer.Quit
' assign the secondary script me object to the primary script's variable
Set objPrimary.objSecondary = Me
' emtpy loop while primary script is working
Do While ChkVBScriptTypeInfo(objPrimary)
WScript.Sleep 10
Loop
' terminate secondary
WScript.Quit
End If
' the code below is executed first in the primary script flow
' create signature string
strSignature = Left(CreateObject("Scriptlet.TypeLib").Guid, 38)
' create new hidden explorer window as container to transfer a reference between script processes
Set objContainer = GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}")
' put this script's me object reference into explorer's property
objContainer.putProperty strSignature, Me
' launch new secondary process of the same script file via cscript.exe with hidden console window, providing signature string in named argument to identify host script
CreateObject("WScript.Shell").Run ("""" & Replace(LCase(WScript.FullName), "wscript", "cscript") & """ //nologo """ & WScript.ScriptFullName & """ ""/signature:" & strSignature & """"), 0
' wait until secondary script has been initialized and put his me object into this script variable
Do Until ChkVBScriptTypeInfo(objSecondary)
WScript.Sleep 10
Loop
' here is your code starts...
' create exec object within hidden console window of secondary script, execute cmd instruction
Set objWshShellExec = objSecondary.objWshShell.Exec("%comspec% /c tasklist")
' read cmd output
strResult = objWshShellExec.StdOut.ReadAll()
WScript.Echo strResult
' ...
' utility check if me object is live
Function ChkVBScriptTypeInfo(objSample)
On Error Resume Next
If TypeName(objSample) <> "VBScriptTypeInfo" Then
ChkVBScriptTypeInfo = False
Exit Function
End If
ChkVBScriptTypeInfo = True
End Function
UPDATE
I've slightly reworked the code to make it more straightforward:
Option Explicit
Dim strCmd, strRes, objWnd, objParent, strSignature
If WScript.Arguments.Named.Exists("signature") Then WshShellExecCmd
strCmd = "%comspec% /c tasklist"
RunCScriptHidden
WScript.Echo strRes
Sub RunCScriptHidden()
strSignature = Left(CreateObject("Scriptlet.TypeLib").Guid, 38)
GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}").putProperty strSignature, Me
CreateObject("WScript.Shell").Run ("""" & Replace(LCase(WScript.FullName), "wscript", "cscript") & """ //nologo """ & WScript.ScriptFullName & """ ""/signature:" & strSignature & """"), 0, True
End Sub
Sub WshShellExecCmd()
For Each objWnd In CreateObject("Shell.Application").Windows
If IsObject(objWnd.getProperty(WScript.Arguments.Named("signature"))) Then Exit For
Next
Set objParent = objWnd.getProperty(WScript.Arguments.Named("signature"))
objWnd.Quit
objParent.strRes = CreateObject("WScript.Shell").Exec(objParent.strCmd).StdOut.ReadAll()
WScript.Quit
End Sub
BTW, here is VBScript "multithreading" implementation that uses the same container approach.
Some great suggestions are listed above. I'd like to make one more suggestion which is more of a workaround. You can use Sysinternals Desktops (a free program) to run your macro on another desktop on your same machine. That way the flashing can all happen on its own desktop and won't interrupt your work.
I use Sysinternals PSEXEC
https://learn.microsoft.com/sv-se/sysinternals/downloads/psexec
Created a Batch-file (in the same folder as the vbs and exe-file) that runs the script as system user.
I can not Access the user profile and I need to be local Admin but when i run the script without interaction with the desktop it will hide all annoying popups.
Run Script as system without interaction with desktop
"%~dp0PsExec.exe" -s wscript.exe "%~dp0MyScript.vbs"
Run Script as system with interaction with desktop
"%~dp0PsExec.exe" -s -i wscript.exe "%~dp0MyScript.vbs"
To hide the command line windows in VBscipt is use Run in WshShell Object
Then to get the result you can send this result to text file in %temp%
Then read this result with FileSystemObject
Set Sh = CreateObject("WScript.Shell")
tFile=Sh.ExpandEnvironmentStrings("%Temp%")&"\t.txt"
Sh.Run "cmd.exe /C tasklist > """&tFile&""" ",0,False
Wscript.echo CreateObject("Scripting.FileSystemObject").openTextFile(tFile).readAll()
OR
If StrComp(right(WScript.FullName,11),"wscript.exe",1) = 0 Then '' get only wscript.exe from "c:\windows\system32\wscript.exe" to compere with wscript.exe
WScript.Quit CreateObject("WScript.Shell").Run("cscript.exe """ & WScript.ScriptFullName & """", 0, False)
End If
MsgBox CreateObject("WScript.Shell").Exec("cmd.exe /c tasklist /v /fi ""imagename EQ explorer*"" /FO LIST | FIND ""PID:""").StdOut.ReadAll()
An alternative to using to windows scripting host is here: Run a batch program(.bat) through a Visual Basic 6.0
It runs a program and captures its screen output. It works for me in VB6, but not in VBA (hangs at WaitForSingleObject, don't know why).
After trying the main solutions without success, I was able to solve my problem with the following code:
With CreateObject("WScript.Shell")
.Run "cmd /c start /b tasklist.exe > c:\out.txt", 0, True
End With
The real deal was the "/b" as the console help display:
START ["title"] [/D path] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED]
[/LOW | /NORMAL | /HIGH | /REALTIME | /ABOVENORMAL | /BELOWNORMAL]
[/NODE <NUMA node>] [/AFFINITY <hex affinity mask>] [/WAIT] [/B]
[command/program] [parameters]
"title" Title to display in window title bar.
path Starting directory.
B Start application without creating a new window. The
application has ^C handling ignored. Unless the application
enables ^C processing, ^Break is the only way to interrupt
the application.

Hide command prompt window when using Exec()

I'm trying to execute this simple test script, but a command shell window is appearing after I execute the script.:
Set objShell = WScript.CreateObject("WScript.Shell")
strCommand = "cmd /C tasklist"
Set objExecObject = objShell.Exec(strCommand)
wscript.echo "Test"
How can I prevent it from showing up?
Update
I was able to improve it with this code change:
strCommand = "cmd /C /Q tasklist"
Now the window only shows up for a split second. But I don't want it to show up at all.
You're always going to get a window flash with Exec(). You can use Run() instead to execute the command in a hidden window. But you can't directly capture the command's output with Run(). You'd have to redirect the output to a temporary file that your VBScript could then open, read, and delete.
For example:
With CreateObject("WScript.Shell")
' Pass 0 as the second parameter to hide the window...
.Run "cmd /c tasklist.exe > c:\out.txt", 0, True
End With
' Read the output and remove the file when done...
Dim strOutput
With CreateObject("Scripting.FileSystemObject")
strOutput = .OpenTextFile("c:\out.txt").ReadAll()
.DeleteFile "c:\out.txt"
End With
The FileSystemObject class has methods like GetSpecialFolder() to retrieve the path of Windows temp folder and GetTempName() to generate a temporary filename that you can use instead of hardcoding an output filename as I've done above.
Also note that you can use the /FO CSV argument with tasklist.exe to create a CSV file which should make parsing it much easier.
Finally, there are VBScript "native" ways to retrieve the list of running processes. WMI's Win32_Process class, for example, can do this without the need for Run/Exec.
Edit:
For the sake of completeness, I should mention that your script can relaunch itself in a hidden console window where you can run Exec() silently. Unfortunately, this hidden console window will also hide your output from functions like WScript.Echo(). Aside from that, however, you probably won't notice any differences running your script under cscript vs wscript. Here's an example of this method:
' If running under wscript.exe, relaunch under cscript.exe in a hidden window...
If InStr(1, WScript.FullName, "wscript.exe", vbTextCompare) > 0 Then
With CreateObject("WScript.Shell")
WScript.Quit .Run("cscript.exe """ & WScript.ScriptFullName & """", 0, True)
End With
End If
' "Real" start of script. We can run Exec() hidden now...
Dim strOutput
strOutput = CreateObject("WScript.Shell").Exec("tasklist.exe").StdOut.ReadAll()
' Need to use MsgBox() since WScript.Echo() is sent to hidden console window...
MsgBox strOutput
Of course, if your script expects command-line parameters, those would need to be forwarded when relaunching your script as well.
Edit 2:
Yet another possibility is to use the Windows clipboard. You can pipe the output of your command to the clip.exe utility. Then, retrieve the text via any number of available COM objects that can access the contents of the clipboard. For example:
' Using a hidden window, pipe the output of the command to the CLIP.EXE utility...
CreateObject("WScript.Shell").Run "cmd /c tasklist.exe | clip", 0, True
' Now read the clipboard text...
Dim strOutput
strOutput = CreateObject("htmlfile").ParentWindow.ClipboardData.GetData("text")
You can use .Exec() method, without console window flash, temp files and unexpected WScript.Echo output muting. The method is slightly tricky, and requires to launch secondary linked script, so I added the comments:
Option Explicit
Dim objDummy, strSignature, objPrimary, objSecondary, objContainer, objWshShell, objWshShellExec, strResult
' this block is executed only in the secondary script flow, after primary script runs cscript
If WScript.Arguments.Named.Exists("signature") Then
' retrieve signature string from argument
strSignature = WScript.Arguments.Named("signature")
Do
' loop through all explorer windows
For Each objContainer In CreateObject("Shell.Application").Windows
' check if the explorer's property with signature name contains the reference to the live script
If ChkVBScriptTypeInfo(objContainer.getProperty(strSignature)) Then
Exit Do
End If
Next
WScript.Sleep 10
Loop
' create shell object within secondary script
Set objWshShell = CreateObject("WScript.Shell")
' retrieve the primary script me object reference from explorer's property with signature name
Set objPrimary = objContainer.getProperty(strSignature)
' quit explorer window to release memory as it's no longer needed
objContainer.Quit
' assign the secondary script me object to the primary script's variable
Set objPrimary.objSecondary = Me
' emtpy loop while primary script is working
Do While ChkVBScriptTypeInfo(objPrimary)
WScript.Sleep 10
Loop
' terminate secondary
WScript.Quit
End If
' the code below is executed first in the primary script flow
' create signature string
strSignature = Left(CreateObject("Scriptlet.TypeLib").Guid, 38)
' create new hidden explorer window as container to transfer a reference between script processes
Set objContainer = GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}")
' put this script's me object reference into explorer's property
objContainer.putProperty strSignature, Me
' launch new secondary process of the same script file via cscript.exe with hidden console window, providing signature string in named argument to identify host script
CreateObject("WScript.Shell").Run ("""" & Replace(LCase(WScript.FullName), "wscript", "cscript") & """ //nologo """ & WScript.ScriptFullName & """ ""/signature:" & strSignature & """"), 0
' wait until secondary script has been initialized and put his me object into this script variable
Do Until ChkVBScriptTypeInfo(objSecondary)
WScript.Sleep 10
Loop
' here is your code starts...
' create exec object within hidden console window of secondary script, execute cmd instruction
Set objWshShellExec = objSecondary.objWshShell.Exec("%comspec% /c tasklist")
' read cmd output
strResult = objWshShellExec.StdOut.ReadAll()
WScript.Echo strResult
' ...
' utility check if me object is live
Function ChkVBScriptTypeInfo(objSample)
On Error Resume Next
If TypeName(objSample) <> "VBScriptTypeInfo" Then
ChkVBScriptTypeInfo = False
Exit Function
End If
ChkVBScriptTypeInfo = True
End Function
UPDATE
I've slightly reworked the code to make it more straightforward:
Option Explicit
Dim strCmd, strRes, objWnd, objParent, strSignature
If WScript.Arguments.Named.Exists("signature") Then WshShellExecCmd
strCmd = "%comspec% /c tasklist"
RunCScriptHidden
WScript.Echo strRes
Sub RunCScriptHidden()
strSignature = Left(CreateObject("Scriptlet.TypeLib").Guid, 38)
GetObject("new:{C08AFD90-F2A1-11D1-8455-00A0C91F3880}").putProperty strSignature, Me
CreateObject("WScript.Shell").Run ("""" & Replace(LCase(WScript.FullName), "wscript", "cscript") & """ //nologo """ & WScript.ScriptFullName & """ ""/signature:" & strSignature & """"), 0, True
End Sub
Sub WshShellExecCmd()
For Each objWnd In CreateObject("Shell.Application").Windows
If IsObject(objWnd.getProperty(WScript.Arguments.Named("signature"))) Then Exit For
Next
Set objParent = objWnd.getProperty(WScript.Arguments.Named("signature"))
objWnd.Quit
objParent.strRes = CreateObject("WScript.Shell").Exec(objParent.strCmd).StdOut.ReadAll()
WScript.Quit
End Sub
BTW, here is VBScript "multithreading" implementation that uses the same container approach.
Some great suggestions are listed above. I'd like to make one more suggestion which is more of a workaround. You can use Sysinternals Desktops (a free program) to run your macro on another desktop on your same machine. That way the flashing can all happen on its own desktop and won't interrupt your work.
I use Sysinternals PSEXEC
https://learn.microsoft.com/sv-se/sysinternals/downloads/psexec
Created a Batch-file (in the same folder as the vbs and exe-file) that runs the script as system user.
I can not Access the user profile and I need to be local Admin but when i run the script without interaction with the desktop it will hide all annoying popups.
Run Script as system without interaction with desktop
"%~dp0PsExec.exe" -s wscript.exe "%~dp0MyScript.vbs"
Run Script as system with interaction with desktop
"%~dp0PsExec.exe" -s -i wscript.exe "%~dp0MyScript.vbs"
To hide the command line windows in VBscipt is use Run in WshShell Object
Then to get the result you can send this result to text file in %temp%
Then read this result with FileSystemObject
Set Sh = CreateObject("WScript.Shell")
tFile=Sh.ExpandEnvironmentStrings("%Temp%")&"\t.txt"
Sh.Run "cmd.exe /C tasklist > """&tFile&""" ",0,False
Wscript.echo CreateObject("Scripting.FileSystemObject").openTextFile(tFile).readAll()
OR
If StrComp(right(WScript.FullName,11),"wscript.exe",1) = 0 Then '' get only wscript.exe from "c:\windows\system32\wscript.exe" to compere with wscript.exe
WScript.Quit CreateObject("WScript.Shell").Run("cscript.exe """ & WScript.ScriptFullName & """", 0, False)
End If
MsgBox CreateObject("WScript.Shell").Exec("cmd.exe /c tasklist /v /fi ""imagename EQ explorer*"" /FO LIST | FIND ""PID:""").StdOut.ReadAll()
An alternative to using to windows scripting host is here: Run a batch program(.bat) through a Visual Basic 6.0
It runs a program and captures its screen output. It works for me in VB6, but not in VBA (hangs at WaitForSingleObject, don't know why).
After trying the main solutions without success, I was able to solve my problem with the following code:
With CreateObject("WScript.Shell")
.Run "cmd /c start /b tasklist.exe > c:\out.txt", 0, True
End With
The real deal was the "/b" as the console help display:
START ["title"] [/D path] [/I] [/MIN] [/MAX] [/SEPARATE | /SHARED]
[/LOW | /NORMAL | /HIGH | /REALTIME | /ABOVENORMAL | /BELOWNORMAL]
[/NODE <NUMA node>] [/AFFINITY <hex affinity mask>] [/WAIT] [/B]
[command/program] [parameters]
"title" Title to display in window title bar.
path Starting directory.
B Start application without creating a new window. The
application has ^C handling ignored. Unless the application
enables ^C processing, ^Break is the only way to interrupt
the application.

Would you fix this vbs to execute this bat file with admin priviledge

Under windows 7 with uac activated.
This is all around an issue. THIS ISSUE:
upnphost excessive cpu load
Especifically:
Mine has this problem frequently, and I hate to go restart the upnphost service all the time, so instead i just created a task in the
task scheduler to run a once a day, and repeat every 5 minutes. The
task runs a .bat file:
net stop upnphost
net start upnphost
if you want to make it run in the background without the cmd window
coming up, run this .vbs with the above .bat already created as
"C:\upnphost.bat":
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\upnphost.bat" & Chr(34), 0 Set
WshShell = Nothing
this way the upnphost service will automatically restart every 5
minutes with no visible presentation, so if it decides to misbehave
and go high cpu, it will be for 5 minutes tops, you could change this
to any interval you want.
Everything works except for the fact that for the bat to actually work i need to right click directly on the bat and execute as admin.
For that reason if i click the vbs it will execute it but not as admin and it wont work.
So scheduling it as a task wont work either.
Can you fix the code in the vbs:
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\upnphost.bat" & Chr(34), 0 Set
WshShell = Nothing
So it executes the bat with admin priviledge.
It that matters, my route to the bat has spaces.
Respectfully
You can launch an program as an administrator with UAC enabled, but you'll still get prompted whether you want to launch this program. For example,
Set objSA = CreateObject ("Shell.Application")
objSA.ShellExecute "cmd.exe","uac","","runas",1
However,
I was able to use this vbscript to stop and restart this service using a scheduled task, setting the task to run as "Hidden" and run with the highest privileges.
strService = "upnphost"
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colService = objWMIService.ExecQuery("SELECT Name FROM Win32_Service " _
& "where Name='" & strService & "'")
For Each objService In colService
return = objService.StopService()
return = objService.StartService()
Next
The scheduled task must be run as a user who can start and stop the service (usually an admin account) and with the option "Run with highest privileges" enabled.

How to kill the last opened Internet Explorer window using a command?

I'm trying to write a Windows command file to open a webpage in IE, wait for it to load, then close the IE window. The following works but will kill all IE windows so any that were already open before running the .cmd will also get closed.
start iexplore.exe "page to load"
ping localhost -n 10 > nul
taskkill /IM iexplore.exe
I only want to kill the IE that was opened. I know I can just kill a particular process if I know its PID but how can find this from the command line? Is there a way to get it when starting the IE window? What I really want to do is:
start iexplore.exe "page to load"
ping localhost -n 10 > nul
taskkill /PID ?
where ? is the PID of the IE that gets opened but how can I get this? This needs to run as a .cmd file without any input from a user.
IE already supports automation, there is no point in finding and killing the correct process:
Set IE = CreateObject("InternetExplorer.Application")
IE.visible=true
IE.navigate "http://stackoverflow.com/"
while IE.Busy
WScript.Sleep 555
wend
IE.Quit
Save as .vbs (And run with wscript.exe from parent program/batch file)
use vbscript
Set objFS=CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments
strProcess = objArgs(0) 'argument, which is the process name
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
' call WMI service Win32_Process
Set colProcessList = objWMIService.ExecQuery("Select * from Win32_Process Where Name = '"&strProcess&"'")
t=0
For Each objProcess in colProcessList
' do some fine tuning on the process creation date to get rid of "." and "+"
s = Replace( objProcess.CreationDate ,".","")
s = Replace( objProcess.CreationDate ,"+","")
' Find the greatest value of creation date
If s > t Then
t=s
strLatestPid = objProcess.ProcessID
End If
Next
WScript.Echo "latest: " & t , strLatestPid
'Call WMI to terminate the process using the found process id above
Set colProcess = objWMIService.ExecQuery("Select * from Win32_Process where ProcessId =" & strLatestPid)
For Each objProcess in colProcess
objProcess.Terminate()
Next
usage:
c:\test>cscript //nologo kill.vbs "iexplore.exe"

Resources