web-dev-qa-db-fra.com

Comment puis-je exécuter un programme au démarrage, minimisé?

Je veux juste que Telegram soit exécuté et je l'ai ajouté aux applications de démarrage. Le fait est que j'ai besoin que cela soit minimisé. Des commandes?

17
Hossein Soltanloo

Lancer une application minimisée

Démarrer une application de manière minimisée prend deux commandes:

  • démarrer l'application
  • minimiser sa fenêtre

Par conséquent, la commande ou le script doit être "intelligent"; la deuxième commande doit attendre que la fenêtre de l'application apparaisse réellement.

Solution générale pour démarrer une application minimisée

Le script ci-dessous le fait et peut être utilisé comme une solution générale pour démarrer une application de manière minimisée. Il suffit de l'exécuter dans la syntaxe:

<script> <command_to_run_the_application> <window_name>

Le scénario

#!/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

Comment utiliser

Le script nécessite à la fois wmctrlet xdotoolname__:

Sudo apt-get install wmctrl xdotool

Ensuite:

  1. Copiez le script dans un fichier vide, enregistrez-le sous startup_minimizd.py
  2. Test: exécutez le script avec (par exemple) geditla commande:

    python3 /path/to/startup_minimizd.py gedit gedit
    
  3. Si tout fonctionne correctement, ajoutez la commande (pour votre application) à Startup Applications

Explication

  • Le script démarre l'application en exécutant la commande que vous avez donnée en premier argument
  • Ensuite, le script vérifie la liste des fenêtres (à l’aide de wmctrlname__) pour windows, nommées après votre deuxième argument.
  • Si la fenêtre apparaît, elle est immédiatement réduite à l'aide de xdotoolname__. Pour empêcher une boucle sans fin si la fenêtre peut ne pas apparaître pour une raison quelconque, le script applique un délai de 30 secondes pour l'affichage de la fenêtre.

Remarque

Inutile de mentionner que vous pouvez utiliser le script pour plusieurs applications à la fois, car vous l'exécutez avec des arguments en dehors du script.


MODIFIER

reconnaissant la fenêtre par son pid

Si le titre de la fenêtre est incertain ou variable, ou s'il existe un risque de conflit de nom dans le nom de la fenêtre, l'utilisation de pidest une méthode plus fiable.

Le script ci-dessous est basé sur l'utilisation du pid de l'application, comme dans le résultat de wmctrl -lp et ps -ef.

La configuration est à peu près la même, mais le titre de la fenêtre n’est pas nécessaire dans cette version, la commande pour l’exécuter est la suivante:

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

Comme le premier script, il a besoin des noms wmctrlet xdotoolname__

Le scénario

#!/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)

Note sur le second script

Bien qu'en général, la deuxième version devrait être plus fiable, dans les cas où l'application est démarrée par un script d'encapsuleur, le pid de la commande sera différent de l'application qui sera finalement appelée.

Dans de tels cas, je recommande d'utiliser le premier script.



EDIT2 une version spécifique du script pour Steam

Comme demandé dans un commentaire, ci-dessous une version spécialement conçue pour le démarrage de Steam minimisé.

Pourquoi une version spécifique pour Steam?

Il s'avère que Steamse comporte assez différemment d'une application "normale":

  • Il s'avère que Steamne lance pas un pid, mais pas moins que (dans mon test) huit!
  • Steams'exécute au démarrage avec au moins deux fenêtres (une fenêtre semblable à une barre), mais une fenêtre de message supplémentaire apparaît parfois.
  • Windows de Steam a pid 0, ce qui pose un problème dans le script.
  • Une fois la fenêtre principale créée, la fenêtre est levée une seconde après environ une seconde. Une minimisation simple ne suffit pas.

Ce comportement exceptionnel de Steamdemande une version spéciale du script, qui est ajoutée ci-dessous. Le script démarre Steamet pendant 12 secondes, il surveille toutes les nouvelles fenêtres du WM_CLASS correspondant et vérifie si elles sont réduites au minimum. Sinon, le script s'assure qu'ils le seront.

Comme le script d'origine, celui-ci nécessite wmctrlet xdotoolpour être installé.

Le scénario

#!/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)

Pour l'utiliser

  • Copiez-le simplement dans un fichier vide, enregistrez-le sous runsteam_minimized.py
  • Exécutez-le à l'aide de la commande:

    python3 /path/to/runsteam_minimized.py
    
28
Jacob Vlijm

Il est bon d’avoir les scripts donnés par user72216 et Sergey comme solutions générales au problème, mais parfois l’application que vous souhaitez réduire au minimum possède déjà un commutateur qui fera ce que vous voulez.

Voici quelques exemples avec les chaînes de commande du programme de démarrage correspondantes:

  • Telegram (depuis la version 0.7.10) a l'option -startintray: <path-to-Telegram>/Telegram -startintray
  • Steam a l'option -silent: /usr/bin/Steam %U -silent
  • La transmission a l'option --minimized: /usr/bin/transmission-gtk --minimized

Dans Unity, ces applications sont réduites au minimum sous forme d’icônes dans la barre de menus supérieure plutôt que sous forme d’icônes sur le lanceur, bien que l’icône de lancement normale apparaisse toujours une fois que vous commencez à utiliser l’application. D'autres applications peuvent se comporter différemment.

3
Francis Chin

Si le programme est fermé au bac, il est possible que vous souhaitiez fermer la fenêtre du programme au démarrage au lieu de la minimiser. Viber est un exemple de ce type de programme. Dans ce cas, on pourrait utiliser le script suivant 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

Utilisation: <path-to-script> <program-to-start>

1
Mykola Novik

J'ai pris les scripts de Jacob et les ai modifiés un peu pour en faire un plus universel.

#!/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)

Les principales différences sont les suivantes:

  • Le programme définit l'ID de groupe (GID) pour le processus. Ainsi, tous les processus enfants et leurs fenêtres peuvent être facilement trouvés
  • xdotool - L'option sync est utilisée à la place d'une boucle while
  • Le script permet de passer des arguments au programme

WAIT_TIME doit être défini assez grand pour permettre au programme de diviser ses processus enfants. Sur mon ordinateur, cela suffit pour les gros programmes comme Steam. Augmentez-le si nécessaire.

Ajout

xdotoolname L'option windowunmappeut fonctionner de manière funky avec certaines applications et certains programmes de plateau (le plateau de linux mint, par exemple). Voici donc une version alternative du script pour ces exceptions.

#!/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
Sergey

J'avais besoin des programmes fermés jusqu'au plateau, non minimisés, et j'ai essayé tous les scripts postés ici, ceux qui ont fonctionné, ne fonctionnaient que pour certains programmes et pas pour d'autres. J'ai donc codé celui qui fonctionne beaucoup mieux (vous ne voyez presque pas la fenêtre apparaître, mais uniquement l'icône de la barre d'état système, il a l'air natif) et fonctionne pour tous les programmes que j'ai essayés. C'est basé sur celui de Jacob. Avec ce script, vous devrez peut-être ajouter un argument en fonction du programme (voir ci-dessous), mais cela a toujours fonctionné pour moi avec de nombreux programmes, il devrait également fonctionner avec Steam.

tilisation:

  1. Sudo apt-get install wmctrl xdotool
  2. Enregistrez le script sous startup_closed.py, donnez-lui les autorisations d'exécution, puis exécutez python3 ./startup_closed.py -c <command to open program>.
  3. Si l'icône de la barre des programmes ne s'affiche pas ou si la fenêtre ne s'affiche pas, vous devez ajouter l'un des arguments suivants: -splash ou -hide, par essais et erreurs. Par exemple: python3 ./startup_closed.py -hide -c teamviewer ou python3 ./startup_closed.py -splash -c slack
  4. Il y a plus d'arguments mais vous n'en avez probablement pas besoin. Il existe également des informations complètes sur le moment et la raison pour lesquels les arguments sont nécessaires dans l'aide: ./startup_closed.py --help

Script:

#!/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
fermmm

Je surfais et je suis tombé sur cette question. Je me demandais donc quel est votre système d'exploitation? Quant à moi, j'utilise BUNTU BUDGIE 18.04 LTS alors dans ce système d'exploitation, c'est très simple.

Il suffit d'aller au menu

Dans le menu, allez dans Paramètres de Budgie Desktop

et

De la configuration du bureau, allez à Démarrage automatique

Il vous donnera 2 options, de "+" ajouter

1. Ajouter une application

2. Ajouter une commande

En sélectionnant Ajouter une application toutes les applications seront répertoriées, sélectionnez celle que vous souhaitez et elle démarrera au démarrage de votre ordinateur. Elle sera également réduite au minimum.

0
Muntaha Liaqat