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

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

18
задан 19 August 2015 в 12:12

7 ответов

Запущение приложения минимизировано

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

  • запущение приложения
  • минимизируйте его окно

Поэтому команда или сценарий должны быть "умными"; вторая команда должна ожидать окна приложения для фактического появления.

Общее решение запустить минимизированное приложение

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

<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 не выполняет один pid, но не меньше затем (в моем тесте) восемь!
  • Steam работает на запуске по крайней мере с двумя окнами (один всплеск - как окно), но иногда дополнительное окно сообщения появляется.
  • Windows Пара имеет 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
    
29
ответ дан 23 November 2019 в 02:07

Хорошо дать сценарии user72216 и Sergey как общие решения проблемы, но иногда приложение, которое Вы хотите запустить минимизированный уже, имеет переключатель, который сделает то, что Вы хотите.

Вот несколько примеров с соответствующими командными строками программы запуска:

  • Telegram (начиная с версии 0.7.10) имеет -startintray опция: <path-to-Telegram>/Telegram -startintray
  • Пар имеет -silent опция: /usr/bin/steam %U -silent
  • Передача имеет --minimized опция: /usr/bin/transmission-gtk --minimized

В Единице эти приложения запускаются минимизированный как значки в верхней панели меню, а не как значки на средстве запуска, хотя нормальный значок запуска все еще появится, после того как Вы начинаете использовать приложение. Другие приложения могут вести себя по-другому.

3
ответ дан 23 November 2019 в 02:07

Я взял сценарии Jacob и изменил их немного для создания более универсального.

#!/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 - синхронизирующая опция используется вместо некоторое время цикла
  • , Сценарий позволяет передающие аргументы программе

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

Дополнение

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)
1
ответ дан 23 November 2019 в 02:07

Мне были нужны программы, закрытые для лотка, не минимизированного, и я попробовал все сценарии, отправленные здесь, те, которые работали, работал только на некоторые программы а не на других. Таким образом, я кодировал тот, который работает намного лучше (Вы почти не видите, что окно появляется, только значок панели задач, это выглядит собственным), и работает на все программы, которые я попробовал. Это основано на одном Jacob. С этим сценарием Вы, возможно, должны добавить аргумент в зависимости от программы (см. ниже), но всегда работал на меня с большим количеством программ, это должно также работать с паром.

Использование:

  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
ответ дан 23 November 2019 в 02:07

Я был просто перемещающимся и столкнулся с этим вопросом, таким образом, я просто задавался вопросом, какова Ваша операционная система? Что касается меня я использую ВОЛНИСТЫЙ ПОПУГАЙЧИК UBUNTU 18,04 LTS так в этой операционной системе, это очень просто.

Просто переходят к меню

Из Меню, переходят к Настольным Настройкам Волнистого попугайчика

, и

От Настольной Установки переходят к Автоматическому запуску

, Это даст Вам, 2 опции, от "+" добавляют

1. Добавьте Приложение

2. Добавьте, что Команда

Путем выбора Добавляет Приложение , все приложения будут перечислены выбор любое приложение, которое Вы хотите, и это запустится, когда Вы запустите свой компьютер, и это будет также минимизировано.

0
ответ дан 23 November 2019 в 02:07

Я шел с довольно изящным решением, которое полагается исключительно на xdotool, и это довольно полезно для приложений, которые не имеют , "запускаются минимизированный" аргумент, как Telegram.

единственный недостаток - то, что решение должно быть вручную обработано для каждого приложения, но принятие это не проблема (например: если Вы хотите автоматически запустить определенное приложение, не позволяя этому загрязнить Ваш экран после входа в систему) , это намного более просто и просто.

Фактические Примеры

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

Решение

На первый взгляд, Вы могли бы думать, что лучше использовать PID процесса или класс для соответствия против, однако это на самом деле контрпродуктивно, поскольку Вы часто будете получать несколько результатов для того же PID. Примерами является 0x0 окно, это на самом деле ожидает уведомления, systray значка или любого другого "скрытого" окна.

решение , обработка xdotool управляет, чтобы всегда возвращал только одно уникальное окно . В обоих моих примерах, который был сделан с помощью --name, однако можно объединить несколько селекторов с --all (например: соответствуйте данному имени класса + имя класса + имя regex) . Обычно польза --name regex добивается цели.

После обработки Вашего search условия, просто мечите икру, экземпляр xdotool (отсоединился от оболочки) с --sync параметр и Ваши условия, сопровождаемые windowclose. Запустите свое приложение впоследствии:

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

Выезд xdotool search --help для всех возможностей комбинаций можно расположить смочь быть нацеленными на точное окно, которое Вы хотите. Иногда это становится хитрым, и необходимо объединить несколько условий, но однажды законченный, это редко когда-либо перестанет работать (если обновление не изменит приложение, и повредите реализацию, конечно).

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 процесса или класс для соответствия против, однако это на самом деле контрпродуктивно, поскольку Вы часто будете получать несколько результатов для того же PID. Примерами является 0x0 окно, это на самом деле ожидает уведомления, systray значка или любого другого "скрытого" окна.

решение , обработка xdotool управляет, чтобы всегда возвращал только одно уникальное окно . В обоих моих примерах, который был сделан с помощью --name, однако можно объединить несколько селекторов с --all (например: соответствуйте данному имени класса + имя класса + имя regex) . Обычно польза --name regex добивается цели.

После обработки Вашего search условия, просто мечите икру, экземпляр xdotool (отсоединился от оболочки) с --sync параметр и Ваши условия, сопровождаемые windowclose. Запустите свое приложение впоследствии:

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

Выезд xdotool search --help для всех возможностей комбинаций можно расположить смочь быть нацеленными на точное окно, которое Вы хотите. Иногда это становится хитрым, и необходимо объединить несколько условий, но однажды законченный, это редко когда-либо перестанет работать (если обновление не изменит приложение, и повредите реализацию, конечно).

0
ответ дан 23 November 2019 в 02:07

Если программа закрывается для лотка, можно было бы на самом деле хотеть закрыть окно программы на запуске вместо того, чтобы минимизировать его. Одним примером такой программы является 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
ответ дан 23 November 2019 в 02:07

Другие вопросы по тегам:

Похожие вопросы: