ฉันจะรันโปรแกรมเมื่อเริ่มต้น, ย่อขนาดเล็กสุดได้อย่างไร?


19

ฉันแค่ต้องการให้โทรเลขทำงานและฉันได้เพิ่มลงในแอปเริ่มต้น ประเด็นคือฉันต้องการให้มันลดลง คำสั่งใด ๆ


คำสั่งให้เริ่มต้น Telegram คืออะไรและชื่อหน้าต่างหลังแอปพลิเคชันเริ่มทำงานคืออะไร
Jacob Vlijm

คำสั่งที่ฉันใช้เป็นเพียงเส้นทางของแอปและชื่อหน้าต่างคือ Telegram Desktop
Hossein Soltanloo

สวัสดี Hossien ในกรณีที่คุณอาจต้องการใช้ pid แทนชื่อหน้าต่างแก้ไขคำตอบของฉัน
Jacob Vlijm

@JacobVlijm ขอบคุณ! มันมีประสิทธิภาพและเป็นประโยชน์อย่างมาก! อย่างไรก็ตามวิธีแรกทำงานได้อย่างราบรื่นในกรณีชื่อหน้าต่างตัวแปร ทำได้ดีมาก!
Hossein Soltanloo

1
@SumeetDeshmukh คุณเป็นคนดีและใจดีอย่างไม่น่าเชื่อ จริงๆ!
Jacob Vlijm

คำตอบ:


29

การเริ่มแอปพลิเคชั่นลดลง

การเริ่มต้นแอปพลิเคชันด้วยวิธีที่ย่อเล็กสุดใช้สองคำสั่ง:

  • การเริ่มต้นแอปพลิเคชัน
  • ย่อขนาดหน้าต่าง

ดังนั้นคำสั่งหรือสคริปต์จะต้อง "ฉลาด"; คำสั่งที่สองควรรอให้หน้าต่างแอปพลิเคชันปรากฏขึ้นจริง

วิธีการทั่วไปในการเริ่มต้นแอปพลิเคชั่นลดลง

สคริปต์ด้านล่างทำเช่นนั้นและสามารถใช้เป็นโซลูชันทั่วไปในการเริ่มต้นแอปพลิเคชันในแบบที่ย่อเล็กสุด เพียงเรียกใช้ในรูปแบบของไวยากรณ์:

<script> <command_to_run_the_application> <window_name>

บท

#!/usr/bin/env python3
import subprocess
import sys
import time

subprocess.Popen(["/bin/bash", "-c", sys.argv[1]])
windowname = sys.argv[2]

def read_wlist(w_name):
    try:
        l = subprocess.check_output(["wmctrl", "-l"]).decode("utf-8").splitlines()
        return [w.split()[0] for w in l if w_name in w][0]
    except (IndexError, subprocess.CalledProcessError):
        return None

t = 0
while t < 30:
    window = read_wlist(windowname)
    time.sleep(0.1)
    if window != None:
        subprocess.Popen(["xdotool", "windowminimize", window])
        break
    time.sleep(1)
    t += 1

วิธีใช้

สคริปต์ต้องการทั้งwmctrlและxdotool:

sudo apt-get install wmctrl xdotool

แล้ว:

  1. คัดลอกสคริปต์ลงในไฟล์ว่างแล้วบันทึกเป็น startup_minimizd.py
  2. ทดสอบสคริปต์ด้วยgeditคำสั่ง(เช่น) :

    python3 /path/to/startup_minimizd.py gedit gedit
    
  3. หากทำงานได้ดีให้เพิ่มคำสั่ง (สำหรับแอปพลิเคชันของคุณ) ไปที่ Startup Applications

คำอธิบาย

  • สคริปต์เริ่มต้นแอปพลิเคชันโดยเรียกใช้คำสั่งที่คุณให้ไว้เป็นอาร์กิวเมนต์แรก
  • จากนั้นสคริปต์จะตรวจสอบรายการหน้าต่าง (ด้วยความช่วยเหลือwmctrl) สำหรับ windows ตั้งชื่อตามอาร์กิวเมนต์ที่สองของคุณ
  • หากหน้าต่างปรากฏขึ้นก็จะย่อเล็กสุดทันทีด้วยความช่วยเหลือของxdotool เพื่อป้องกันการวนซ้ำไม่สิ้นสุดหากหน้าต่างอาจไม่ปรากฏขึ้นด้วยเหตุผลบางอย่างสคริปต์จะดำเนินการ จำกัด เวลา 30 วินาทีเพื่อให้หน้าต่างปรากฏขึ้น

บันทึก

ไม่จำเป็นต้องพูดถึงว่าคุณสามารถใช้สคริปต์สำหรับหลาย ๆ แอปพลิเคชันได้ในครั้งเดียวเนื่องจากคุณรันสคริปต์ด้วยอาร์กิวเมนต์ที่อยู่นอกสคริปต์


แก้ไข

รับรู้หน้าต่างโดย pid ของมัน

หากชื่อหน้าต่างไม่แน่ใจหรือตัวแปรหรือมีความเสี่ยงของการปะทะกันของชื่อในชื่อของหน้าต่างการใช้pidเป็นวิธีที่เชื่อถือได้มากขึ้นในการใช้

สคริปต์ด้านล่างนี้ขึ้นอยู่กับการใช้ pid ของแอปพลิเคชันเช่นเดียวกับในเอาต์พุตของทั้งสองwmctrl -lpและps -efและ

การตั้งค่าค่อนข้างเหมือนกัน แต่ไม่จำเป็นต้องตั้งชื่อหน้าต่างในรุ่นนี้ดังนั้นคำสั่งในการรันคือ:

python3 /path/to/startup_minimizd.py <command_to_run_application>

เช่นเดียวกับสคริปต์แรกมันต้องการทั้งสองอย่างwmctrlและxdotool

บท

#!/usr/bin/env python3
import subprocess
import sys
import time

command = sys.argv[1]
command_check = command.split("/")[-1]

subprocess.Popen(["/bin/bash", "-c", command])

t = 1
while t < 30:
    try:
        w_list = [l.split() for l in subprocess.check_output(["wmctrl", "-lp"]).decode("utf-8").splitlines()]
        proc = subprocess.check_output(["pgrep", "-f", command_check]).decode("utf-8").strip().split()
        match = sum([[l[0] for l in w_list if p in l] for p in proc], [])
        subprocess.Popen(["xdotool", "windowminimize", match[0]])
        break
    except (IndexError, subprocess.CalledProcessError):
        pass
    t += 1
    time.sleep(1)

หมายเหตุเกี่ยวกับสคริปต์ที่สอง

แม้ว่าโดยทั่วไปแล้วเวอร์ชันที่สองควรมีความน่าเชื่อถือมากกว่าในกรณีที่แอปพลิเคชันเริ่มต้นด้วยสคริปต์ตัวตัดคำสั่ง pid ของคำสั่งจะแตกต่างจากแอปพลิเคชันที่ถูกเรียกใช้ในที่สุด

ในกรณีเช่นนี้ฉันขอแนะนำให้ใช้สคริปต์แรก



EDIT2 สคริปต์เฉพาะสำหรับ Steam

ตามที่ร้องขอในความคิดเห็นด้านล่างเวอร์ชันสร้างขึ้นเป็นพิเศษสำหรับการเริ่มต้นใช้งาน STEAM ย่อเล็กสุด

ทำไมต้องเป็นรุ่นเฉพาะสำหรับ Steam

ปรากฎว่าSteamทำงานค่อนข้างแตกต่างจากแอปพลิเคชัน "ปกติ":

  • ปรากฎว่ามันSteamไม่ได้ทำงานเพียงหนึ่ง pid แต่ไม่น้อยกว่า (ในการทดสอบของฉัน) แปด!
  • Steamทำงานเมื่อเริ่มต้นด้วยหน้าต่างอย่างน้อยสองหน้าต่าง (หน้าต่างเดียวเหมือน splash-) แต่บางครั้งหน้าต่างข้อความเพิ่มเติมจะปรากฏขึ้น
  • Windows ของ Steam มีpid 0ซึ่งเป็นปัญหาในสคริปต์เหมือนเดิม
  • หลังจากสร้างหน้าต่างหลักแล้วหน้าต่างจะถูกยกขึ้นเป็นครั้งที่สองหลังจากวินาทีที่สองดังนั้นการย่อขนาดเพียงครั้งเดียวจะไม่ทำ

พฤติกรรมที่พิเศษของการSteamขอสคริปต์รุ่นพิเศษซึ่งเพิ่มไว้ด้านล่าง สคริปต์เริ่มทำงานSteamและในช่วง 12 วินาทีมันจะคอยดูหน้าต่างใหม่ทั้งหมดของหน้าต่างที่เกี่ยวข้องWM_CLASSโดยตรวจสอบว่ามีการย่อขนาดเล็กสุดหรือไม่ ถ้าไม่สคริปต์จะทำให้แน่ใจว่าพวกเขาจะ

เช่นเดียวกับสคริปต์เดิมนี้หนึ่งในความต้องการwmctrlและxdotoolมีการติดตั้ง

บท

#!/usr/bin/env python3
import subprocess
import time

command = "steam"
subprocess.Popen(["/bin/bash", "-c", command])

def get(cmd):
    return subprocess.check_output(cmd).decode("utf-8").strip()

t = 0

while t < 12:
    try:
        w_list = [l.split()[0] for l in get(["wmctrl", "-l"]).splitlines()]
        for w in w_list:
            data = get(["xprop", "-id", w])
            if all(["Steam" in data, not "_NET_WM_STATE_HIDDEN" in data]):
                subprocess.Popen(["xdotool", "windowminimize", w])
    except (IndexError, subprocess.CalledProcessError):
        pass

    t += 1
    time.sleep(1)

ที่จะใช้มัน

  • เพียงแค่คัดลอกลงในไฟล์เปล่าแล้วบันทึกเป็น runsteam_minimized.py
  • เรียกใช้โดยคำสั่ง:

    python3 /path/to/runsteam_minimized.py
    

ว้าวเยี่ยมมาก! ฉันจะไม่ทันจับexcept:เพื่อส่งคืนไม่มี อาจดีกว่าปล่อยให้มันล้มเหลวเพื่อให้คุณเห็นสิ่งที่ล้มเหลว มิเช่นนั้นอาจทำลายสาเหตุที่แตกต่างกันและจะผ่านไปโดยไม่ตั้งใจ
fedorqui

1
@fedorqui สิ่งที่ดีมีข้อยกเว้นสองประการที่อาจเกิดขึ้นได้: subprocess.CalledProcesError (เนื่องจาก buggy wmctrl) และIndexError(ข้อยกเว้นปกติ) จะแก้ไขในหนึ่งนาที :) ขอบคุณที่พูดถึง
Jacob Vlijm

@HosseinSoltanloo คำสั่งที่คุณใช้ในการรันสคริปต์คืออะไร?
Jacob Vlijm

@JacobVlijm สคริปต์ทำงานได้ดี แต่มีปัญหาอื่นที่คุณอาจแก้ไขได้ เมื่อใดก็ตามที่ฉันมีข้อความที่ยังไม่ได้อ่านและฉันเปิดแอพชื่อหน้าต่างจะเปลี่ยนไปเป็น "Telegram (2)" เนื่องจากมีข้อความที่ยังไม่ได้อ่านสองข้อความและด้วยวิธีนี้สคริปต์จะไม่ทำงานเนื่องจากการเปลี่ยนแปลงในชื่อ
Hossein Soltanloo

2
@JDHolland ฉันแน่ใจว่าสามารถแก้ไขได้ จะมองเข้าไปในบางแห่งในอีกไม่กี่วันข้างหน้า :)
Jacob Vlijm

3

เป็นการดีที่จะให้สคริปต์ที่กำหนดโดยผู้ใช้ 72216 และ Sergey เป็นวิธีแก้ไขปัญหาทั่วไป แต่บางครั้งแอปพลิเคชันที่คุณต้องการเริ่มต้นย่อให้เล็กสุดก็มีสวิตช์ที่จะทำสิ่งที่คุณต้องการ

นี่คือตัวอย่างเล็ก ๆ น้อย ๆ ที่มีสตริงคำสั่งของโปรแกรมเริ่มต้นที่เกี่ยวข้อง:

  • Telegram (ตั้งแต่รุ่น 0.7.10) มี-startintrayตัวเลือก:<path-to-Telegram>/Telegram -startintray
  • Steam มี-silentตัวเลือก:/usr/bin/steam %U -silent
  • การส่งมี--minimizedตัวเลือก:/usr/bin/transmission-gtk --minimized

ใน Unity แอปพลิเคชันเหล่านี้จะย่อขนาดเป็นไอคอนในแถบเมนูด้านบนแทนที่จะเป็นไอคอนบนตัวเรียกใช้งานแม้ว่าไอคอนตัวเรียกใช้ปกติจะยังคงปรากฏขึ้นเมื่อคุณเริ่มใช้แอปพลิเคชัน แอปพลิเคชันอื่นอาจทำงานแตกต่างกัน


1

ฉันใช้สคริปต์ของยาโคบแล้วปรับเปลี่ยนเล็กน้อยเพื่อให้เป็นสากลมากขึ้น

#!/usr/bin/python

import os
import subprocess
import sys
import time
import signal

WAIT_TIME = 10


def check_exist(name):
    return subprocess.Popen("which "+name,
                            shell=True,
                            stdout=subprocess.PIPE
                            ).stdout.read().rstrip("-n")


def killpid(pidlist):
    for pid in pidlist:
        args = ["xdotool",
                "search",
                "--any",
                "--pid",
                pid,
                "--name",
                "notarealprogramname",
                "windowunmap",
                "--sync",
                "%@"]
        subprocess.Popen(args)


def killname(name):
    args = ["xdotool",
            "search",
            "--any",
            "--name",
            "--class",
            "--classname",
            name,
            "windowunmap",
            "--sync",
            "%@"]
    subprocess.Popen(args)


sys.argv.pop(0)

if check_exist(sys.argv[0]) == "":
    sys.exit(1)
if check_exist("xdotool") == "":
    sys.stderr.write("xdotool is not installed\n")
    sys.exit(1)
if check_exist("wmctrl") == "":
    sys.stderr.write("wmctrl is not installed\n")
    sys.exit(1)

try:
    prog = subprocess.Popen(sys.argv, preexec_fn=os.setsid)
except OSError, e:
    sys.exit(1)

time.sleep(WAIT_TIME)
idlist = subprocess.Popen("pgrep -g " + str(prog.pid),
                          shell=True,
                          stdout=subprocess.PIPE
                          ).stdout.read().splitlines()

ps1 = os.fork()
if ps1 > 0:
    ps2 = os.fork()

if ps1 == 0:  # Child 1
    os.setpgid(os.getpid(), os.getpid())
    killpid(idlist)
    sys.exit(0)
elif ps2 == 0:  # Child 2
    killname(os.path.basename(sys.argv[0]))
    sys.exit(0)
elif ps1 > 0 and ps2 > 0:  # Parent
    time.sleep(WAIT_TIME)
    os.killpg(os.getpgid(int(ps1)), signal.SIGTERM)
    os.kill(ps2, signal.SIGTERM)
    os.waitpid(ps1, 0)
    os.waitpid(ps2, 0)
    sys.exit(0)
else:
    exit(1)

ความแตกต่างที่สำคัญคือ:

  • โปรแกรมตั้งค่า group ID (GID) สำหรับกระบวนการ ดังนั้นกระบวนการลูกทั้งหมดและหน้าต่างของพวกเขาสามารถพบได้ง่าย
  • xdotool - ตัวเลือกซิงค์ใช้แทนห่วงในขณะที่
  • สคริปต์อนุญาตให้ส่งผ่านข้อโต้แย้งไปยังโปรแกรม

ควรตั้งค่า WAIT_TIME ใหญ่พอที่จะอนุญาตให้โปรแกรมแยกกระบวนการย่อย ในคอมพิวเตอร์ของฉันมันก็เพียงพอแล้วสำหรับโปรแกรมขนาดใหญ่เช่น Steam เพิ่มมันถ้าจำเป็น

ส่วนที่เพิ่มเข้าไป

xdotoolตัวเลือกของตัวเลือกwindowunmapอาจทำงานได้ดีกับบางแอปพลิเคชั่นและโปรแกรมถาด (เช่นถาดของ linux mint) ดังนั้นนี่เป็นเวอร์ชั่นทางเลือกของสคริปต์สำหรับข้อยกเว้นเหล่านั้น

#!/usr/bin/python

import os
import subprocess
import sys
import time
import signal

WAIT_TIME = 10


def check_exist(name):
    return subprocess.Popen("which "+name,
                            shell=True,
                            stdout=subprocess.PIPE
                            ).stdout.read().rstrip("-n")


def killpid(pidlist):
    for pid in pidlist:
        args = ["xdotool",
                "search",
                "--sync",
                "--pid",
                pid]
        for i in subprocess.Popen(args,
                                  stdout=subprocess.PIPE).\
                stdout.read().splitlines():
            if i != "":
                subprocess.Popen("wmctrl -i -c " +
                                 hex(int(i)), shell=True)


def killname(name):
    args = ["xdotool",
            "search",
            "--sync",
            "--any",
            "--name",
            "--class",
            "--classname",
            name]
    for i in subprocess.Popen(args,
                              preexec_fn=os.setsid,
                              stdout=subprocess.PIPE)\
            .stdout.read().splitlines():
        if i != "":
            subprocess.Popen("wmctrl -i -c " + hex(int(i)),
                             shell=True)


sys.argv.pop(0)

if check_exist(sys.argv[0]) == "":
    sys.exit(1)
if check_exist("xdotool") == "":
    sys.stderr.write("xdotool is not installed\n")
    sys.exit(1)
if check_exist("wmctrl") == "":
    sys.stderr.write("wmctrl is not installed\n")
    sys.exit(1)


try:
    prog = subprocess.Popen(sys.argv, preexec_fn=os.setsid)
except OSError, e:
    sys.exit(1)

time.sleep(WAIT_TIME)
idlist = subprocess.Popen("pgrep -g " + str(prog.pid),
                          shell=True,
                          stdout=subprocess.PIPE
                          ).stdout.read().splitlines()

ps1 = os.fork()
if ps1 > 0:
    ps2 = os.fork()

if ps1 == 0:  # Child 1
    os.setpgid(os.getpid(), os.getpid())
    killpid(idlist)
    sys.exit(0)
elif ps2 == 0:  # Child 2
    killname(os.path.basename(sys.argv[0]))
    sys.exit(0)
elif ps1 > 0 and ps2 > 0:  # Parent
    time.sleep(WAIT_TIME)
    os.killpg(os.getpgid(int(ps1)), signal.SIGTERM)
    os.kill(ps2, signal.SIGTERM)
    os.waitpid(ps1, 0)
    os.waitpid(ps2, 0)
    sys.exit(0)
else:
    exit(1)

ฉันลองใช้สคริปต์ตัวแรกของคุณ มันใช้งานไม่ได้หรือไม่ลดให้เร็วพอ startminimizedฉันบันทึกเป็น startminimized gnome-calendarแล้วผมก็วิ่ง ปฏิทินเปิดและทำงานต่อไปหรือไม่
Khurshid Alam

1
คุณสามารถลองเพิ่มตัวแปรWAIT_TIMEได้ ฉันใช้ความล่าช้า 40 วินาทีสำหรับคอมพิวเตอร์ที่อ่อนแอ นอกจากนี้คุณสามารถลองใช้สคริปต์ที่สองเนื่องจากใช้คำสั่งอื่นเพื่อย่อขนาดแอป
Sergey

1

หากโปรแกรมถูกปิดลงในถาดหนึ่งอาจต้องการปิดหน้าต่างโปรแกรมเมื่อเริ่มต้นแทนการย่อเล็กสุด ตัวอย่างหนึ่งของโปรแกรมดังกล่าวคือ Viber ในกรณีนี้เราสามารถใช้สคริปต์ต่อไปนี้start_closed.sh:

#!/bin/bash

# Check that there is only one input argument
if [[ $# -gt 1 ]]; then
echo "Usage: $0 <program-to-start>"
exit 1
fi

$1 &                               # Start program passed in first argument
pid=$!                             # Get PID of last started program
xdotool search --sync --pid $pid | # Wait for window with PID to appear...
xargs wmctrl -i -c                 # ...and close it

การใช้งาน: <path-to-script> <program-to-start>


1
คุณอาจต้องการทราบว่าxdotoolจะไม่ทำงานอย่างถูกต้องในการติดตั้งด้วย Wayland
Videonauth

0

ฉันเพิ่งท่องและเจอคำถามนี้ดังนั้นฉันแค่สงสัยว่าระบบปฏิบัติการของคุณคืออะไร สำหรับฉันฉันใช้UBUNTU BUDGIE 18.04 LTSดังนั้นในระบบปฏิบัติการนี้มันง่ายมาก

เพียงไปที่เมนู

จากเมนูไปที่การตั้งค่า Budgie Desktop

และ

จาก Desktop Setting ไปที่ Auto Start

มันจะให้ 2 ตัวเลือกจาก "+" เพิ่ม

1. เพิ่มแอปพลิเคชัน

2. เพิ่มคำสั่ง

โดยการเลือกเพิ่มแอปพลิเคชันทั้งหมดแอปพลิเคชันจะแสดงรายการเลือกแอปพลิเคชันที่คุณต้องการและแอปจะเริ่มเมื่อคุณเริ่มคอมพิวเตอร์และจะถูกย่อให้เล็กสุด


0

ฉันต้องการโปรแกรมที่ปิดลงในถาดไม่ย่อเล็กสุดและฉันได้ลองสคริปต์ทั้งหมดที่โพสต์ที่นี่โปรแกรมที่ใช้งานได้ใช้ได้กับบางโปรแกรมเท่านั้นและไม่ใช่สำหรับโปรแกรมอื่น ๆ ดังนั้นฉันจึงเขียนโค้ดที่ใช้งานได้ดีกว่ามาก (คุณแทบไม่เห็นหน้าต่างปรากฏขึ้นมีเพียงไอคอนถาดมันดูเป็นเนทิฟ) และใช้งานได้กับทุกโปรแกรมที่ฉันได้ลอง มันขึ้นอยู่กับยาโคบ ด้วยสคริปต์นี้คุณอาจจำเป็นต้องเพิ่มอาร์กิวเมนต์ขึ้นอยู่กับโปรแกรม (ดูด้านล่าง) แต่ทำงานได้ดีสำหรับฉันเสมอด้วยโปรแกรมมากมายมันควรทำงานกับ Steam ด้วย

การใช้งาน:

  1. sudo apt-get install wmctrl xdotool
  2. บันทึกสคริปต์ตามที่startup_closed.pyให้สิทธิ์ในการเรียกใช้แล้วดำเนินการpython3 ./startup_closed.py -c <command to open program>
  3. หากไอคอนถาดโปรแกรมไม่แสดงขึ้นมาหรือหน้าต่างไม่แสดงขึ้นมาคุณจะต้องเพิ่มอาร์กิวเมนต์ตัวใดตัวหนึ่งต่อไปนี้: -splashหรือ-hideจากการลองผิดลองถูก ตัวอย่างเช่น: python3 ./startup_closed.py -hide -c teamviewerหรือpython3 ./startup_closed.py -splash -c slack
  4. มีข้อโต้แย้งเพิ่มเติม แต่คุณอาจไม่ต้องการ นอกจากนี้ยังมีรายละเอียดที่สมบูรณ์ของเวลาและเหตุผลที่ต้องการข้อโต้แย้งในความช่วยเหลือ:./startup_closed.py --help

สคริปต์:

#!/usr/bin/env python3
import subprocess
import sys
import time
import argparse
import random

parser = argparse.ArgumentParser(description='This script executes a command you specify and closes or hides the window/s that opens from it, leaving only the tray icon. Useful to "open closed to tray" a program. If the program does not have a tray icon then it just gets closed. There is no magic solution to achieve this that works for all the programs, so you may need to tweek a couple of arguments to make it work for your program, a couple of trial and error may be required with the arguments -splash and -hide, you probably will not need the others.')

parser.add_argument("-c", type=str, help="The command to open your program. This parameter is required.", required=True)
parser.add_argument("-splash", help="Does not close the first screen detected. Closes the second window detected. Use in programs that opens an independent splash screen. Otherwise the splash screen gets closed and the program cannot start.", action='store_true', default=False)
parser.add_argument("-hide", help="Hides instead of closing, for you is the same but some programs needs this for the tray icon to appear.", action='store_true', default=False)
parser.add_argument("-skip", type=int, default=0, help='Skips the ammount of windows specified. For example if you set -skip 2 then the first 2 windows that appear from the program will not be affected, use it in programs that opens multiple screens and not all must be closed. The -splash argument just increments by 1 this argument.', required=False)
parser.add_argument("-repeat", type=int, default=1, help='The amount of times the window will be closed or hidden. Default = 1. Use it for programs that opens multiple windows to be closed or hidden.', required=False)
parser.add_argument("-delay", type=float, default=10, help="Delay in seconds to wait before running the application, useful at boot to not choke the computer. Default = 10", required=False)
parser.add_argument("-speed", type=float, default=0.02, help="Delay in seconds to wait between closing attempts, multiple frequent attempts are required because the application may be still loading Default = 0.02", required=False)

args = parser.parse_args()

if args.delay > 0:
    finalWaitTime = random.randint(args.delay, args.delay * 2);
    print(str(args.delay) + " seconds of delay configured, will wait for: " + str(finalWaitTime))
    time.sleep(finalWaitTime)
    print("waiting finished, running the application command...")

command_check = args.c.split("/")[-1]
subprocess.Popen(["/bin/bash", "-c", args.c])

hasIndependentSplashScreen = args.splash
onlyHide = args.hide
skip = args.skip
repeatAmmount = args.repeat
speed = args.speed

actionsPerformed = 0
lastWindowId = 0

if hasIndependentSplashScreen:
    skip += 1

while True:
    try:
        w_list = [l.split() for l in subprocess.check_output(["wmctrl", "-lp"]).decode("utf-8").splitlines()]
        proc = subprocess.check_output(["pgrep", "-f", command_check]).decode("utf-8").strip().split()
        match = sum([[l[0] for l in w_list if p in l] for p in proc], [])
        if len(match) > 0:
            windowId = match[0]
            if windowId != lastWindowId:
                if skip > 0:
                    skip -= 1
                    print("skipped window: " + windowId)
                    lastWindowId = windowId
                else:
                    print("new window detected: " + windowId)
                    if onlyHide:
                        subprocess.Popen(["xdotool", "windowunmap", windowId])
                        print("window was hidden: " + windowId)
                    else:
                        subprocess.Popen(["xdotool", "key", windowId, "alt+F4"])
                        print("window was closed: " + windowId)

                    actionsPerformed += 1
                    lastWindowId = windowId

            if actionsPerformed == repeatAmmount:
                break

    except (IndexError, subprocess.CalledProcessError):
        break

    time.sleep(speed)

print("finished")

0

ฉันมาพร้อมกับวิธีแก้ปัญหาที่ค่อนข้างหรูหราซึ่งอาศัย แต่เพียงผู้เดียวxdotoolและมีประโยชน์มากสำหรับแอปพลิเคชันที่ไม่มีการโต้แย้ง"เริ่มย่อเล็กสุด"เช่น Telegram

เพียงข้อเสียคือการแก้ปัญหาที่จะต้องมีการสร้างขึ้นมาด้วยตนเองสำหรับแอปแต่ละ แต่สมมติว่าไม่ใช่ปัญหา(เช่นถ้าคุณต้องการที่จะ autostart โปรแกรมบางโดยไม่ต้องปล่อยให้มันก่อให้เกิดมลพิษหน้าจอของคุณหลังจากที่เข้าสู่ระบบใน)นี้เป็นง่ายมากและตรงไปตรงมา .

ตัวอย่างจริง

## Starts Telegram and immediately closes it
xdotool search --sync --onlyvisible --name '^Telegram$' windowclose &
telegram-desktop &
## Starts WhatsApp and immediately closes it
xdotool search --sync --onlyvisible --name '(\([0-9]*\) ){0,1}(WhatsApp$|WhatsApp Web$)' windowclose &
whatsapp-nativefier &

การแก้ไขปัญหา

ในภาพรวมครั้งแรกคุณอาจคิดว่าเป็นการดีกว่าที่จะใช้กระบวนการ 'PID หรือคลาสเพื่อต่อต้าน ตัวอย่างคือหน้าต่าง 0x0 ที่รอการแจ้งเตือนไอคอน systray หรือหน้าต่าง "ซ่อน" อื่น ๆ

วิธีแก้ปัญหาคือการสร้างคำสั่ง xdotool ที่จะส่งคืนหน้าต่างที่ไม่ซ้ำกันเพียงหน้าต่างเดียวเสมอ ในทั้งสองตัวอย่างของฉันที่ได้กระทำโดยใช้--nameแต่คุณสามารถรวมตัวเลือกหลายที่มี--all (เช่นตรงกับชื่อคลาส + ชื่อชั้นที่กำหนด + ชื่อ regex) โดยปกติ--nameregex ที่ดีจะหลอกลวงได้

หลังจากงานหัตถกรรมของคุณsearchเงื่อนไขวางไข่เพียงตัวอย่างของ xdotool (ถอดออกจากเปลือก)กับพารามิเตอร์และเงื่อนไขของคุณตามด้วย--sync windowcloseเรียกใช้แอปของคุณในภายหลัง:

xdotool search --sync [... myapp-match-conditions] windowclose &
my-app

ตรวจสอบxdotool search --helpความเป็นไปได้ทั้งหมดของชุดค่าผสมที่คุณสามารถจัดเรียงเพื่อให้สามารถกำหนดเป้าหมายหน้าต่างแน่นอนที่คุณต้องการ บางครั้งมันจะยุ่งยากและคุณต้องรวมหลายเงื่อนไข แต่เมื่อคุณทำเสร็จแล้วมันจะไม่ค่อยเกิดความล้มเหลว (เว้นแต่การอัปเดตจะเปลี่ยนแอปพลิเคชันและทำให้การติดตั้งใช้งานไม่ได้)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.