Tracking PID in batch file and closing cmd when PID closes - windows

I have a batch file that starts a HTML file from command line in whatever is the default browser:
start filename.html
I am looking for some way to find out the ID of the spawned process (firefox, ie, chrome) and track the PID in order to shut down the cmd window when the process is complete.
Basically, the process would ideally go like this: start html, find PID of last spawned process, watch the PID, when PID closes - CMD will exit
I have tried searching around for this and found a way to find the pid of a process but not how to track until exit.
Is it possible to do this in a BAT file? Any assistance would be lovely. Thanks!

start filename.html
exit
try this. but however what i know is this that once the process is complete cmd closes on its own.
OR
u can directly run your file without opening the cmd black window try this below script save it as example.vbs and replace testing with ur batch filename and then run this example.vbs file instead of batch file.
Set oShell = CreateObject ("Wscript.Shell")
Dim strArgs
strArgs = "cmd /c testing.bat"
oShell.Run strArgs, 0, false

Related

Run batch file in background

I've got a batch file that I want to run in the background whenever the system (Windows 2007) is turned on. The batch file monitors the task list for a given program, and when it sees that it's shut down, prompts the user to de-licence it.
I'm currently trying to do this without converting the batch file into either an executable or Windows service file.
I've found more online references than I can count which tell me that I should use "start /b file.bat" to run the batch file in the background, but this doesn't work for me, it just starts up the batch file in the same cmd line window that I'm using.
Can anyone suggest either what's going wrong, or even better; a nice simple way for me to get the batch file to run ion start up (I cannot use a GUI as I have to roll this out to several computers remotely)
Thanks
You could make a shortcut to your batch file and place the shortcut in your Startup Programs directory:
C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
Since you have to roll this out to several computers remotely, you should be able to copy the batch file to the startup programs directory over the network assuming the remote machines have WinRM enabled and your account has adequate permissions.
If you want this batch file to run in the background at start up, you could reference your batch file from a VBScript (instead of using the batch file's short cut) and set the VBscript to run in invisible mode:
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\path\to\your\batchfile.bat" & Chr(34), 0
Set WshShell = Nothing
Just give this vbscript file the .vbs extension.
If the program you are concerned about is a GUI program (ie non console) just wait for it to exit. Batch waits for GUI programs to exit (but not when started interactively).
notepad
echo My notepad exited
Start /b says to start program in same window. See Start /?. Also Start is usually the wrong command to be using. It starts programs in abnormal ways. See end of http://stackoverflow.com/questions/41030190/command-to-run-a-bat-file/41049135#41049135 for how to start programs.
This is a VBS file.
This monitors for notepad exiting, pops up a messagebox, and restarts notepad.
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set objEvents = objWMIService.ExecNotificationQuery("SELECT * FROM Win32_ProcessStopTrace")
Do
Set objReceivedEvent = objEvents.NextEvent
msgbox objReceivedEvent.ProcessName
If lcase(objReceivedEvent.ProcessName) = lcase("Notepad.exe") then
Msgbox "Process exited with exit code " & objReceivedEvent.ExitStatus
WshShell.Run "c:\Windows\notepad.exe", 1, false
End If
Loop
This should use less battery power and CPU cycles. Batch files are read line by line so make VERY poor background tasks.
If the program you are concerned about is a GUI program (ie non console) just wait for it to exit. Batch waits for GUI programs to exit (but not when started interactively).
notepad
echo My notepad exited

Getting the name of a running bat file from an external application

I'm trying to find out what's the full path of a running bat file from an external application.
The process is cmd.exe but I can't get the name for the actual running bat.
In task manager it shows as cmd.exe
If I get the process as an object, the closest property to the bat is in MainWindowTitle.
Is there any way to get the full running bat path from it's running cmd process?
The answer written by vtrz on question How to check if a process is running via a batch script? contains the command you are looking for:
%SystemRoot%\System32\wbem\wmic.exe PROCESS where (name="cmd.exe") GET CommandLine
Windows Management Instrumentation Command-line utility with those parameters lists all running cmd.exe processes line by line with the command line used to start them.
But that means if a user opened a command prompt window and started from within this window a batch file executed by already started cmd.exe, the command line output for this command process is just "C:\Windows\System32\cmd.exe". As far as I know it is not possible to get from an already running command process the information what this command process currently executes.
Well, if the executed batch files use the command title to give their console windows meaningful titles, it is also possible to use tasklist to get information about a command processes with a specific window title or use taskkill to terminate or kill a command process with a specific window title.
This is the function I ended up with (VB.NET), if anyone cares. It can retrieve the bat path from cmd.exe process and also I use it to get vbs files from wscript.exe. It receives as argument the ProcessID of cmd.exe or wscript.exe and returns a list of string because I needed to get also argument files passed to vbs. The parsing part works well at list in scenarios that I use it in.
Function GetArgFiles(PID As Integer) As List(Of String)
Dim Ret As New List(Of String)
Try
Dim MOS As New ManagementObjectSearcher("root\CIMV2", "SELECT Name, CommandLine FROM WIN32_Process where ProcessID = '" & PID & "'")
For Each MO As ManagementObject In MOS.[Get]()
Try
Dim name As String = MO.GetPropertyValue("Name")
Dim CommandLine As String = MO.GetPropertyValue("CommandLine")
If CommandLine Is Nothing Then Exit Try
For Each CLE As String In New List(Of String)(CommandLine.Split(Chr(34)))
Try
CLE = CLE.Trim
If CLE.Length < 5 Then Continue For
If CLE.ToLower Like "*" & name.Trim.ToLower & "*" Then Continue For
If CLE Like "*:\*" Then
CLE = CLE.Substring(CLE.LastIndexOf(":\") - 1)
Else
Continue For
End If
If CLE.Contains("/") Then CLE = CLE.Substring(0, CLE.LastIndexOf("/"))
If CLE.Substring(5).Contains(":") Then CLE = CLE.Substring(0, CLE.LastIndexOf(":"))
If File.Exists(CLE.Trim) Then Ret.Add(CLE.Trim)
Catch
End Try
Next
Catch
End Try
Next
Catch
End Try
Return Ret
End Function

Wscript make proccess not run on background or wait while finishes

Scenario: We have some scheduled jobs (Control-M) running many proccesses and some of them execute a .VBS file (with parameters) that reads the configuration from an XML file and sends it to a company's software that interprets it and loads data onto tables.
I need help with the VBS file, that as stated above, only gets the instructions from the XML and send it to the software with these steps (also, logs each step):
Finds the XML;
Creates an object to login the software (with XML parameters);
Dim object
Set object = CreateObject("service.location.id")
Login into the Database (with XML parameters);
object.Login("DATABASE_NAME")
Select which Data base (XML...);
object.SelectDatabase("DATABASE_NAME")
Sends command to start load proccess
object.LoadRepositoryTable(XML)
The problem is that since the default interpreter is wscript, when executing the script, it runs on the background and the Job Scheduler thinks it finished executing and starts the next job.
Executing the script on CMD, if I start it as cscript SCRIPT.vbs it waits for the whole load proccess to finish (it doesn't run on background), and I want to do this when running as wscript - because since there are many jobs, editing how they calls the script is not an option right now. This includes creating an .bat file that calls the SCRIPT.vbs as cscript.
I also tried searching on "how to run another .vbs file inside a VB Script" to run as cscript, but didn't manage to make it work.
What can I do?
Is there a way to make wscript wait for the load?
Is there a way to call a .vbs in the same folder (without sending it as parameter) while passing 2 arguments?
Another option I'm not seeing?
Edit: Here is what I've come to so far, but I'm getting "expected end of statement".
Dim objShell
Dim arg_dir
arg_dir = Wscript.Arguments.Item(0)
Dim arg_xml
arg_xml = Wscript.Arguments.Item(1)
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "cmd /k cscript ""C:\Folder\Scripts\SCRIPT.vbs" &" "& arg_dir &" "& arg_xml"", 1, True
cscript is the solution for your problem. Either have your scheduler run each VBScript with cscript.exe, or (if that isn't possible for some reason) make cscript the default script host by running
wscript.exe //h:cscript
once as an administrator.
The script you have cobbled together won't resolve your problem, even if you fixed the syntax error in the last line, because as long as you run it with wscript.exe it will still return immediately. It doesn't matter that the code in that script is running other scripts synchronously as long as all of that is happening in the background.

vbs run command no output

Okay I created a small script to call "net file" and pump the output to a file. There are no spaces in the filenames, and everything seems okay when I run it interactively. So I run the following and I get no results and no errors:
set oWShell = CreateObject("WScript.Shell")
owshell.run "net file > C:\openfiles.txt"
Set owShell = nothing
Now if modify this just slightly to show execute the same command (and keep my command window open) it works just as expected (except it keeps the cmd window open which I can't have)
set oWShell = CreateObject("WScript.Shell")
owshell.run "%comspec% /k net file > C:\openfiles.txt"
Set owShell = nothing
It must be something obvious that I'm just missing. I only touch vbs once in a blue moon so it isn't something that I'm that used to using.
Any help would be appreciated! Thanks in advance!
You need a shell (i.e. %comspec%) to get shell features like redirection; the persisten window is what you asked for: the /k lets the shell stay open (try /c instead) and you should use the second and third parameter of the .Run method to get a hidden window (and possibly wait for the process before you zap the owShell).
Have a look at Run. Changing
owshell.run "%comspec% /k net file > C:\openfiles.txt"
to
owshell.run "%comspec% /c net file > C:\openfiles.txt", 0, FALSE
This will hide the cmd and carry on with the rest of the script... If you want to wait for the command to finish, change FALSE to TRUE.
Also keep in mind that some machines are funny about letting you write files directly to C:\. Possibly create a test folder and write to there instead!

Start a process in a new window from a batch file

I have written a batch file (.bat) in windows. I want to execute a particular process in a new window. How do I do this?
Example
a.py -s 3 -l 5
b.py -k 0 -> I want to start this in a new window and let the original batch file continue
C:\program.exe
...
....
Use the start command:
start foo.py
or
start "" "c:\path with spaces\foo.py"
start "title" "C:\path\to\file.exe"
I would highly recommend inserting a title so that you can call that title later via the TASKKILL command if needed.
TASKKILL /im title
The solutions below are for calling multiple files in the same window; this question has been answered already so I am just adding my 2 cents.
If you are working with a master batch file that calls multiple other batch files, you would use the "call" command. These aren't processes, though.
Within the other batch files you can call the "start" command to start them in separate windows.
master.bat
call myCoolBatchFile1.bat
call myCoolBatchFile2.bat
call myCoolBatchFile3.bat
If you are using Windows Powershell, you can use the Start-Process command.
myPowershell.ps1:
#silent install java from java exe.
$javaLogLocation = "[my log path here]"
$javaFileName = "[javaInstaller file name here].exe"
$process = "$javaFileName"
$args = "/lang=1033 /s /L $javaLogLocation"
Start-Process $process -ArgumentList $args -Wait
For more info on the start command and its usages, as well as other scripting tech:
https://ss64.com/nt/start.html
As per the requirement, we can follow up like this. As I was doing an automation work for my office purpose. So I need to create a process for a certain time, & after that I have to kill the service/ process.
So What I did,
For start a process:
**`start "API" C:\Python27\python.exe`**
Then I tried with my all other works & tasks. After that I need to kill that process. So That I did,
**`taskkill /F /IM python.exe`**
After killing the process, outcome ran smoothly.

Resources