3

I use the solution provided in this post to change the Windows desktop wallpaper from Python

In particular here is the code sample

import ctypes
import os
image_file = "myimage.jpg"
print("Setting the wallpaper")
SPI_SETDESKWALLPAPER = 20 
ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0,  os.path.abspath(image_file) , 0)

The problem is that the change is non persistent, in the sense that the desktop wallpaper gets reset whenever I restart my PC. How can I persistently change the Windows desktop wallpaper from Python?

I use python 3.5

4
  • 1
    It's not your immediate problem, but please use user32 = ctypes.WinDLL('user32', use_last_error=True) instead of ctypes.windll.user32. Check for success and if not raise ctypes.WinError(ctypes.get_last_error()), so that the caller can handle the exception instead of blindly pretending that everything is fine. Commented Jun 7, 2017 at 7:02
  • As to the immediate problem, you should be able to solve that in a few seconds by reading the docs for the fWinIni parameter of SystemParametersInfo. Commented Jun 7, 2017 at 7:06
  • @eryksun you are right, but where to I find the value of SPIF_UPDATEINIFILE? The documentation (msdn.microsoft.com/en-us/library/ms724947) does not provide it, while it provides the value of SPI_SETDESKWALLPAPER . In winuser.h it is defined as equal to 1. Is it correct to assume that this value will never change in future versions although it is not specified in the documentation? Commented Jun 7, 2017 at 7:21
  • Yes, always use the constants, function declarations, and struct definitions from the Windows headers if you have them. The online docs are a starting place, but they're often wrong in some details. Commented Jun 7, 2017 at 7:25

1 Answer 1

1

You need to call it like this

print("Setting the wallpaper")
SPI_SETDESKWALLPAPER = 20 
SPIF_UPDATEINIFILE = 1
ctypes.windll.user32.SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, os.path.abspath(image_file) , SPIF_UPDATEINIFILE)

Also have a look at the related documentation

Sign up to request clarification or add additional context in comments.

4 Comments

This particular action succeeds even if the file doesn't exist or is a directory, so you may want to check os.path.isfile(image_file) beforehand.
It would still be better in general to use user32 = ctypes.WinDLL('user32', use_last_error=True). Adding a global windll to ctypes was a bad idea for several reasons, the first being that shared global state is almost always a problem in waiting.
@eryksun regarding your first comment, that is really strange, because the documentation says that "When the SPI_SETDESKWALLPAPER flag is used, SystemParametersInfo returns TRUE unless there is an error (like when the specified file doesn't exist).". I did not test it, but if that is the case, if would mean that the ctypes library does not handle return values correctly
ctypes is fine here. As I said, MSDN is often wrong (e.g. bad values, wrong types and fields in structs, and inaccurate descriptions of behavior). The docs aren't written by the developers, and they're often stale or reflect what should have been implemented and no one ever actually got around to it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.