[英]changing the wallpaper in python program works when the program is ran directly. but doesn't work when it's run from a service
I've been wanting to make a program that immediatly sets my wallpaper to 1 picture, waits 10 seconds, then sets it to the other.我一直想制作一个程序,立即将我的壁纸设置为 1 张图片,等待 10 秒,然后将其设置为另一张。
The program works just fine when running it from command prompt, or using the python interpreter.从命令提示符或使用 python 解释器运行时,该程序工作正常。 But as a service, it doesn't work.
但作为一项服务,它不起作用。
I have used nssm (Non-Sucking Service Manager) to turn the script into a service.我已经使用 nssm(Non-Sucking Service Manager)将脚本变成服务。
Here's the wallpaper changing part of the code:这是代码的墙纸更改部分:
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 captured the I/O to a log file to find out if it had worked or not and it said "Failed to set wallpaper".我将 I/O 捕获到一个日志文件中,以确定它是否有效,但它显示“无法设置墙纸”。
So.. I'm kind of stuck.所以..我有点卡住了。 Thanks to anyone who can help.
感谢任何能提供帮助的人。 :)
:)
What I was expecting我所期待的
I was expecting it to change the wallpaper, then after 10 seconds change it to another.我原以为它会更改墙纸,然后在 10 秒后将其更改为另一个。
What actually happened究竟发生了什么
It reported that changing the wallpaper failed.报告更换壁纸失败。
Heads up, this is not my code.注意,这不是我的代码。 I've used a python wallpaper manager called superpaper before, and...it's a python wallpaper manager.
我以前用过一个叫 superpaper 的 python 壁纸管理器,而且......它是一个 python 壁纸管理器。 The first rule of engineering is to not reinvent the wheel.
工程的第一条规则是不要重新发明轮子。 Here is their project: https://github.com/hhannine/superpaper
这是他们的项目: 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()
You would call it via你会通过
set_wallpaper_win('/path/to/image.png')
Another possible reason is that wallpapers are per user, and services don't necessarily run as the user.另一个可能的原因是壁纸是每个用户的,服务不一定以用户身份运行。 You want to set the service to run as the currently logged on user.
您希望将服务设置为以当前登录的用户身份运行。 From NSSM's website (as of 2022-12-28):
来自 NSSM 的网站(截至 2022-12-28):
Log on tab The Log on tab can be used to manage the user account which will run the service.
登录选项卡 登录选项卡可用于管理将运行该服务的用户帐户。 nssm will automatically ensure that the account you choose has the necessary log on as a service permissions.
nssm 将自动确保您选择的帐户具有必要的登录即服务权限。
Equivalent commands:
等效命令:
nssm set UT2003 ObjectName LocalSystem nssm set UT2003 Type SERVICE_WIN32_OWN_PROCESS Refer to the command line usage documentation for details on configuring an account and password on the command line.
nssm set UT2003 ObjectName LocalSystem nssm set UT2003 Type SERVICE_WIN32_OWN_PROCESS 有关在命令行上配置帐户和密码的详细信息,请参阅命令行使用文档。 If you need to configure a blank password you must use the command line.
如果需要配置空白密码,则必须使用命令行。
Additionally, it may be related to this question: Change wallpaper with service此外,它可能与这个问题有关: Change wallpaper with service
Personally, I would just choose not to make it a Windows Service, and instead opt for a tray service or background CLI application.就个人而言,我会选择不将其设为 Windows 服务,而是选择托盘服务或后台 CLI 应用程序。 You can just make a shortcut in a startup folder that will call python with the arguments to start your python script.
您可以在启动文件夹中创建一个快捷方式,它将调用 python 和 arguments 以启动您的 python 脚本。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.