I am using AutoItX3.Control via win32com.client to detect and close Windows security dialog ("do you trust..."). I use WinExist with window title\text and It works fine when running the python script (Autoit version is 3.3.8.1).
Problem is with the compiled Python script (compiled with PyInstaller). The window is not detected and I can't close it. When I run the Autoit application (SciTE4AutoIt3) it does detect the window.
Any advice?
///// adding some more info:
using the following autoit options:
Opt('WinWaitDelay', 500)
Opt('SendKeyDelay', 8)
Opt('WinTitleMatchMode', 4)
Opt('WinSearchChildren', 1)
Opt('SendKeyDownDelay', 10)
Opt('WinDetectHiddenText', 1)
also, Im running the autoit on another process as an instance of the Process class (Process(target=handle_window_func))
Did you try to use the classic method to set the the active X options? Like:
oAutoItx.AutoItSetOption("WinTitleMatchMode", 4)
instead of:
oAutoItx.Opt("WinTitleMatchMode", 4)
Also AutoItx help says: "Mode 4 ("only" Kept for backward compatibility)".
So check your options and took the simplest you can use.
Try using the following code:
import pythoncom
pythoncom.CoInitialize()
This initializes the COM libraries for the calling thread.
See more info here:
http://docs.activestate.com/activepython/2.5/pywin32/pythoncom__CoInitialize_meth.html
Solved by running both the autoit functionality and the process triggering the pop up window in the same script and monitoring for the pop up while the process runs:
popup_p = Popen(*cmd_args, no_wait=True, *cmd_kwargs)
while popup_p.is_running():
handle_window_func()
time.sleep(1)
Note that Popen is run with no_wait - returns the process without waiting for it to finish.
Related
I am trying to open a window application when it is not opened in the background. To do that, I need to check if the process is running in the background. I am using pymen to check if the calc.exe is running, and if it's not, I will use subprocess to open a new calc.exe window. However, the code that I am using is not detecting if my calc.exe is actually running or not. It will always be Calculator is Not Running...
from pymem import Pymem
try:
pm = Pymem('calc.exe')
print('Calculator Started And Is Running....')
except:
print ('Calculator Is Not Running....')
I believe that the code is going through the details tab as shown as below to check if calc.exe is running or not. However, I can't find it in here as well even though the calculator app is running.
The detail tab in Task Manager
App like Notepad and Chrome are working fine but calculator. I have no idea why it is not working for calculator.
From Microsoft Calculator Windows 10:
The Calculator in non-LTSC editions of Windows 10 is a Universal
Windows Platform app. In contrast, Windows 10 LTSC (which does not
include universal Windows apps) includes the traditional calculator,
but which is now named win32calc.exe. … Both the universal Windows
app and LTSC's win32calc.exe register themselves with the system as
handlers of a 'calculator:' pseudo-protocol. … All Windows 10
editions (both LTSC and non-LTSC) continue to have a calc.exe, which
however is just a stub that launches (via ShellExecute) the
handler that is associated with the 'calculator:' pseudo-protocol.
In other words, calc.exe is merely a wrapper which launches another executable:
import psutil
import subprocess
import time
def list_calc(phase):
print(phase)
for proc in psutil.process_iter():
if proc.name().startswith( PROCNAME):
print( proc.name())
print( proc.cmdline()[0])
if proc.name() == 'CalculatorApp.exe':
proc.kill()
PROCNAME = 'Calc'
list_calc('- before:')
calc = subprocess.Popen([PROCNAME+'.exe'])
time.sleep(3) # wait until calculator window appears
list_calc('- after:')
Result: ver && .\SO\75191242.py
Microsoft Windows [Version 10.0.19045.2486]
- before:
- after:
CalculatorApp.exe
C:\Program Files\WindowsApps\Microsoft.WindowsCalculator_11.2210.0.0_x64__8wekyb3d8bbwe\CalculatorApp.exe
This is a frequent question, but reading the other threads did not solve the problem for me.
I provide the full paths to make sure I have not made any path formulation errors.
import subprocess
# create batch script
myBat = open(r'.\Test.bat','w+') # create file with writing access
myBat.write('''echo hello
pause''') # write commands to file
myBat.close()
Now I tried running it via three different ways, found them all here on SO. In each case, my IDE Spyder goes into busy mode and the console freezes. No terminal window pops up or anything, nothing happens.
subprocess.call([r'C:\\Users\\felix\\folders\\Batch_Script\\Test.bat'], shell=True)
subprocess.Popen([r'C:\\Users\\felix\\folders\\Batch_Script\Test.bat'], creationflags=subprocess.CREATE_NEW_CONSOLE)
p = subprocess.Popen("Test.bat", cwd=r"C:\\Users\\felix\\folders\\Batch_Script\\")
stdout, stderr = p.communicate()
Each were run with and without the shell=True setting, also with and without raw strings, single backslashes and so on. Can you spot why this wont work?
Spyder doesn't always handle standard streams correctly so it doesn't surprise me that you see no output when using subprocess.call because it normally runs in the same console. It also makes sense why it does work for you when executed in an external cmd prompt.
Here is what you should use if you want to keep using the spyder terminal, but call up a new window for your bat script
subprocess.call(["start", "test.bat"], shell=True)
start Starts a separate Command Prompt window to run a specified program or command. You need shell=True because it's a cmd built-in not a program itself. You can then just pass it your bat file as normal.
You should use with open()...
with open(r'.\Test.bat','w+') as myBat:
myBat.write('echo hello\npause') # write commands to file
I tested this line outside of ide (by running in cmd) and it will open a new cmd window
subprocess.Popen([r'Test.bat'], creationflags=subprocess.CREATE_NEW_CONSOLE)
Hey I have solution of your problem :)
don't use subprocess instead use os
Example :
import os
myBatchFile = f"{start /max} + yourFile.bat"
os.system(myBatchFile)
# "start /max" will run your batch file in new window in fullscreen mode
Thank me later if it helped :)
I try to write a programm in python that notifies me, when a shell like cmd gets opened.
Until now I did the following in python.
Check for new starting processes, get the name of the process and check if its name is cmd.exe.
This works if I start a cmd process manually myself.
But it Turns out if i open a shell with subprocess.getoutput(command) from the subprocess library in python there is no shell listed in the prosesses and I also cant see it in taskmanager.
So I assumed its a childprocess of the pythonscripts process running?
My next Idea was to list all the modules a process is using and check for cmd.exe in the modules.
It turns out the pythonscript with subprocess.getoutput(command) does not use cmd.exe in the modules. Strange.
So right now I am not sure how I could detect the shell or if I am even on the right way.
Maybe I need to find the childprocesses of a the pythonprocess? Or is it possible to get a shell without calling cmd.exe I honestly dont know enough about it.
Maybe its better to check for chertain dlls in the used methods by a process?
I also tried to look in the subprocess.py library but it is difficult for me to understand and it seems to atleast pass over cmd as a parameter for subprocess.getoutput() method.
Can somebody help?
Thank you.
UPDATE:
I use this code to detect the process:
import wmi
c = wmi.WMI()
process_watcher = c.Win32_Process.watch_for("creation")
while True:
new_process = process_watcher()
print(new_process.Caption, new_process.ProcessId)
if new_process.Caption =="cmd.exe":
pid = new_process.ProcessID
break
But if I run this code
import subprocess
output = subprocess.getoutput("ipconfig")
print(output)
The only process detected is pythonw.exe
But if I run
import subprocess
while True:
output = subprocess.getoutput("ipconfig")
print(output)
At some point it find cmd.exe.
So I assume that wmi takes to long to detect the process. So cmd is already closed and does not get found.
Any Ideas how to do this a better way?
I didnt know practic version of solution.But you can use pyautogui for it if you want.You can write a program with pyautogui that notifies you when it find cmd logo at task bar.Example:
import pyautogui
cmdlogo = pyautogui.locateOnScreen('get screenshot of cmd logo and write file name here example:'cmd.png'')
While True:
if cmdlogo:
print('write here what yo want to say when it finds cmd')
else:
pyautogui.sleep(5)
I'm trying to implement an auto-update functionality, so I'm programmatically downloading the update_myprog.exe (created with Inno Setup), and then I want to close the program immediately and run update_myprog.exe. Currently I am using subprocess.Popen() to run it, but for some reason when the update_myprog.exe runs, I get an error: "Setup was unable to automatically close all applications. It is recommended that you close all applications using files that need to be updated by Setup before continuing.". When I run update_myprog.exe myself (not through the original program), it works just fine.
So, I'm wondering, is it a problem with my Python, with Inno Setup, or something else?
Below is a simplified version of my problem, extracting just the relevant code.
Here is my python code (autoupdate.py):
import wx
import subprocess
import win32process
import tempfile
class Main(wx.Frame):
def __init__(self,*args,**kwargs):
wx.Frame.__init__(self,*args,**kwargs)
self.SetTitle('MyProg v1')
self.updatebutton=wx.Button(self,label='Update')
self.updatebutton.Bind(wx.EVT_BUTTON,self.update)
def update(self,event):
canupdate=True
if(canupdate):
tempdir=tempfile.mkdtemp()
fname=os.path.join(tempdir,'update_myprog.exe')
proc = subprocess.Popen('"update_myprog.exe" /SP- /silent /noicons /nocancel /password="pw"', creationflags=win32process.DETACHED_PROCESS,shell=True)
self.Destroy()
sys.exit()
app = wx.App(False)
Main(parent=None).Show(True)
app.MainLoop()
I then compiled it with:
pyinstaller "autoupdate.py" --distpath="make\dist" --workpath="make\build"
And then I made the installer (update_myprog.exe) with the following Inno Setup Script:
[Setup]
AppId={{7FBA93BE-7DC4-4114-91DF-DD524A078F63}
AppName=My Program
AppVersion=1
AppPublisher=My Company, Inc.
AppPublisherURL=http://www.example.com/
AppSupportURL=http://www.example.com/
AppUpdatesURL=http://www.example.com/
DefaultDirName={pf}\My Program
DefaultGroupName=My Program
AllowNoIcons=yes
OutputDir=make/Installer
OutputBaseFilename=update_myprog
Password=pw
Compression=lzma
SolidCompression=yes
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: "C:\Python27\My Projects\Test Update\make\dist\autoupdate\autoupdate2.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: "C:\Python27\My Projects\Test Update\make\dist\autoupdate\*"; DestDir: "{app}";
[Icons]
Name: "{group}\My Program"; Filename: "{app}\autoupdate.exe"
Name: "{commondesktop}\My Program"; Filename: "{app}\autoupdate.exe"; Tasks: desktopicon
[Run]
Filename: "{app}\autoupdate.exe"; Description: "{cm:LaunchProgram,My Program}"; Flags: nowait postinstall
Then I run the installer (works fine), and copy the installer into the directory it installed to. Then I run my program, and click the button, and it gives me an error. Why?
It might help me if somebody else could run do the above steps on their computer, and let me know if they have the same problems. All help is appreciated.
Old Question:
So, I basically have the same question as Spawning a non-child process in python but for Windows.
I'm trying to implement an auto-update functionality, so I'm programmatically downloading the update_myprog.exe (created with Inno Setup), and then I want to close the program immediately and run update_myprog.exe. Currently I am using subprocess.Popen() to run it, but it seems like it is still a child of the original program, and thus cannot overwrite the exe file of the original to update it.
Would os.system be what I'm looking for, or is there some other solution?
If you want to completely detach the process you can use:
from win32process import DETACHED_PROCESS
from subprocess import Popen
Popen(["python","xyz.py"],creationflags=DETACHED_PROCESS,shell=True).pid
Update
Compiling it could lead to it's own little nightmare with the use of temporary directories, but that's another question, and god knows how wx is behaving here. Be sure that download is actually finishing and try execfile(filename) instead of Popen. If no luck there, try the following:
from subprocess import Popen, CREATE_NEW_CONSOLE,CREATE_NEW_PROCESS_GROUP
Popen(["python", 'xyz.py'],shell = True | CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE)
Failing that, repost the question and let someone else have a look. Sorry I couldn't be of more help. Let me know how you sussed it in the end.
I implemented auto-update using Inno Setup and PyInstaller over a year ago.
You need to call self.destroy() before the subprocess. This is so that after you call Inno, you can exit immediately. You can also use the /FORCECLOSEAPPLICATIONS flag so that Inno-Setup can close your program in case the sys.exit() was not fast enough.
I've been writing a small utility application using Python 3 (the below testcase also works in Python 2, however) and PyQt 4 that uses the code module to spawn a REPL prompt allowing interaction with a Qt window.
Unfortunately I've hit a problem I've been unable to solve: When I exit() the app while code is inside input() (known as raw_input() in Python 2.x), my Linux terminal subsequently no longer echoes typed characters. I.e. the terminal appears to be left in a broken state, presumably due to some escape sequence issued by input().
I've tried a variety of approaches to fix this, from using the curses module and other means to reset the terminal prior to running exit, to trying to emulate the stdin stream to exit by actually handing exit() to input() (unfornunately code.InteractiveConsole.push() does not work that way, as one might think it would), to trying to write my own non-blocking input() using threading, but I've been unable to pull together something working.
Here, here, here and here are discussions of similar problems.
Finally, here is a reduced testcase to demonstrate the problem:
#!/usr/bin/env python3
import code
import sys
from PyQt4.QtGui import QApplication, QWidget
app = QApplication(sys.argv)
app.lastWindowClosed.connect(exit)
widget = QWidget()
widget.show()
code.interact()
For those unfamiliar with (Py)Qt, this will open a blank window, and when it is closed, the connection from app's lastWindowClosed signal will cause a call to the built-in exit() function to happen. This occurs while the code module is executing a call to input() to read from sys.stdin. And here, when I close the window, typing into the terminal afterwards doesn't show any of the types characters.
I'm mainly using Python 3, and the actual app uses Python 3-specific code, but I've tried the testcase in Python 2.7 as well and it shows the same problem.
Try os.system('stty sane'). The stty sane is supposed to reset echo, and some other things apparently.
This is no real solution to the problem, but
if you type "reset" in the terminal after you've closed the app, it goes back to normal.
I had similar issues once when developing a c application that didn't close a pipe correctly.
Maybe something similar is happening here aswell.
The answer from Quentin Engles worked for me too but as a Python neophyte I didn't understand where the stty sane was supposed to go. After some hunting and head scratching I figured out that exit was a reference to the exit() method so I created exiting() and passed a reference to it:
#!/usr/bin/env python3
import code
import sys
from PyQt4.QtGui import QApplication, QWidget
def exiting():
os.system('stty sane')
exit()
app = QApplication(sys.argv)
app.lastWindowClosed.connect(exiting)
widget = QWidget()
widget.show()
code.interact()
I've run in to the same problem using the curses module. Using the other answer on this page, I've sidestepped the problem with import os at the beginning of the program, and then ending the program with os.system('reset').