Brauche Hilfe bei Meinem Manger wo ich mit Tinker erstellen möchte

Fragen zu Tkinter.
Antworten
Raconin
User
Beiträge: 2
Registriert: Samstag 22. Februar 2025, 13:05

Guten Tag

Ich bin grade Dabei mir einen Manger zu Erstellen mit Tinker womit ich mir meine Ark Survival Ascended Schneller erstellen und verwalten kann.
Aber ich bekomme es irgendwie nicht hin das wenn ich auf neuen Server Hinzufügen Drücke das es dann auch Den Ark Survival Ascended Server Automatisch installiert und Steam CMD.
Kann mir da jemand vielleicht weiterhelfen das ist mein Code wie er im moment aussieht.

Code: Alles auswählen

import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import subprocess
import os
import threading
import json
import requests
import zipfile
import time
import schedule
import psutil
from rcon.source import Client

CONFIG_FILE = "servers.json"
STEAMCMD_DIR = r"E:\\HigFiveManger\\steamcmd"
STEAMCMD_PATH = os.path.join(STEAMCMD_DIR, "steamcmd.exe")
STEAMCMD_URL = "https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip"
ARK_APP_ID = "376030"

def load_servers():
    if os.path.exists(CONFIG_FILE):
        with open(CONFIG_FILE, "r") as file:
            return json.load(file)
    return {"servers": {}}

def save_servers():
    with open(CONFIG_FILE, "w") as file:
        json.dump(servers, file, indent=4)

def install_steamcmd():
    if not os.path.exists(STEAMCMD_DIR):
        os.makedirs(STEAMCMD_DIR)
    
    if os.path.exists(STEAMCMD_PATH):
        print("SteamCMD bereits installiert.")
        return
    
    print("Lade SteamCMD herunter...")
    response = requests.get(STEAMCMD_URL, stream=True)
    zip_path = os.path.join(STEAMCMD_DIR, "steamcmd.zip")
    with open(zip_path, "wb") as file:
        for chunk in response.iter_content(chunk_size=1024):
            file.write(chunk)
    
    print("Entpacke SteamCMD...")
    with zipfile.ZipFile(zip_path, "r") as zip_ref:
        zip_ref.extractall(STEAMCMD_DIR)
    os.remove(zip_path)
    print("SteamCMD Installation abgeschlossen.")

def install_ark_server(server_path, log_widget):
    install_steamcmd()
    
    command = [STEAMCMD_PATH, "+login", "anonymous", "+force_install_dir", server_path, "+app_update", ARK_APP_ID, "validate", "+quit"]
    process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, shell=True)
    
    for line in process.stdout:
        log_widget.insert(tk.END, line + "\n")
        log_widget.see(tk.END)
    process.wait()
    log_widget.insert(tk.END, "Installation abgeschlossen!\n")
    log_widget.see(tk.END)

servers = load_servers()

class ArkServerManager:
    def __init__(self, root):
        self.root = root
        self.root.title("ARK: Survival Ascended Server Manager")
        self.root.geometry("800x600")
        
        self.tabs = ttk.Notebook(root)
        self.tabs.pack(expand=1, fill="both")
        
        self.servers = servers.get("servers", {})
        self.add_server_tab = ttk.Frame(self.tabs)
        self.tabs.add(self.add_server_tab, text="+ Neuer Server")
        self.setup_add_server_tab()
        
        for server_name, server_data in self.servers.items():
            self.create_server_tab(server_name, server_data)
        
        # SteamCMD sofort beim Start prüfen und installieren
        threading.Thread(target=install_steamcmd, daemon=True).start()

    def setup_add_server_tab(self):
        label = tk.Label(self.add_server_tab, text="Neuen Server hinzufügen")
        label.pack()
        self.new_server_name = tk.Entry(self.add_server_tab, width=30)
        self.new_server_name.pack(pady=5)
        self.new_server_path = tk.Entry(self.add_server_tab, width=50)
        self.new_server_path.pack(pady=5)
        browse_btn = tk.Button(self.add_server_tab, text="Verzeichnis wählen", command=self.browse_server_path)
        browse_btn.pack(pady=5)
        add_btn = tk.Button(self.add_server_tab, text="Hinzufügen", command=self.add_server)
        add_btn.pack(pady=5)

    def browse_server_path(self):
        path = filedialog.askdirectory()
        if path:
            self.new_server_path.delete(0, tk.END)
            self.new_server_path.insert(0, path)

    def add_server(self):
        name = self.new_server_name.get()
        path = self.new_server_path.get()
        if name and path:
            self.servers[name] = {"path": path}
            servers["servers"] = self.servers
            save_servers()
            self.create_server_tab(name, {"path": path})
            self.new_server_name.delete(0, tk.END)
            self.new_server_path.delete(0, tk.END)

    def create_server_tab(self, name, data):
        tab = ttk.Frame(self.tabs)
        self.tabs.add(tab, text=name)
        server_path = data["path"]
        
        log_text = tk.Text(tab, height=15, width=80)
        log_text.pack(pady=5)
        
        install_btn = tk.Button(tab, text="📥 Server Installieren", command=lambda: self.install_server(server_path, log_text))
        install_btn.pack(pady=5)
        
        start_btn = tk.Button(tab, text="▶ Server Starten", command=lambda: self.start_server(server_path))
        start_btn.pack(pady=5)
        
        stop_btn = tk.Button(tab, text="⏹ Server Stoppen", command=self.stop_server)
        stop_btn.pack(pady=5)
        
        # Automatisch die Installation starten
        self.install_server(server_path, log_text)

    def install_server(self, server_path, log_widget):
        threading.Thread(target=install_ark_server, args=(server_path, log_widget), daemon=True).start()

    def start_server(self, server_path):
        command = f'cd "{server_path}" && start ShooterGameServer.exe TheIsland?listen'
        subprocess.Popen(command, shell=True)

    def stop_server(self):
        os.system("taskkill /f /im ShooterGameServer.exe")

if __name__ == "__main__":
    root = tk.Tk()
    app = ArkServerManager(root)
    root.mainloop()
Wäre gut wenn mir da vielleicht jemand weiter helfen kann
Benutzeravatar
__blackjack__
User
Beiträge: 13919
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Raconin: Das ist eine zu ungenaue Problembeschreibung. Was genau funktioniert denn nicht? Gibt es eine Fehlermeldung? Falls ja, welche?

Die Importe sollten mal aufgeräumt werden, da wird einiges gar nicht verwendet was importiert wird. `time`, `messagebox`, `psutil`, `schedule`, `Client` aus `rcon.source`.

Statt `os.path` & Co verwendet man in neuem Code `pathlib`.

Das Hauptprogramm sollte in einer Funktion stehen und `servers` sollte nicht global sein und schon gar nicht versteckt zwischen Funktions- und Klassendefinitionen zum laden einer Datei beim Import des Moduls führen.

Vor dem Öffnen einer Datei prüft man nicht auf die Existenz weil diese Prüfung ja bereits im Öffnen der Datei enthalten ist. Zudem kann sich diese Situation zwischen Prüfen und Öffnen ja auch ändern, also muss man sich so oder so um die Ausnahme kümmern.

Beim öffnen von Textdateien sollte man explizit die Kodierung angeben.

`ArkServerManager` braucht das `root`-Attribut nicht. Auch `add_server_tab` muss man nicht an dieses Objekt binden.

Man muss nicht jedes Zwischenergebnis an einen Namen binden.

Das `create_server_tab()` als zweites Argument ein Wörterbuch erwartet statt einfach den Pfadwert aus dem Wörterbuch, macht den Code unnötig komplizierter, weil beim hinzufügen beispielsweise extra ein Wörterbuch erstellt werden muss, das man eigentlich gar nicht bräuchte.

`install_steamcmd()` läuft nebenläufig, und kann auch mehrfach laufen. Das ist schon mal kaputt. Wenn man sicher sein will, dass das installiert ist, und sich auch nicht durch Mehrfachaufrufe die temporäre Datei kaputt machen kann, muss das vorher einmal, nicht nebenläufig ablaufen.

Ob die EXE installiert ist, wäre wohl das *erste* was man in der Funktion prüft.

`create_server_tab()` erstellt einen Button über den der Server installiert werden und und am Ende wird der Server installiert. Eins von beidem ist ja dann falsch.

`install_server()`, `start_server()` und `stop_server()` sind keine Methoden, sondern Funktionen.

`install_ark_server()` startet eine Shell in der ein externes Programm gestartet wird, ohne die Shell tatsächlich zu benötigen. Es werden dort auch Standard- und Standardfehlerausgabe umgeleitet, aber nur eine Datei davon ausgelesen, was zum hängen des externen Programms führen kann.

Auch `start_server()` sollte keine unnötige Shell starten. Das Arbeitsverzeichnis kann man `Popen` als Argument übergeben. Und wenn man `Popen` verwendet, mit dem Objekt dann aber überhaupt gar nichts macht, dann ist da was komisch, und man erzeugt auch potentielle Zombie-Prozesse wenn man sich nicht um das saubere abräumen kümmert.

`os.system()` geht gar nicht, dafür gibt es sich extra das `subprocess`-Modul.

Zwischenstand, ungetestet und mit ein paar kommentierten Bugs die man beseitigen müsste:

Code: Alles auswählen

import json
import subprocess
import threading
import tkinter as tk
import zipfile
from pathlib import Path
from tkinter import filedialog, ttk

import requests

CONFIG_FILENAME = "servers.json"
STEAMCMD_DIR_PATH = Path(R"E:\\HigFiveManger\\steamcmd")
STEAMCMD_PATH = STEAMCMD_DIR_PATH / "steamcmd.exe"
STEAMCMD_URL = "https://steamcdn-a.akamaihd.net/client/installer/steamcmd.zip"
ARK_APP_ID = "376030"


def load_servers():
    try:
        with open(CONFIG_FILENAME, "rb") as file:
            return json.load(file)
    except FileNotFoundError:
        return {"servers": {}}


def save_servers(servers):
    with open(CONFIG_FILENAME, "w", encoding="utf-8") as file:
        json.dump(servers, file, indent=4)


def install_steamcmd():
    if STEAMCMD_PATH.exists():
        print("SteamCMD bereits installiert.")
        return

    STEAMCMD_DIR_PATH.mkdir(parents=True, exist_ok=True)

    print("Lade SteamCMD herunter...")
    response = requests.get(STEAMCMD_URL, stream=True, timeout=None)
    response.raise_for_status()

    zip_file_path = STEAMCMD_DIR_PATH / "steamcmd.zip"
    with open(zip_file_path, "wb") as file:
        file.writelines(response.iter_content(chunk_size=1024))

    print("Entpacke SteamCMD...")
    with zipfile.ZipFile(zip_file_path, "r") as zip_file:
        zip_file.extractall(STEAMCMD_DIR_PATH)
    zip_file_path.unlink()
    print("SteamCMD Installation abgeschlossen.")


def install_ark_server(server_path, log_widget):
    with subprocess.Popen(
        [
            str(STEAMCMD_PATH),
            "+login",
            "anonymous",
            "+force_install_dir",
            server_path,
            "+app_update",
            ARK_APP_ID,
            "validate",
            "+quit",
        ],
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT,
        text=True,
    ) as process:
        for line in process.stdout:
            log_widget.insert(tk.END, line + "\n")
            log_widget.see(tk.END)

    log_widget.insert(tk.END, "Installation abgeschlossen!\n")
    log_widget.see(tk.END)


def install_server(server_path, log_widget):
    #
    # BUG Hier wird ein Thread gestartet aus dem heraus dann `log_widget`
    #   verändert wird.
    #
    threading.Thread(
        target=install_ark_server,
        args=(server_path, log_widget),
        daemon=True,
    ).start()


def start_server(server_path):
    subprocess.run(
        ["start", "ShooterGameServer.exe", "TheIsland?listen"],
        cwd=server_path,
        check=True,
    )


def stop_server():
    subprocess.run(
        ["taskkill", "/f", "/im", "ShooterGameServer.exe"], check=True
    )


class ArkServerManager:
    def __init__(self, root, servers):
        root.title("ARK: Survival Ascended Server Manager")
        root.geometry("800x600")

        self.tabs = ttk.Notebook(root)
        self.tabs.pack(expand=True, fill=tk.BOTH)

        self.servers = servers
        add_server_tab = ttk.Frame(self.tabs)
        self.tabs.add(add_server_tab, text="+ Neuer Server")
        self.setup_add_server_tab(add_server_tab)

        for server_name, server_data in self.servers["servers"].items():
            self.create_server_tab(server_name, server_data["path"])

    def setup_add_server_tab(self, add_server_tab):
        tk.Label(add_server_tab, text="Neuen Server hinzufügen").pack()
        self.new_server_name_entry = tk.Entry(add_server_tab, width=30)
        self.new_server_name_entry.pack(pady=5)
        self.new_server_path_entry = tk.Entry(add_server_tab, width=50)
        self.new_server_path_entry.pack(pady=5)
        tk.Button(
            add_server_tab,
            text="Verzeichnis wählen",
            command=self.browse_server_path,
        ).pack(pady=5)
        tk.Button(
            add_server_tab, text="Hinzufügen", command=self.add_server
        ).pack(pady=5)

    def browse_server_path(self):
        path = filedialog.askdirectory()
        if path:
            self.new_server_path_entry.delete(0, tk.END)
            self.new_server_path_entry.insert(0, path)

    def add_server(self):
        #
        # BUG Hier kann man Server hinzufügen die es unter dem gleichen Namen
        #   schon gibt, wo man dann einen zusätzlichen Reiter bekommt, aber der
        #   Name nur einmal in den Daten existiert.
        #
        name = self.new_server_name_entry.get()
        path = self.new_server_path_entry.get()
        if name and path:
            self.servers["servers"][name] = {"path": path}
            save_servers(self.servers)
            self.create_server_tab(name, path)
            self.new_server_name_entry.delete(0, tk.END)
            self.new_server_path_entry.delete(0, tk.END)

    def create_server_tab(self, name, path):
        tab = ttk.Frame(self.tabs)
        self.tabs.add(tab, text=name)

        log_text = tk.Text(tab, height=15, width=80)
        log_text.pack(pady=5)
        #
        # BUG Dieser Button kann mehrfach gedrückt werden, insbesondere auch
        #   während eine Installation bereits läuft.
        #
        tk.Button(
            tab,
            text="📥 Server Installieren",
            command=lambda: install_server(path, log_text),
        ).pack(pady=5)

        tk.Button(
            tab, text="▶ Server Starten", command=lambda: start_server(path)
        ).pack(pady=5)
        #
        # BUG Die Aktion hier bezieht sich gar nicht auf einen speziellen
        #   Server.
        #
        tk.Button(tab, text="⏹ Server Stoppen", command=stop_server).pack(
            pady=5
        )


def main():
    install_steamcmd()
    root = tk.Tk()
    _app = ArkServerManager(root, load_servers())
    root.mainloop()


if __name__ == "__main__":
    main()
“I am Dyslexic of Borg, Your Ass will be Laminated” — unknown
Raconin
User
Beiträge: 2
Registriert: Samstag 22. Februar 2025, 13:05

Okay Danke für die Antworte Dann werde ich Sobald ich mal mehr Zeit habe eine Genauere Problem Beschreibung machen.
Antworten