1

I am trying to remotely execute a script using PsExec and return live output using subprocess.Popen within my Tkinter program. Everything workes fine using below code (without compiling my app using the --windowed parameter).

cmd = [Settings.psexec_loc, f"\\\\{target}", "-n", str(10), "-c", "-f", "-s", "-accepteula", "-nobanner", Settings.temp_cmd_loc]
process = subprocess.Popen(
    cmd,
    stdout=subprocess.PIPE,
    stderr=subprocess.STDOUT
)

while True:
    line = process.stdout.readline()
    if not line:
        break
    print(line.decode().rstrip())

When i tried removing the Tkinter startup cmd console window using the --windowed or --noconsole option when i compiled my program to .exe using pyinstaller, things started to break down unfortunately. I can only get to read STDERR and the first line of STDOUT, depending on combination of parameters i use.

I have tried several parameters for subprocess.Popen, including startup_info and creation_flags. It just doesnt seem to work. If stdin is set to subprocess.DEVNULL, and i run the app without compiling it, it outputs the same thing when i compile the app using the --windowed flag with stdin=None.

All commands within the cmd script are actually executed by PsExec. I tested this with msg * hello at the end of the script. Its just that subprocess only returns the first line of STDOUT.

I just want to process STDOUT and STDERR, and ignore STDIN. But i do not want any console windows visible anywhere. Can anyone provide me with some tips and tricks? Thanks in advance!

Anyway, i created this small program in my free time for a company i work for. If anyone is interested and willing to look into the source, this is the GitHub repo: https://github.com/vlreinier/CmdDeployer/blob/main/Progression.py (line 235-290)

EDIT: A temporary fix for hiding the CMD window during runtime is using the function below, and compiling without the --windowed flag. This will NOT however hide the console window during program startup.

def cmd_visibility(show=True):
    hWnd = ctypes.WinDLL('kernel32').GetConsoleWindow()
    if hWnd:
        ctypes.WinDLL('user32').ShowWindow(hWnd, int(show))
vlreinier
  • 11
  • 2
  • Have you tried replacing the while loop with `lines = process.stdout.readlines()`, then iterating over that? Alternatively, you could add `if not line: break`, which would exit if your program is no longer printing to stdout. If this is happening (and depending on what your program is doing), you could try adding a delay instead of breaking out of the loop. – jmklam Aug 09 '21 at 19:31
  • The `subprocess` command looks wrong, do you really want to pass in a single backslash? Also, maybe try tokenizing it: `subprocess.Popen(["psexec", r"\\computer", "-c", "-f", "-s", "commands.cmd"], ...)` (where I have assumed you want a doubled literal backslash, and thus an `r`-string). – tripleee Aug 10 '21 at 06:02
  • You are both correct. I want to read the output live, so `readlines()` will not work for me (even so it returns the same output). I will provide a more exact version of my code. Unfortunately both suggestions do not work. – vlreinier Aug 10 '21 at 06:49
  • `"-n 10",` should be two separate parameters `"-n", "10",` – tripleee Aug 10 '21 at 11:45
  • Jup i encountered that one too ;P – vlreinier Aug 10 '21 at 14:37

0 Answers0