85 lines
2.6 KiB
Python
85 lines
2.6 KiB
Python
# -*- coding: utf-8 -*-
|
||
"""在 Profile 目录内创建浏览器快捷方式(Windows .lnk)。"""
|
||
from __future__ import annotations
|
||
|
||
import logging
|
||
import os
|
||
import re
|
||
import subprocess
|
||
import sys
|
||
from typing import Optional
|
||
|
||
from service.browser_service import resolve_chromium_executable
|
||
|
||
_WIN_LNK_FORBIDDEN = re.compile(r'[<>:"/\\|?*\x00-\x1f]')
|
||
|
||
|
||
def _lnk_safe_filename(name: str, fallback: str = "browser") -> str:
|
||
t = _WIN_LNK_FORBIDDEN.sub("_", (name or "").strip())
|
||
t = t.rstrip(" .")
|
||
return t or fallback
|
||
|
||
|
||
def _ps_single_quote(value: str) -> str:
|
||
return "'" + value.replace("'", "''") + "'"
|
||
|
||
|
||
def create_profile_browser_shortcut(
|
||
profile_dir: str,
|
||
account_label: str,
|
||
log: Optional[logging.Logger] = None,
|
||
) -> Optional[str]:
|
||
"""
|
||
在 profile_dir 内创建 {account_label}.lnk,目标为系统 Chrome/Edge + --user-data-dir。
|
||
|
||
非 Windows 或未安装 Chrome/Edge 时静默跳过,返回 None。
|
||
成功返回 .lnk 绝对路径。
|
||
"""
|
||
if log is None:
|
||
log = logging.getLogger(__name__)
|
||
|
||
if sys.platform != "win32":
|
||
log.debug("profile_shortcut_skip platform=%s", sys.platform)
|
||
return None
|
||
|
||
browser_exe = resolve_chromium_executable()
|
||
if not browser_exe:
|
||
log.warning("profile_shortcut_skip reason=no_chromium")
|
||
return None
|
||
|
||
profile_abs = os.path.abspath(profile_dir)
|
||
os.makedirs(profile_abs, exist_ok=True)
|
||
|
||
lnk_name = f"{_lnk_safe_filename(account_label)}.lnk"
|
||
lnk_path = os.path.join(profile_abs, lnk_name)
|
||
arguments = f'--user-data-dir="{profile_abs}"'
|
||
working_dir = os.path.dirname(browser_exe)
|
||
|
||
ps = (
|
||
"$WshShell = New-Object -ComObject WScript.Shell; "
|
||
f"$s = $WshShell.CreateShortcut({_ps_single_quote(lnk_path)}); "
|
||
f"$s.TargetPath = {_ps_single_quote(browser_exe)}; "
|
||
f"$s.Arguments = {_ps_single_quote(arguments)}; "
|
||
f"$s.IconLocation = {_ps_single_quote(browser_exe + ',0')}; "
|
||
f"$s.WorkingDirectory = {_ps_single_quote(working_dir)}; "
|
||
"$s.Save()"
|
||
)
|
||
|
||
try:
|
||
subprocess.run(
|
||
["powershell", "-NoProfile", "-NonInteractive", "-Command", ps],
|
||
check=True,
|
||
capture_output=True,
|
||
text=True,
|
||
)
|
||
except (OSError, subprocess.CalledProcessError) as exc:
|
||
log.warning("profile_shortcut_failed profile_dir=%s error=%s", profile_abs, exc)
|
||
return None
|
||
|
||
if not os.path.isfile(lnk_path):
|
||
log.warning("profile_shortcut_missing_after_create path=%s", lnk_path)
|
||
return None
|
||
|
||
log.info("profile_shortcut_created path=%s browser=%s", lnk_path, browser_exe)
|
||
return lnk_path
|