繁体   English   中英

当程序直接运行时,更改 python 程序中的墙纸有效。 但在从服务运行时不起作用

[英]changing the wallpaper in python program works when the program is ran directly. but doesn't work when it's run from a service

我一直想制作一个程序,立即将我的壁纸设置为 1 张图片,等待 10 秒,然后将其设置为另一张。

从命令提示符或使用 python 解释器运行时,该程序工作正常。 但作为一项服务,它不起作用。

我已经使用 nssm(Non-Sucking Service Manager)将脚本变成服务。

这是代码的墙纸更改部分:

def change_wallpaper(filename):
    # Load the user32 library.
    user32 = ctypes.WinDLL('user32')

    # Set the wallpaper.
    result = user32.SystemParametersInfoW(
        win32con.SPI_SETDESKWALLPAPER, 0, filename, win32con.SPIF_UPDATEINIFILE
    )

    # Check the result.
    if not result:
        print("Failed to set wallpaper.")
    else:
        print("Successfully set wallpaper.")

我将 I/O 捕获到一个日志文件中,以确定它是否有效,但它显示“无法设置墙纸”。

所以..我有点卡住了。 感谢任何能提供帮助的人。 :)


我所期待的

我原以为它会更改墙纸,然后在 10 秒后将其更改为另一个。

究竟发生了什么

报告更换壁纸失败。

注意,这不是我的代码。 我以前用过一个叫 superpaper 的 python 壁纸管理器,而且......它是一个 python 壁纸管理器。 工程的第一条规则是不要重新发明轮子。 这是他们的项目: https://github.com/hhannine/superpaper

import ctypes
from typing import List
import pythoncom
import pywintypes
import win32gui
from win32com.shell import shell, shellcon
user32 = ctypes.windll.user32


def _make_filter(class_name: str, title: str):
    """https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-enumwindows"""

    def enum_windows(handle: int, h_list: list):
        if not (class_name or title):
            h_list.append(handle)
        if class_name and class_name not in win32gui.GetClassName(handle):
            return True  # continue enumeration
        if title and title not in win32gui.GetWindowText(handle):
            return True  # continue enumeration
        h_list.append(handle)

    return enum_windows


def find_window_handles(parent: int = None, window_class: str = None, title: str = None) -> List[int]:
    cb = _make_filter(window_class, title)
    try:
        handle_list = []
        if parent:
            win32gui.EnumChildWindows(parent, cb, handle_list)
        else:
            win32gui.EnumWindows(cb, handle_list)
        return handle_list
    except pywintypes.error:
        return []


def force_refresh_syspar():
    user32.UpdatePerUserSystemParameters(1)


def enable_activedesktop():
    """https://stackoverflow.com/a/16351170"""
    try:
        progman = find_window_handles(window_class='Progman')[0]
        cryptic_params = (0x52c, 0, 0, 0, 500, None)
        user32.SendMessageTimeoutW(progman, *cryptic_params)
    except IndexError as e:
        raise WindowsError('Cannot enable Active Desktop') from e


def set_wallpaper_win(image_path: str, use_activedesktop: bool = True):
    if use_activedesktop:
        enable_activedesktop()
    pythoncom.CoInitialize()
    iad = pythoncom.CoCreateInstance(shell.CLSID_ActiveDesktop,
                                     None,
                                     pythoncom.CLSCTX_INPROC_SERVER,
                                     shell.IID_IActiveDesktop)
    iad.SetWallpaper(str(image_path), 0)
    iad.ApplyChanges(shellcon.AD_APPLY_ALL)
    force_refresh_syspar()

你会通过

set_wallpaper_win('/path/to/image.png')

另一个可能的原因是壁纸是每个用户的,服务不一定以用户身份运行。 您希望将服务设置为以当前登录的用户身份运行。 来自 NSSM 的网站(截至 2022-12-28):

登录选项卡 登录选项卡可用于管理将运行该服务的用户帐户。 nssm 将自动确保您选择的帐户具有必要的登录即服务权限。

登录设置

等效命令:

nssm set UT2003 ObjectName LocalSystem nssm set UT2003 Type SERVICE_WIN32_OWN_PROCESS 有关在命令行上配置帐户和密码的详细信息,请参阅命令行使用文档。 如果需要配置空白密码,则必须使用命令行。

此外,它可能与这个问题有关: Change wallpaper with service

就个人而言,我会选择不将其设为 Windows 服务,而是选择托盘服务或后台 CLI 应用程序。 您可以在启动文件夹中创建一个快捷方式,它将调用 python 和 arguments 以启动您的 python 脚本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM