Run batch file in background - windows

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

Related

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.

On boot, issues running a bat file through vbs script

I need to run a program (a python script made into an exe) on start up, without the console showing up.
In some question, I found the solution, i.e to execute the program. Right now, I'm testing it out with a simple python program filewriter.py that does -
while count != 1000:
f = open('test.txt','a+')
f.write(str(count))
f.close()
sleep 1
The bat file tool.bat :
#ECHO OFF
python "<absolute_path_here>\filewriter.py"
EXIT /B
The VBS file :
Set WinScriptHost = CreateObject("WScript.Shell")
WinScriptHost.Run Chr(34) & "<absolute_path_here>\tool.bat" & Chr(34), 0
Set WinScriptHost = Nothing
If I execute the VBS file (double-click it), everything works fine. The output file appears, without the console appearing. So I added it to registry under
HKCU\Software\Microsoft\CurrenVersion\Run
as WScript "path_to_the_vbs_file".
On Startup, the VBS file executes properly (verified it by adding a MsgBox which displayed the popup) but the call to the bat file is not being executed. How do I make this work?
In windows there are two python executables: python.exe, pythonw.exe. If you don't wish to see the terminal window you must use pythonw.exe.
I need to run a program (a python script made into an exe).
If you covert your script to .exe with help of py2exe it is simillar. You can assing your script to console or windows. Look to Py2exe Tutorial, the console variable can be replace forwindows.
You don't need to create EXE files from python. You can run pythonw.exe with path as argument to your script. Why do you need to create .bat which you run from vbscript ? Look here: Run on windows startup CMD with arguments
I forgot to say, that the Windows Python installer normally create following file association, so the script can run directly.
'.py' to python.exe
'.pyw' to pythonw.exe
Other way how you can run the the script on boot is to use Windows Scheduler. The big advantage is you can setup user rights or more events when start the script. You can run the script manually too and you will last status.
Create Python .exe is sometimes tricky. If you don't need to distribute your script to multiple computers I prefer don't use.

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.

Voodoo with DOS Batch files

I've created a simple batch file that kicks off my *.msi installer within our company, creating a log file of the process, then displays the log file after the installer has completed.
installAndLog.bat:
msiexec.exe /i "\\FileServer2\setup.msi" /l*v "C:\setupLog.txt"
"C:\setupLog.txt"
It works, but there are two (2) glitches that annoy me:
The black console box shows in the background the whole time the installer is running and the log file is being displayed. Q1: How do I hide that?
and
The console box will not close until the log file is no longer being viewed (i.e. notepad.exe is closed). Q2: Can I call the text file in a new process and simply exit?
I was a DOS lover back in the day, but that was too many years ago.
I don't think you can hide the console window when running a batch file. However you can use vbscript instead which will by default not create a console window.
Take the below and put it in a file with a .vbs extension:
Dim wshShell
Set wshShell = CreateObject("WScript.Shell")
wshShell.Run "msiexec.exe /i ""\\FileServer2\setup.msi"" /l*v ""C:\setupLog.txt""", 1, true
wshShell.Run "C:\setupLog.txt"
All the double double quotes are there because the entire command must be surrounded by "'s and doubling them escapes them. The the documentation for WshShell.Run for more info.
Q1 - AFAIK you can't really hide the console window.
Q2 - Use the start command. This will launch the specified program (notepad) outside of the shell. It will also prevent the shell from waiting until the application closes to continue processing the batch script.
You might be better off changing the batch script to launch the MSI installer using the start command and having the installer launch notepad to view the log file once installation is complete.
If you really want to get these batch windows away, you'll have to switch over to something else. One simple alternative could be one of the scripting languages supported by the windows scripting host.
Or you try HTA (HTML applications) see here and here.
Run the dos script as a different user by scheduled task or as a service.

Closing a startup program programmatically in Vista/Windows 7

I am looking to be able to write a script that will close an application that is included in the Windows start up. I know the common sense is why not remove it from start up, but I want it to run because the application connects my NAS. I just close it every single time because I have no use for the actual app except for the fact that it makes the connections.
So I got the bright idea that perhaps I could write a script that will also run in the startup after the app is launch that will kill/close it.
First does this sound possible? Is there a better way?
You can create a .bat file and run it during startup, after the NAS program has run. The following code will kill all instances of a process (the current code will kill notepad)
Dim WMI, KillProc
Dim processName: processName = "notepad.exe"
Set WMI = GetObject("winmgmts:\.\root\cimv2")
Set KillProc = WMI.ExecQuery("Select * from Win32_Process Where Name = '" & processName & "')
For Each Proc In KillProc
Proc.Terminate()
Next
Is the app mapping drives to shared folders on your NAS? If so, then you could remove it from the Startup folder and either:
use Explorer's "Map Network Drive" feature
write a BAT file to run on Startup that does a NET USE to map
write some VBScript :), using WScript.Network.MapNetworkDrive

Resources