Running external EXE from python - python

I'm running several portable apps from my python app.
Consider the following code:
import win32com.shell.shell as w32shell
import os
import sys
import win32process as process
PORTABLE_APP_LOCATION = "C:\\Windows\\System32\\calc.exe"
#This function runs a portable application:
def runPortable():
try:
startObj = process.STARTUPINFO()
process.CreateProcess(PORTABLE_APP_LOCATION,None,None,None,8,8,None,None,startObj)
# OR
#w32shell.ShellExecuteEx(lpFile=PORTABLE_APP_LOCATION)
except:
print(sys.exc_info()[0])
runPortable()
1) Should I expect any differences in the execution of this code from pythonw or python ?
2) If I change PORTABLE_APP_LOCATION to the path to a portable version of CDBurnerXP and use the ShellExecuteEx option instead of CreateProcess, I see the process is started on Windows Task Manager but the actual window of the app isn't visible. This doesn't happen with other EXEs such as a portable version of GIMP that do show up after being ran. I assume this difference comes from a property of the executables. Anybody knows what's causing this?
3) Under what terms does Windows prompts the "Are you sure you want to run this EXE"? I believe CDBurnerXP is signed with a certificate but still sometimes Windows pops this question when trying to run this EXE from within python.
Thanks a lot.

About Your first question , you should pay attention that when executing python code using pythonw.exe runtime , your sys.stdout buffer is limited to 4096 Bytes and when overflowed will throw an IOError wich you will not see because the code is running windowless .

I am a newbie in this field. May be this can help you
use subprocess.call, more info here:
import subprocess
subprocess.call(["C:\\temp\\calc.exe"])
or
import os
os.system('"C:/Windows/System32/notepad.exe"')
i hope it helps you...

Related

Screenshotting the windows desktop when working through WSL

I'm primarily using Windows, where I run WSL2. So from a python script running in the subsystem, I would like to screenshot whatever is on windows monitor, as simple as such:
v1
import mss
import os
os.environ['DISPLAY'] = ':0'
with mss.mss() as sct:
sct.shot()
This gives only gives "Segmentation fault" error and no image. So I tried to setup vcxsrv in Windows and I'm able to open stuff from my subsystem in Windows through the server, however I cant get it the other way around..
I just want access to the windows screen so I can screenshot it. Any help about how to access the monitor through wsl would be greatly appreciated, I can't find much on google..
The problem with your attempted solution is that the WSL/Linux Python's mss, as you've found, isn't able to capture the Windows desktop. Being the Linux version of MSS, it will only be able to communicate with Linux processes and protocols like X. Starting up VcXsrv might get you part of the way there, in that you might be able to capture X output, but you may need to be running the Python app from inside a terminal that is running in a X window.
Regardless, you've said that your goal is to capture the entire Windows desktop, not just the X output in VcXsrv. To do that, you'll need to use a Windows process of some sort.
But don't worry; using WSL's interop, you can still do that from inside WSL/Linux Python. We just need to call out to a Windows .exe of some sort.
There are literally dozens of third-party apps that you could use in Windows to create a screenshot. But I prefer to use a solution that doesn't require any additional installation.
So I resorted to PowerShell for this, since you can easily call powershell.exe and pass in a script from WSL. There are a number of examples here on Stack Overflow, but I ended up going slightly "lower tech" to try to simplify a bit. The code here is most similar to this solution, so refer to that if you want to expand on this.
From WSL/Linux Python:
import os
os.system("""
powershell.exe \"
Add-Type -AssemblyName System.Windows.Forms
[Windows.Forms.Sendkeys]::SendWait('+{Prtsc}')
\$img = [Windows.Forms.Clipboard]::GetImage()
\$img.Save(\\\"\$env:USERPROFILE\\Pictures\\Screenshots\\screenshot.jpg\\\", [Drawing.Imaging.ImageFormat]::Jpeg)\"
""")
That essentially sends the ShiftPrintScreen key chord to capture the current desktop to the clipboard, then saves the clipboard. It can get slightly hairy with the quoting, since you are essentially wrapping PowerShell inside a /bin/sh inside a Python script.
Note that, even though you are in Linux Python, since it's the Windows PowerShell that we are calling, it takes the Windows path format (C:\Users\Username\Pictures...) rather than the Linux version (/mnt/c/Users/...).
While I didn't have any timing issues with this, you may need to insert small delays. Again, refer to the existing answer for that. This solution is primarily to explain how to do it through WSL's Python using PowerShell.
if you are on a laptop you could hit the windows button and prtsc to take a screenshot and if you are on PC you could use OBS its recording software that can do pretty much anything.

Run Windows application as a current user or admin

I'm trying to call Windows application (exe file) using Python (from Jupyter). The problem is, looks like, the application starts under another user, because all the user settings in that application are reset. Or, maybe this happening because the exe file is prevented from accessing required .ini file? The second is even more likely.
I tried each way to run the application, that I could find: os, subprocess, pywinauto, ShellExecuteEx. Nothing worked for me so far (I'm just starting to work with Python). Any thoughts on this?
Thank you!
The problem was that I didn't set the working directory.
This way app starts properly:
import os
os.chdir('C:\\Folder\\Subfolder')
os.system("app.exe")

Python automate open application

Please give me idea regarding how to tackle this problem. I am not able to find any resource regarding this. Your help will be immensely valuable. So we have one limited license software. And want to reiterate the python invoking the application. If the application gives the error that licence is not available it should close the application and wait for sometime say 1 min and again invoke the process, it should do so endlessly until a licence is available and the application is finally open.
I am able to open the application using
Import os
os.startfile('application executable')
After this I want the application to know if there is an error window popping , it should close the window and wait for sometime and again open the application
os.startfile returns as soon as the associated application is launch so use Popen instead.
As you are using windows use these steps.
To Open a Shortcut using Popen on Windows first install pywin32
Step one:
python -m pip install pywin32
Step two:
Navigate to your python Scrips folder something like
C:\Users\Name\AppData\Local\Programs\Python\Python38-32\Scripts then type the command.
pywin32_postinstall.py -install
Then the code to use Popen is.
import subprocess
import win32com.client, win32api
shell = win32com.client.Dispatch("WScript.Shell")
shortcut = shell.CreateShortCut(r'path to shortcut')
long_path = shortcut.Targetpath
p = subprocess.Popen(long_path)
p.wait()

How to run python script on background/as a process?

I want to run a python script as a process/in the background. I searched and found pythonw.exe but when I do pythonw.exe name_of_my_script.py nothing happened. Am I doing something wrong and/or how else would I run it in the background?
This is part of my code that do problem :
from selenium import webdriver
I will thank you for any help whatsoever.
note:
With the help of the comments here, I understood that also python.exe running don't work and bring error - NameError: name 'PROTOCOL_TLS' is not defined ( even tough in normal running it doesn't have errors.
edit:
i used http://pytoexe.com/ and i got exe file that work but the cmd console still exist ( mabye it because i use phantomjs ? ) click here
You can create your own exe by going to http://pytoexe.com .
After that convert your script. Choose windows-based and convert it.
You'll not have any problems after that. Hope that helps.
I'd approach this by using threading module, and use os.fork() - but I'm not running Windows. I suggest having a look through Difference in behavior between os.fork and multiprocessing.Process for other OSes.
By "I want to run a python script as a process/in the background," do you mean make the window not visible? if so, just save the script as .pyw instead of .py

python as a "batch" script (i.e. run commands from python)

I'm working in a windows environment (my laptop!) and I need a couple of scripts that run other programs, pretty much like a windows batch file.
how can I run a command from python such that the program when run, will replace the script? The program is interactive (for instance, unison) and keeps printing lines and asking for user input all the time.
So, just running a program and printing the output won't suffice. The program has to takeover the script's input/output, pretty mcuh like running the command from a .bat file.
I tried os.execl but it keeps telling me "invalid arguments", also, it doesn't find the program name (doesn't search the PATH variable); I have to give it the full path ..?!
basically, in a batch script I can write:
unison profile
how can I achieve the same effect in python?
EDIT:
I found out it can be done with os.system( ... ) and since I cannot accept my own answer, I'm closing the question.
EDIT: this was supposed to be a comment, but when I posted it I didn't have much points.
Thanks Claudiu, that's pretty much what I want, except for a little thing: I want the function to end when the program exits, but when I try it on unison, it doesn't return control to the python script, but to the windows command line environment
>>> os.execlp("unison")
C:\>Usage: unison [options]
or unison root1 root2 [options]
or unison profilename [options]
For a list of options, type "unison -help".
For a tutorial on basic usage, type "unison -doc tutorial".
For other documentation, type "unison -doc topics".
C:\>
C:\>
C:\>
how to get around this?
You should create a new processess using the subprocess module.
I'm not fluent in windows processes but its Popen function is cross-platform, and should be preffered to OS specific solutions.
EDIT: I maintain that you should prefer the Subprocess module to os.* OS specific functions, it is cross-platform and more pythonic (just google it). You can wait for the result easily, and cleanly:
import os
import subprocess
unison = os.path.join(os.path.curdir, "unison")
p = subprocess.Popen(unison)
p.wait()
I found out that os.system does what I want,
Thanks for all that tried to help.
os.system("dir")
runs the command just as if it was run from a batch file
import subprocess
proc = subprocess.Popen(['unison', 'profile'], stderr=subprocess.PIPE,
stdout=subprocess.PIPE, stdin=subprocess.PIPE)
proc.stdin.write('user input')
print proc.stdout.read()
This should help you get started. Please edit your question with more information if you want a more detailed answer!
os.execlp should work. This will search your path for the command. Don't give it any args if they're not necessary:
>>> import os
>>> os.execlp("cmd")
D:\Documents and Settings\Claudiu>Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.
D:\Documents and Settings\Claudiu>

Categories

Resources