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

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

Related

How to give script a name?

I have a script that I run to keep my computer from going to sleep. It's a simple script that presses the Num Lock key. How can I give my script a name so I can see it in Task Manager? I would like to end the process every now and then and not sure which application it is.
Here is the code (idle.vbs):
Dim objResult
Set objShell = WScript.CreateObject("WScript.Shell")
Do While True
objResult = objShell.sendkeys("{NUMLOCK}{NUMLOCK}")
Wscript.Sleep (60000)
Loop
Your script is being executed in an interpreter, and in Task Manager you will see the name of the executable : wscript.exe
You cannot change the process name, although you can identify the name of the running script using another script and the property of handles.
But the easiest way would be to make a copy of the executable wscript.exe, rename it with something suggestive for you, and use that executable in cmd to run the script. For example idleEx.exe and run it :
...\idleEx.exe idle.vbs
Or, the other method: create a shortcut for the vbs and change Properties / General / Opens with, browse and choose idleEx.exe.
After that, your process name will apear as idleEx.exe

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.

Tracking PID in batch file and closing cmd when PID closes

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

VBscript wscript.shell execute not refreshing in winpe

I have a DISM based imaging solution for use in WinPE as follows:
set WshShell = CreateObject("WScript.Shell")
Wscript.StdOut.WriteLine "[44m[1;37m restoring image boot partition for " & name & " [0m[40m"
Set objExec = WshShell.Exec("DISM.exe /Apply-Image /ImageFile:" & name & "/index:1 /ApplyDir:c:\")
Do
line = objExec.StdOut.ReadLine()
Wscript.StdOut.WriteLine line
Loop While Not objExec.Stdout.atEndOfStream
There are two issues with the way this executes:
The execution seems to stall and I have to press enter for it to continue.
The second problem is that the progress bar does not show up. It stays at "applying image".
Normally, if you execute DISM.exe /Apply-Image /ImageFile:" & name & "/index:1 /ApplyDir:c:\ it will look something like this:
"applying Image {1%-------------------------------------}
Interestingly this segment which prepares the disk shows each line of execution:
Set WshShell = CreateObject("WScript.Shell")
Set objExec = WshShell.Exec("diskpart.exe /s clean.sh")
Do
line = objExec.StdOut.ReadLine()
Wscript.StdOut.WriteLine line
Loop While Not objExec.Stdout.atEndOfStream
I think the DISM output is different because it only has one line that refreshes itself, but I'm not sure how to code around it.
I don't know how dism.exe outputs data (at the moment i only have a XP to test) but there is at least two cases in which code as
Set objExec = objShell.Exec( ...... )
Do
WScript.StdOut.WriteLine(objExec.StdOut.ReadLine())
Loop While Not objExec.Stdout.atEndOfStream
will not work as expected.
One is when the program output is directly send to the console buffer, not writing into stdout. As the code reads from the stdout stream of child process and there is no anything on it....
Second is when there is no end of line mark in child process output. Both Read and ReadLine return when the Enter key is pressed or when a CRLF is inside content being read. But, the tipical form of generating a progress bar in a console output is not sending the LF part, sending only the CR to return the caret to the start of the line and output the next change in progress bar just writing over the first drawn one. In this case, both the indicated methods will not return until there is a CRLF included in the output stream of the child process or the stream is closed.
As said, i've no access to DISM to test, but it seems it will fall in one of the two cases.
And no, it seems Run method has no way to run the command in the same window.
If the "same window" is a mandatory requirement, the better approach is to code something like
start a "master" batch file
this batch file starts the vbs
the vbs do what it needs to do and in the case of having to execute DISM or anything similar, generate a temporary batch file with the adecuate content and exit from vbs
the "master" batch file retrieves the control, checks for the presence of the temporary batch file and calls it
on completion of the temporary batch file, "master" retrieves the control and starts again the vbs
use the method that better adapts (arguments, environment variables, flag files, ...) to determine that this is not the first execution and continue execution as required.

VS macro. Getting the title (not name) of the process to attach to

I'm modifying one of the attach to process macro's for VS 2010.
I often have multiple instances of iisexpress running. I usually run them via batch start command and specify a title - so whenever i use VS's attach to process window i can clearly see the title of the instance i'm attaching to. I'm wondering how do I get the title of the process within the macro. I can get process id which could potentially give me access to title I assume... ?
You can use the Process.MainWindowTitle property:
Sub Main()
For Each process In System.Diagnostics.Process.GetProcesses()
If process.ProcessName = "cmd" Then
Console.WriteLine("{0}: {1}", process.ProcessName, process.MainWindowTitle)
End If
Next
End Sub
If you execute this command:
start "xyzzy" cmd.exe
The test program produces this output:
cmd: C:\Windows\system32\cmd.exe
cmd: xyzzy
After you get EnvDTE.Process, e.g. process, you can get the tile like this:
System.Diagnostics.Process.GetProcessById(process.ProcessID).MainWindowTitle

Resources