I am having an issue with getting psexec and find to play nicely together in my python function. Here is the function that I am trying to get to work:
def CountString(address, file, findstr):
cmd_line = r'psexec \\{0} cmd /c find /c "{1}" "{2}"'.format(address, findstr, file)
print cmd_line
myP = subprocess.Popen(cmd_line, shell=True, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
out = timeout(myP.communicate, (), {}, 30, (None, None))
return out
Here is an example of how I am testing the function:
test = CountString(r'RemotePC', r'c:\directory\File to Count.txt', r'String to count')
print test
In my first snippet of code I have added a print cmd_line
in order to verify that the cmd line looks correct, and from what I can tell it does. If I run the function with my example input it returns:
psexec \\RemotePC cmd /c find /c "String to count" "c:\directory\File to Count.txt"
I can even copy and paste the output of print cmd_line
into a cmd window and it works as expected:
C:\>psexec \\RemotePC cmd /c find /c "String to count" "c:\directory\File to Count.txt"
PsExec v1.97 - Execute processes remotely
Copyright (C) 2001-2009 Mark Russinovich
Sysinternals - www.sysinternals.com
---------- c:\directory\File to Count.txt: 3600
cmd exited on RemotePC with error code 0.
C:\>
But for some reason I cannot get the python function to return a result, it will just sit there and hang if I do not have it timeout.
I have also tried changing my syntax of cmd_line
to add ""
around find /c "{1}" "{2}"
:
cmd_line = r'psexec \\{0} cmd /c "find /c "{1}" "{2}""'.format(address, findstr, file)
Again the output of print cmd_line
works from the cmd line itself, but will not consistently work in python.
One strange thing I have noticed is that this will return what I want maybe 1 out of 25 tries. But when I run it again against the same remote PC and the same file, it fails.
Note: I am not opposed to using something besides find
if there is something else that will return a count of the string I am trying to find in the file. But I do need to use psexec
, or something that will allow me to execute the command remotely on an XP machine, because the files that I am attempting to count the string from are very large and will return results over a few thousand.
I found a work around! I am still using find
, but now instead of using it directly, I pipe it the results from findstr
.
Here is what my cmd_line
looks like now:
cmd_line = r'psexec \\{0} cmd /c "findstr /c:"{1}" "{2}" | find /v /c """'.format(address, findstr, file)