iT邦幫忙

0

[Python] 用PyautoGUI 執行桌面上的檔案被Python視窗擋住

  • 分享至 

  • xImage

用PyautoGUI 寫了一個很簡單執行桌面程式再去點擊按鈕的動作,

但是現在很尷尬是Python跑起來後的視窗會擋住我要執行的桌面程式,(跑到前景)

我有試過調命令提至字元的視窗大小但沒有用,

所以想問一下我可以把Python執行後放到背景去執行嗎 ? 或是有其他比較smart的作法

感恩 感謝使用你的時間幫我

yaoa789 iT邦新手 5 級 ‧ 2023-08-28 14:01:20 檢舉
正好遇到相同的問題,感謝樓主大大提問
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

0
ccutmis
iT邦高手 2 級 ‧ 2023-02-18 19:38:19

看看這是不是你要的...

import win32gui,win32con
import time

time.sleep(2)
Minimize = win32gui.GetForegroundWindow()
win32gui.ShowWindow(Minimize, win32con.SW_MINIMIZE)
print("lol...I'm hiding...")

需要安裝套件 : pip install pypiwin32

資料來源:

https://stackoverflow.com/questions/25466795/how-to-minimize-a-specific-window-in-python


上述的技巧適用python程式是在 CMD 視窗執行,如果是編譯成執行檔(.EXE)的,
以下是一個複雜但更實用的作法,適用於目標對象是執行檔或某些已開啟知道部份標題名的視窗…

實作前先大概說明,你要執行腳本的對象如果是視窗,你要考慮它有可能隨時變成不在前景的狀態,比如說你開了一個chrome視窗,並把它最大化,目前它是位於前景,但是二秒後系統右下角跳出一個通知,這時chrome視窗就不在前景了,如果你的pyautogui(或其它類似的像autoit)腳本沒考慮這些,那不出意外的話就要出意外了。

在這裡我示範的就是如何把特定視窗設為前景,首先開一個新文件,並將它命名為"WindowMgr.py"(存在跟你要執行的腳本同一目錄)

import win32gui, win32com.client, win32con, winxpgui, win32api, ctypes
from re import match
from subprocess import Popen,PIPE

class WindowMgr:
    def __init__ (self):
        self._handle = None
        self.is_exist = False
    """Pass to win32gui.EnumWindows() to check all the opened windows"""
    def _window_enum_callback(self, hwnd, wildcard):
        if match(".*"+wildcard+"*", str(win32gui.GetWindowText(hwnd))) is not None:
            self._handle = hwnd
            self.is_exist = True
    """ 找到標題內含wildcard字串的視窗 """
    def find_window_wildcard(self, wildcard):
        self._handle = None
        self.is_exist = False
        win32gui.EnumWindows(self._window_enum_callback, wildcard)
    """ 將目標視窗設為前景 """
    def set_foreground(self):
        win32gui.SetForegroundWindow(self._handle)
    """ 執行 find_window_wildcard ()後要找另一個目標視窗前,需先執行 reset() """
    def reset(self):
        shell = win32com.client.Dispatch("WScript.Shell")
        shell.SendKeys('%')
    """ 執行外部程式,先偵測程式是否已執行,若無才執行外部程式,程式執行後會把標題含wildcard字串的視窗設為目標視窗 """
    def run_program(self, program_loc, wildcard, program_param=''):
        self.find_window_wildcard(wildcard)
        if not self.is_exist:
            cmd = program_loc if program_param=='' else program_loc+" "+program_param
            Popen(cmd, stdout=PIPE, creationflags=0x08000000)
            while not self.is_exist:
                msg_str = 'finding window please wait...'
                print(msg_str, end='')
                print('\b' * len(msg_str), end='', flush=True)
                self.find_window_wildcard(wildcard)

WindowMgr.py 裡面示範的是 python 類別的寫法,可以先不用理會裡面是什麼,先學會使用就好。接著在同一個目錄新建一個文件 "run.py",內容如下:

from WindowMgr import WindowMgr
import pyautogui as p

win = WindowMgr()
win.run_program(r"C:\Windows\Notepad.exe","記事本")
win.reset()
p.sleep(15)
win.find_window_wildcard("記事本")
win.set_foreground() # 把目標視窗設為前景
p.typewrite('Hello World...\nGood Bye...\n',interval=0.2)

# 以下的動作說明: 按 組合鍵 alt+f (開啟主選單 檔案 )接著按 組合鍵 alt +x (結束),因為沒有存檔會跳出詢問對話框,要按"→"再按"enter"
p.hotkey('alt', 'f')
p.sleep(0.5)
p.hotkey('alt','x')
p.sleep(2)
p.press('right')
p.sleep(0.5)
p.press('enter')
# 相關細節可以查詢 https://pyautogui.readthedocs.io/en/latest/keyboard.html

可以直接執行 run.py 試試結果,程式執行後它會開啟記事本(若已存在就不會再開啟新的,這個呼叫方式不會讓流程卡在開啟這一步),然後等待15秒這過程中你可以切到瀏覽器,等15秒後它會將記事本設為前景,然後執行已經寫好的 pyautogui 腳本(輸入文字,關閉)

如果你只是單純想寫自動執行腳本的話,找現成的腳本軟體比較簡單(exam: Autoit,按鍵精靈之類的)。

看更多先前的回應...收起先前的回應...
lalelee iT邦新手 4 級 ‧ 2023-02-20 08:46:25 檢舉

謝謝^^ IT邦真的很溫暖, 都是願意教學分享熱情的好人 感恩

ccutmis iT邦高手 2 級 ‧ 2023-02-20 08:55:14 檢舉

不用客氣~
一大早就收到好人卡...
/images/emoticon/emoticon04.gif

lalelee iT邦新手 4 級 ‧ 2023-02-20 09:39:30 檢舉

可以將視窗最小化了 感謝^^ ,但是不知道為什麼變成我的滑鼠不會動, 一直到我把我要執行的程式視窗關掉它才開始動 @@
麻煩幫我看一下那裡有問題 謝謝
我的code 長這樣:

import pyautogui as p
import win32gui
import win32con
import os 
#這個方法使用win32gui模組取得Python視窗的句柄,再將視窗最小化
python_window = win32gui.GetForegroundWindow()
win32gui.ShowWindow(python_window, win32con.SW_MINIMIZE)
#要執行的程式
os.chdir("C:\\Program Files\\Fortinet\\FortiClient\\")
os.system("FortiClient.exe")
p.sleep(5)
#去按程式開起來的按鈕"連結"
p.click(960,793,duration=2)
ccutmis iT邦高手 2 級 ‧ 2023-02-20 10:18:22 檢舉

你試試

import pyautogui as p
import win32gui
import win32con
import os 
#這個方法使用win32gui模組取得Python視窗的句柄,再將視窗最小化
python_window = win32gui.GetForegroundWindow()
win32gui.ShowWindow(python_window, win32con.SW_MINIMIZE)
#要執行的程式
os.chdir("C:\\Program Files\\Fortinet\\FortiClient\\")
print(os.system("FortiClient.exe")) # print(0)
p.sleep(5)
#去按程式開起來的按鈕"連結"
print("sleep 5 sec")
p.click(960,793,duration=2)

然後重新執行 注意cmd裡面的變化,在執行到print(os.system("FortiClient.exe"))時,執行流程就停在那邊了(不會繼續後面的動作),所以你這個作法不可行。

以你這寫法的話,可行作法是:

  1. 先手動執行 FortiClient.exe,確定它在視窗前景。
  2. 再執行python腳本:
import pyautogui as p
import win32gui
import win32con
import os 
#這個方法使用win32gui模組取得Python視窗的句柄,再將視窗最小化
python_window = win32gui.GetForegroundWindow()
win32gui.ShowWindow(python_window, win32con.SW_MINIMIZE)
#要執行的程式
p.sleep(1)
p.click(960,793,duration=2)

但這都不是太好的方法...

ccutmis iT邦高手 2 級 ‧ 2023-02-20 13:15:56 檢舉

我在回答的本文裡面補充了進階版的作法(將目標視窗設為前景),可以參考看看...

0
JamesDoge
iT邦高手 1 級 ‧ 2023-02-18 21:02:22

你可以試著使用以下方法將Python視窗最小化,讓桌面程式能夠在前景執行:

import pyautogui

pyautogui.hotkey('winleft', 'm')

這個方法會模擬按下Win + M鍵,將所有視窗最小化。如果你只想最小化Python視窗,可以使用以下方法:

import win32gui

python_window = win32gui.GetForegroundWindow()
win32gui.ShowWindow(python_window, win32con.SW_MINIMIZE)

這個方法使用win32gui模組取得Python視窗的句柄,再將視窗最小化。你需要先使用以下指令安裝win32gui模組:

pip install pypiwin32

lalelee iT邦新手 4 級 ‧ 2023-02-20 09:40:39 檢舉

可以將視窗最小化了 感謝^^ ,但是不知道為什麼變成我的滑鼠不會動, 一直到我把要執行的視窗關掉它才開始動 @@
麻煩幫我看一下那裡有問題 謝謝
我的code 長這樣:

import pyautogui as p
import win32gui
import win32con
import os 
#這個方法使用win32gui模組取得Python視窗的句柄,再將視窗最小化
python_window = win32gui.GetForegroundWindow()
win32gui.ShowWindow(python_window, win32con.SW_MINIMIZE)
#要執行的程式
os.chdir("C:\\Program Files\\Fortinet\\FortiClient\\")
os.system("FortiClient.exe")
p.sleep(5)
#去按程式開起來的按鈕"連結"
p.click(960,793,duration=2)

我要發表回答

立即登入回答