Remotely manipulating the execution of a batch file - windows

I have a batch file that is located on one machine that I am invoking remotely from another machine. That batch file is pretty simple; all it does is set some environment variables and then executes an application - the application creates a command window and executes inside of it. The application it executes will run forever unless someone types in the command window in which it is executing "quit", at which point it will do some final processing and will exit cleanly. If I just close the command window, the exit is not clean and that is bad for a number of different reasons related to the data that this application produces. Is there a way for me to perhaps write another batch script that will insert the "quit" command into the first command window and then exit?

I'd write a little script using the subprocess module in python, like so:
from subprocess import Popen, PIPE
import os
import os.path
import time
app = Popen(['c:/path/to/app.exe', 'arg1', 'arg2'], stdin=PIPE, env = {
'YOUR_ENV_VAR_1': 'value1',
'YOUR_ENV_VAR_2': 'value2',
# etc as needed to fill environment
})
while not os.path.exists('c:/temp/quit-app.tmp'):
time.sleep(60)
app.communicate('quit\n')
print "app return code is %s" % app.returncode
Then, you remotely invoke a batch script that creates c:/temp/quit-app.tmp when you want to shut down, wait a couple of minutes, and then deletes the file.
Naturally, you need Python installed on the Windows machine for this to work.

It sounds like the type of job for which I'd use expect, though I've never used it under Windows.

You could use the < to take the "quit" from a text file instead of the console... but that would quit your process as soon as it loads. Would that work?
Otherwise you could write a program to send keystrokes to the console... but I don't think this is a production quality trick.

Do you have access to the actual code of the application? if so you can check for a batch file. Else you can do something like the following using powershell.
$Process = Get-Process | Where-Object {$_.ProcessName -eq "notepad"}If (!($Process))
{ "Process isn't running, do stuff"
}Else
{ $myshell.AppActivate("notepad")
$myshell.sendkeys("Exit")
}
I am only suggesting powershell as its easy for you to call the code. you could also put in a loop and wait for it to run.
RE

Related

How can I execute Windows commands from Perl without leaving command windows open?

I have a Perl script on Win10 that uses the system() command to run a couple of different command line processes, including:
Start Windows Media Player with a specified .mp3 file.
my $cmd = "start call wmplayer.exe myRadoShow.mp3";
system($cmd);
Start another Perl program that does something else at the same time (specifically reads and broadcasts a set of timecodes and titles).
my $cmd2 = "secondScript.pl some_params";
system($cmd2);
All of this works correctly; the minor problem is that #1 above starts up a new command line window each time it executes the system($cmd) command. I have to later go back and close those windows.
If I don't use "start call" the Perl script doesn't continue to #2.
Is there a preferred way to execute #1 that doesn't leave these windows open?
I realize this question may be more about Windows commands than Perl.
Firstly, If youre using active perl versions, there is a wperl.exe you can call your script with instead of the default perl.exe. Not to sure if this will hide sub processes created by your script but you can give it a go.
If that doesnt work, then maybe you can use Win32::GUI:
use Win32::GUI;
my $hw = Win32::GUI::GetPerlWindow();
Win32::GUI::Hide($hw);
there are other modules that provide this functionality as well. Good luck!

How can I keep powershell in repl mode with a loaded script

I'm trying to start a powershell instance, that loads a script and remains open so I can still call methods loaded by that script manually.
I'm trying to dot source a script and pipe it to powershell like below, from a cmd instance/batchfile:
echo . .\script.ps1 | powershell
The result in this case is that powershell starts, loads my script, executes it and exits. I've tried running with -noexit argument, it has no effect.
I'm thinking of another option, to start a powershell process and pipe my dot source command to its stdin - but this probably won't allow me to interact with the process anymore because its stdin is opened by the host process.
If you need to run a script file so that window stays open and variables are accessible after the execution.
Try dot sourcing the script file like this:
powershell -noexit ". .\script.ps1"
Once the script is done, you can access any internal variable the script defined. Assuming the variables are at the script level scope.

Python subprocess.Popen terminates when stdin=PIPE is specified

I'm new to subprocesses in python, I need to spawn a number of independent subprocesses, keep them alive and pass commands into them. At first sight, subprocess library is what I'm looking for.
I've read the documenations for it and as I'm understanding to pass any command into the subprocess, I'd have to specify the input.
I need to run commands via windows command line, hence the toy example below is good enough that if I have it working, I'm pretty much done. Running code below via IDLE opens a new cmd window, printing a list of cwd files, however I can't write to it as stdin is not specified (would be writing to it using p.stdin.write('DIR') with 'DIR' being an example command).
from subprocess import Popen, PIPE
p = Popen(['cmd', '/K', 'DIR'])
Therefore I specify the stdin as PIPE, as per documentations.
from subprocess import Popen, PIPE
p = Popen(['cmd', '/K', 'DIR'], stdin=PIPE)
However, running the second snippet of code instantly terminates the opened cmd window. Is that the expected behavior? As far as I could find in the documentations, only p.kill() or p.terminate() end the child process. If so, what are the possible workarounds? If not, what am I doing incorrectly, what other libraries should I be using? Thanks!

Checking for a running python process using python

I have a python script called speech.pyw. I don't want it showing up on the screen when run so I used that extension.
How can I check using another python script whether or not this script is running? If it isn't running, this script should launch it.
Off the top of my head, there are at least two ways to do this:
You could make the script create an empty file in a specific location, and the other script could check for that. Note that you might have to manually remove the file if the script exits uncleanly.
You could list all running processes, and check if the first one is among those processes. This is somewhat more brittle and platform-dependant.
An alternative hybrid strategy would be for the script to create the specific file and write it's PID (process id) to it. The runner script could read that file, and if the specified PID either wasn't running or was not the script, it could delete the file. This is also somewhat platform-dependant.
!/usr/bin/env python2
import psutil
import sys
processName="wastetime.py"
def check_if_script_is_running(script_name):
script_name_lower = script_name.lower()
for proc in psutil.process_iter():
try:
for element in proc.cmdline():
if element.lower() == script_name_lower:
return True
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return False;
print(check_if_script_is_running(processName))
sys.stdin.readline()

running mulitple commands using Subprocess.Popen in the same shell

Hi I am at a loss on how to run multiple commands using popen,
I am trying to automate a series of steps that are normally run on the Windows command line. The basic steps are usually run from the Windows cmd line are
Run a windows command script (.cmd) file to setup environment variables i.e C:\Program Files (x86)\appsettings\setupvariables.cmd
type in the command to connect to the database
type in the command to get data from the database
Stop connection to the database
All these commands must run in the same command line window one after another, not separate processes or separate command line windows. Instead of opening a cmd window and typing in the command I want to use python's subprocess.popen command
So far I have:
args=[]
args.append(r'C:\Program Files (x86)\appsettings\setmyvars.cmd')
args.append(r'start db on db_path="my_url"')
args.append(r'get_data_from_db>c:\temp\output.txt')
args.append(r'stop db on db_path="my_url"')
p=Popen(args,stdout=PIPE,sterr=PIPE,shell=True)
stdout,stderr=p.communicate()
if stderr:
print "you have an error", stderr
else:
print "well done you have data", stdout
This isn't quite working I can see that the first line is run i.e the setmyvars.cmd is executed, but nothing else, none of the other arguments get called, if they did I would see the results in the ouput.txt file.
How do I run a series of commands one after the other using popen. Why is it only the first command seems to be executed and none of the others
I am using python2.7 on Windows
Regards.
You have a couple of issues going on. You still have to tell popen() which program to run. Just using shell=True does not obviate the need to provide cmd.exe as the program to run. If you really want to run all of these commands with one invocation of cmd.exe, then you will need to string them together with &&.
from subprocess import *
args=[]
args.append(r'C:\Windows\System32\cmd.exe')
args.append(r'/C')
args.append(r'(echo 1 && echo 2 && echo 4)')
p = Popen(args,stdout=PIPE,stderr=PIPE,shell=True)
stdout,stderr=p.communicate()
if stderr:
print "you have an error", stderr
else:
print "well done you have data", stdout
It would probably be better to use the %ComSpec% environment variable than it would be to hardcode the location of cmd.exe. The path you have is -usually- correct. :-)

Resources