Lock Screen Image - Windows 10

Get help with using AutoHotkey and its commands and hotkeys
Posts: 100
Joined: 21 May 2015, 18:21

Lock Screen Image - Windows 10

14 Nov 2017, 16:26

I would like to programmatically update the Windows 10 lock screen image.

There appears to be a new UserProfilePersonalizationSettings API for this starting in Windows 10, but I'm not sure how to access it from AHK. I imagine there is probably some way to access this object using DllCall or similar. Anyone have any ideas?

UserProfilePersonalizationSettings Class
LockScreen Class

Looks like one could potentially do this using lexikos' .NET framework interop. If someone else has a simpler solution in mind, let me know. Otherwise I'll post back here if I manage to figure it out.
Last edited by egocarib on 14 Nov 2017, 20:52, edited 1 time in total.
Posts: 100
Joined: 21 May 2015, 18:21

Re: Lock Screen Image - Windows 10

14 Nov 2017, 20:42

Here is the code I came up with so far
.NET Framework Interop, updated for current AHK v2
My code
I am having trouble because the code requires using Windows.System.UserProfile;, however, this does not seem to be able to be loaded like other namespaces. If I try to load it as Windows.System.UserProfile.dll (as in my code pasted above), I encounter the error: Error CS0006 on line 0: Metadata file 'Windows.System.UserProfile.dll' could not be found. After doing a bit more research, it seems the problem might be that Windows.System refers to the Windows Runtime API - which sounds like it can't be loaded quite like other .dll files. I am not sure how to access it through the AHK .NET framework.

Anyone know if that's possible? Or if there are any alternatives I can pursue?
Posts: 468
Joined: 04 Mar 2016, 04:33
GitHub: qwerty12

Re: Lock Screen Image - Windows 10

20 Nov 2017, 01:18

egocarib wrote:Looks like one could potentially do this using lexikos' .NET framework interop. If someone else has a simpler solution in mind, let me know. Otherwise I'll post back here if I manage to figure it out.[/i]
JsRT would probably work: https://github.com/Lexikos/ActiveScript.ahk

As I'd rather give myself an enema with a bicycle pump than write JavaScript, here's something to do it with raw COM:

Code: Select all

#NoEnv  ; Recommended for performance and compatibility with future AutoHotkey releases.

; DllCall("ole32.dll\OleUninitialize")
; DllCall("combase.dll\RoInitialize", "UInt", RO_INIT_MULTITHREADED := 1)

; 1. Create StorageFile obj for pic
VarSetCapacity(IIDStorageFileStatics, 16), VA_GUID(IIDStorageFileStatics := "{5984C710-DAF2-43C8-8BB4-A4D3EACFD03F}")
StorageFile := new rtstr("Windows.Storage.StorageFile")
if (!DllCall("combase.dll\RoGetActivationFactory", "Ptr", StorageFile.str, "Ptr", &IIDStorageFileStatics, "Ptr*", instStorageFile)) {
	if (!DllCall(NumGet(NumGet(instStorageFile+0)+6*A_PtrSize), "Ptr", instStorageFile, "Ptr", (_ := new rtstr("C:\Users\Me\Pictures\Wallpapers\affinity_street_romain_trystram_01.jpg")).str, "Ptr*", sfileasyncwrapper)) {
		; 2. Said SF obj gets created async. Keep checking (in a sync manner) to see if actual SF obj is created
		sfileasyncinfo := ComObjQuery(sfileasyncwrapper, IID_IAsyncInfo := "{00000036-0000-0000-C000-000000000046}")
		while (!DllCall(NumGet(NumGet(sfileasyncinfo+0)+7*A_PtrSize), "Ptr", sfileasyncinfo, "UInt*", status) && !status)
			Sleep 100
		if (status != 1)
			ExitApp 1
		; 3. It has! Finally take pointer to sf obj
		DllCall(NumGet(NumGet(sfileasyncwrapper+0)+8*A_PtrSize), "Ptr", sfileasyncwrapper, "Ptr*", sfile)
		; 4. Create LockScreen obj
		VarSetCapacity(IIDLockScreenStatics, 16), VA_GUID(IIDLockScreenStatics := "{3EE9D3AD-B607-40AE-B426-7631D9821269}")
		lockScreen := new rtstr("Windows.System.UserProfile.LockScreen")
		if (!DllCall("combase.dll\RoGetActivationFactory", "Ptr", lockScreen.str, "Ptr", &IIDLockScreenStatics, "Ptr*", instLockScreen)) {
			; Tell ls obj to set ls pic from sf obj
			DllCall(NumGet(NumGet(instLockScreen+0)+8*A_PtrSize), "Ptr", instLockScreen, "Ptr", sfile, "Ptr*", Operation)
			Sleep 1000 ; Note: it's better to do the sfileasyncinfo stuff again instead of a simple sleep like this to help ensure the lockScreen pic is set. mind, if your script is persistent, it mightn't matter

class rtstr {
	static lpWindowsCreateString := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "combase.dll", "Ptr"), "AStr", "WindowsCreateString", "Ptr")
	static lpWindowsDeleteString := DllCall("GetProcAddress", "Ptr", DllCall("GetModuleHandle", "Str", "combase.dll", "Ptr"), "AStr", "WindowsDeleteString", "Ptr")

	__New(sourceString, length := 0) {
		this.str := !DllCall(rtstr.lpWindowsCreateString, "WStr", sourceString, "UInt", length ? length : StrLen(sourceString), "Ptr*", string) ? string : 0

	__Delete() {
		DllCall(rtstr.lpWindowsDeleteString, "Ptr", this.str)

; From Lexikos' VA.ahk: Convert string to binary GUID structure.
VA_GUID(ByRef guid_out, guid_in="%guid_out%") {
    if (guid_in == "%guid_out%")
        guid_in :=   guid_out
    if  guid_in is integer
        return guid_in
    VarSetCapacity(guid_out, 16, 0)
	DllCall("ole32\CLSIDFromString", "wstr", guid_in, "ptr", &guid_out)
	return &guid_out

Return to “Ask For Help”

Who is online

Users browsing this forum: AHKStudent, anahkuser, Bing [Bot], boiler, Google [Bot], Jrdixon_, Nicknick22, swagfag, Xtra and 282 guests