Как запустить программу при запуске, свести к минимуму?

16

Я просто хочу, чтобы Telegram запускался, и я добавил его в приложения для запуска. Дело в том, что мне нужно, чтобы он был сведен к минимуму. Любые команды?

    
задан Hossein Soltanloo 19.08.2015 в 07:28
источник

4 ответа

27

Запуск приложения с минимизацией

Запуск приложения в свернутом виде принимает две команды:

  • запуск приложения
  • свернуть окно

Следовательно, команда или сценарий должны быть «умными»; вторая команда должна дождаться появления окна приложения.

Общее решение для запуска приложения минимизировано

Сценарий ниже делает это и может использоваться как общее решение для запуска приложения с минимальным способом. Просто запустите его в синтаксисе:

<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 ) для окон, названных в честь вашего второго аргумента.
  • Если окно появляется, оно немедленно сворачивается с помощью 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, но не менее (в моем тесте) eight!
  • Steam запускается при запуске с не менее двумя окнами (одно всплывающее окно), но иногда появляется дополнительное окно сообщения.
  • У Windows Steam есть pid 0 , что является проблемой в скрипте как есть.
  • После создания главного окна окно создается второй раз через секунду или около того, поэтому минимизация single не будет.

Это исключительное поведение 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
    
ответ дан Jacob Vlijm 19.08.2015 в 13:56
источник
3

Хорошо, что сценарии, предоставленные user72216 и 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 эти приложения начинают свертываться как значки в верхней строке меню, а не как значки на панели запуска, хотя обычный значок запуска будет отображаться после запуска приложения. Другие приложения могут вести себя по-разному.

    
ответ дан Francis Chin 24.09.2016 в 17:57
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>

    
ответ дан Mykola Novik 03.12.2017 в 10:18
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)

Основные отличия заключаются в следующем:

  • Программа устанавливает идентификатор группы (GID) для процесса. Таким образом, все дочерние процессы и их окна можно легко найти
  • xdotool --sync используется вместо цикла while
  • Сценарий позволяет передавать аргументы программе

WAIT_TIME должен быть установлен достаточно большим, чтобы программа могла развить свои дочерние процессы. На моем компьютере достаточно больших программ, таких как пар. При необходимости увеличьте его.

Добавление

% опции co_de% xdotool может работать с некоторыми приложениями и программами лотков (например, лоток 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)
    
ответ дан Sergey 16.08.2016 в 19:21