web-dev-qa-db-ja.com

起動時に最小化されたプログラムを実行するにはどうすればよいですか?

Telegramを実行したいだけで、スタートアップアプリに追加しました。ポイントは、最小化する必要があるということです。コマンドはありますか?

17

最小化されたアプリケーションの起動

最小限の方法でアプリケーションを起動するには、次の2つのコマンドが必要です。

  • アプリケーションを開始する
  • ウィンドウを最小化する

したがって、コマンドまたはスクリプトは「スマート」である必要があります。 2番目のコマンドは、アプリケーションウィンドウが実際に表示されるまで待機する必要があります。

最小化されたアプリケーションを起動する一般的なソリューション

次のスクリプトはそれを行い、最小限の方法でアプリケーションを起動する一般的なソリューションとして使用できます。構文で実行するだけです:

<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

使い方

スクリプトには、wmctrlxdotoolの両方が必要です。

Sudo apt-get install wmctrl xdotool

次に:

  1. スクリプトを空のファイルにコピーし、startup_minimizd.pyとして保存します
  2. テストたとえば)geditコマンドでスクリプトを実行します:

    python3 /path/to/startup_minimizd.py gedit gedit
    
  3. すべてが正常に機能する場合は、(アプリケーションの)コマンドをStartup Applicationsに追加します

説明

  • スクリプトはアプリケーションを起動し、最初の引数として指定したコマンドを実行します
  • 次に、スクリプトは、2番目の引数にちなんで命名されたウィンドウのウィンドウリストを(wmctrlを使用して)チェックします。
  • ウィンドウが表示される場合、xdotoolの助けを借りてすぐに最小化されます。何らかの理由でウィンドウが表示されない場合の無限ループを防ぐため、スクリプトはウィンドウが表示されるまで30秒の制限時間を設けます。

注意

スクリプトの外部の引数を使用してスクリプトを実行するため、スクリプトを一度に複数のアプリケーションに使用できることを述べる必要はありません。


編集

pidでウィンドウを認識する

ウィンドウのタイトルが不明または可変である場合、またはウィンドウの名前に名前の衝突のリスクがある場合は、pidを使用する方が信頼性の高い方法です。

以下のスクリプトは、wmctrl -lpps -efの両方の出力のように、アプリケーションのpidの使用に基づいています。

セットアップはほとんど同じですが、このバージョンではウィンドウのタイトルは必要ないため、実行するコマンドは次のとおりです。

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

最初のスクリプトと同様に、wmctrlxdotoolの両方が必要です

スクリプト

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

2番目のスクリプトに関する注意

一般に2番目のバージョンはより信頼性が高いはずですが、アプリケーションがラッパースクリプトによって起動される場合、コマンドのpidは最終的に呼び出されるアプリケーションとは異なります。

このような場合、最初のスクリプトを使用することをお勧めします。



EDIT2 Steam用のスクリプトの特定のバージョン

コメントで要求されているように、Steamの起動用に特別に作成されたバージョンの下に最小化されています。

Steamに特定のバージョンが必要な理由

Steamは、「通常の」アプリケーションとはまったく異なる動作をすることがわかります。

  • Steamは実行されません---(one pidですが、(私のテストでは)eight!
  • Steamは、起動時に少なくとも 2つのウィンドウ(1つのスプラッシュのようなウィンドウ)で実行されますが、追加のメッセージウィンドウが表示される場合があります。
  • Steamのウィンドウにはpid 0がありますが、これは以前のスクリプトの問題です。
  • メインウィンドウが作成された後、ウィンドウは1秒かそこら後に2度目に浮き上がります。したがって、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
    
28
Jacob Vlijm

問題に対する一般的な解決策として、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では、これらのアプリケーションは、ランチャーのアイコンとしてではなく、トップメニューバーのアイコンとして最小化されて起動しますが、アプリケーションの使用を開始すると通常の起動アイコンが表示されます。他のアプリケーションの動作は異なる場合があります。

3
Francis Chin

プログラムがトレイに閉じられている場合、起動時にプログラムウィンドウを最小化するのではなく閉じたい場合があります。そのようなプログラムの一例は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
Mykola Novik

ジェイコブのスクリプトを取り、それらを少し変更して、より普遍的なスクリプトにしました。

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

主な違いは次のとおりです。

  • プログラムは、プロセスのグループID(GID)を設定します。したがって、すべての子プロセスとそのウィンドウを簡単に見つけることができます
  • whileループの代わりにxdotool --syncオプションが使用されます
  • スクリプトは、プログラムに引数を渡すことができます

WAIT_TIMEは、プログラムが子プロセスを分岐できるように十分に大きく設定する必要があります。私のコンピューターでは、Steamのような大きなプログラムには十分です。必要に応じて増やします。

追加

xdotoolのオプションwindowunmapは、一部のアプリケーションやトレイプログラム(Linuxミントのトレイなど)でファンキーに動作する可能性があるため、これらの例外に対するスクリプトの代替バージョンを次に示します。

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

プログラムを最小化せずにトレイに閉じておく必要があり、ここに投稿されたすべてのスクリプトを試しました。だから、私ははるかに良く機能し(ウィンドウがほとんど表示されず、トレイアイコンだけがネイティブに見えます)、試したすべてのプログラムで機能するものをコーディングしました。それはヤコブのものに基づいています。このスクリプトを使用すると、プログラムに応じて引数を追加する必要がある場合があります(以下を参照)が、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
fermmm

私はただサーフィンしていてこの質問に出くわしたので、私はあなたのオペレーティングシステムが何であるか疑問に思っていましたか?私に関してはBUNTU BUDGIE 18.04 LTSを使用しているので、このオペレーティングシステムでは非常に簡単です。

メニューに移動するだけです

メニューからBudgie Desktop Settingsに移動します

そして

デスクトップ設定から自動起動に移動します

「+」から2つのオプションが追加されます

1。アプリケーションの追加

2。コマンドの追加

アプリケーションの追加を選択することにより、すべてのアプリケーションが一覧表示され、必要なアプリケーションを選択すると、コンピューターの起動時に起動し、最小化されます。

0
Muntaha Liaqat