mirror of
https://github.com/AstrBotDevs/AstrBot.git
synced 2026-09-24 16:39:52 +08:00
feat(service): update Windows service command to use PowerShell and enhance task XML configuration
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import base64
|
||||
import copy
|
||||
import getpass
|
||||
import json
|
||||
@@ -334,8 +335,8 @@ def _windows_service_log_paths(service_name: str) -> tuple[Path, Path]:
|
||||
return log_dir / f"{service_name}.out.log", log_dir / f"{service_name}.err.log"
|
||||
|
||||
|
||||
def _windows_cmd_executable() -> str:
|
||||
return os.environ.get("COMSPEC") or "cmd.exe"
|
||||
def _windows_powershell_executable() -> str:
|
||||
return "powershell.exe"
|
||||
|
||||
|
||||
def _quote_windows_cmd_arg(value: Path | str) -> str:
|
||||
@@ -343,14 +344,43 @@ def _quote_windows_cmd_arg(value: Path | str) -> str:
|
||||
return f'"{escaped}"'
|
||||
|
||||
|
||||
def _build_windows_cmd_arguments(service_name: str, executable: Path) -> str:
|
||||
def _quote_powershell_literal(value: Path | str) -> str:
|
||||
escaped = str(value).replace("'", "''")
|
||||
return f"'{escaped}'"
|
||||
|
||||
|
||||
def _build_windows_cmd_line(service_name: str, executable: Path) -> str:
|
||||
out_log, err_log = _windows_service_log_paths(service_name)
|
||||
return (
|
||||
"/d /c "
|
||||
f'"{_quote_windows_cmd_arg(executable)} run '
|
||||
f"{_quote_windows_cmd_arg(executable)} run "
|
||||
f">> {_quote_windows_cmd_arg(out_log)} "
|
||||
f"2>> {_quote_windows_cmd_arg(err_log)}"
|
||||
'"'
|
||||
)
|
||||
|
||||
|
||||
def _build_windows_powershell_arguments(
|
||||
service_name: str,
|
||||
executable: Path,
|
||||
workdir: Path,
|
||||
) -> str:
|
||||
script = (
|
||||
"$ErrorActionPreference = 'Stop'\n"
|
||||
"$env:PYTHONUNBUFFERED = '1'\n"
|
||||
"$cmdExe = if ($env:COMSPEC) { $env:COMSPEC } else { 'cmd.exe' }\n"
|
||||
f"$astrbotCommand = {_quote_powershell_literal(_build_windows_cmd_line(service_name, executable))}\n"
|
||||
"$process = Start-Process "
|
||||
"-FilePath $cmdExe "
|
||||
"-ArgumentList @('/d', '/c', $astrbotCommand) "
|
||||
f"-WorkingDirectory {_quote_powershell_literal(workdir)} "
|
||||
"-WindowStyle Hidden "
|
||||
"-PassThru "
|
||||
"-Wait\n"
|
||||
"exit $process.ExitCode\n"
|
||||
)
|
||||
encoded_script = base64.b64encode(script.encode("utf-16le")).decode("ascii")
|
||||
return (
|
||||
"-NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass "
|
||||
f"-WindowStyle Hidden -EncodedCommand {encoded_script}"
|
||||
)
|
||||
|
||||
|
||||
@@ -386,7 +416,7 @@ def _build_windows_task_xml(
|
||||
_task_element(settings, "RunOnlyIfNetworkAvailable", "false")
|
||||
_task_element(settings, "AllowStartOnDemand", "true")
|
||||
_task_element(settings, "Enabled", "true")
|
||||
_task_element(settings, "Hidden", "false")
|
||||
_task_element(settings, "Hidden", "true")
|
||||
_task_element(settings, "RunOnlyIfIdle", "false")
|
||||
_task_element(settings, "WakeToRun", "false")
|
||||
_task_element(settings, "ExecutionTimeLimit", "PT0S")
|
||||
@@ -397,11 +427,11 @@ def _build_windows_task_xml(
|
||||
|
||||
actions = _task_element(task, "Actions", attrib={"Context": "Author"})
|
||||
exec_action = _task_element(actions, "Exec")
|
||||
_task_element(exec_action, "Command", _windows_cmd_executable())
|
||||
_task_element(exec_action, "Command", _windows_powershell_executable())
|
||||
_task_element(
|
||||
exec_action,
|
||||
"Arguments",
|
||||
_build_windows_cmd_arguments(service_name, executable),
|
||||
_build_windows_powershell_arguments(service_name, executable, workdir),
|
||||
)
|
||||
_task_element(exec_action, "WorkingDirectory", str(workdir))
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import base64
|
||||
import json
|
||||
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
|
||||
from pathlib import Path
|
||||
@@ -22,6 +23,12 @@ from astrbot.cli.commands.cmd_service import (
|
||||
)
|
||||
|
||||
|
||||
def _decode_windows_encoded_command(task_xml: str) -> str:
|
||||
marker = "-EncodedCommand "
|
||||
encoded_command = task_xml.split(marker, 1)[1].split("<", 1)[0]
|
||||
return base64.b64decode(encoded_command).decode("utf-16le")
|
||||
|
||||
|
||||
class _HealthyHandler(BaseHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
self.send_response(200)
|
||||
@@ -134,13 +141,20 @@ def test_windows_task_xml_uses_astrbot_executable_and_working_directory():
|
||||
Path("C:\\Users\\astrbot\\.local\\bin\\astrbot.exe"),
|
||||
Path("C:\\Users\\astrbot\\AstrBot"),
|
||||
).decode("utf-16")
|
||||
powershell_script = _decode_windows_encoded_command(task_xml)
|
||||
|
||||
assert "<Command>cmd.exe</Command>" in task_xml
|
||||
assert "C:\\Users\\astrbot\\.local\\bin\\astrbot.exe" in task_xml
|
||||
assert "run" in task_xml
|
||||
assert "astrbot.out.log" in task_xml
|
||||
assert "astrbot.err.log" in task_xml
|
||||
assert "<WorkingDirectory>C:\\Users\\astrbot\\AstrBot</WorkingDirectory>" in task_xml
|
||||
assert "<Command>powershell.exe</Command>" in task_xml
|
||||
assert "<Hidden>true</Hidden>" in task_xml
|
||||
assert "-WindowStyle Hidden" in task_xml
|
||||
assert "Start-Process" in powershell_script
|
||||
assert "-WindowStyle Hidden" in powershell_script
|
||||
assert "C:\\Users\\astrbot\\.local\\bin\\astrbot.exe" in powershell_script
|
||||
assert "run" in powershell_script
|
||||
assert "astrbot.out.log" in powershell_script
|
||||
assert "astrbot.err.log" in powershell_script
|
||||
assert (
|
||||
"<WorkingDirectory>C:\\Users\\astrbot\\AstrBot</WorkingDirectory>" in task_xml
|
||||
)
|
||||
|
||||
|
||||
def test_load_dashboard_port_reads_cmd_config(tmp_path):
|
||||
|
||||
Reference in New Issue
Block a user