Discussion:
Setting screensaver from command-line
(too old to reply)
Java Jive
2023-10-15 17:00:38 UTC
Permalink
I have created the BATch file appended below, which is intended to
provide a quick and painless way to change the screensaver and power
modes from their normal settings, Blank & Stay Awake, to a disabled
state, None and Presentation, and back again. This is easy enough to do
via the relevant dialog boxes, but is irritatingly fiddly because some
of the settings are under Personalisation, Screensaver and others under
Power, hence the desire for a quicker and simpler method.

The power setting change between Stay Awake and Presentation appears to
be working correctly, but the screensaver change is failing. If I run,
say ...
Screensave /0
... but then launch the control panel for the screensaver, the choice of
screensaver is correctly None, but the option "On resume, display logon
screen" is still checked and this means that the screen will still go to
the logon screen when the timer expires. Conversely if I clear the
option and do ...
Screensave /1
... and then launch the screensaver dialog again, the option remains
unchecked, which means that if the timer expires, or I hibernate the
machine, I'm not prompted for a password, which of course is insecure.

All online sources that I've read suggest that the following registry
settings should be enough to set the screensaver ...

With Blank screensaver:

[HKEY_CURRENT_USER\Control Panel\Desktop]
"ScreenSaveActive"="1"
"ScreenSaverIsSecure"="1"
"SCRNSAVE.EXE"="C:\\Windows\\system32\\scrnsave.scr"

With no screensaver:

[HKEY_CURRENT_USER\Control Panel\Desktop]
"ScreenSaveActive"="0"
"ScreenSaverIsSecure"="0"

ie: "SCRNSAVE.EXE" setting deleted

... and those are exactly what my BATch file sets. Further, a before
and after comparison of the entire registry after changing just the
screensaver lock setting manually suggests that the ScreenSaverIsSecure
setting is the only thing of any seeming relevance which is changed by
altering this setting:

[HKU\<ID>\Control Panel\Desktop]
"ScreenSaverIsSecure"="1"

; As expected, value changes to "0"

[HKU\<ID>\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32]
[HKU\<ID>\Software\Classes\Local
Settings\Software\Microsoft\Windows\Shell\Bags\584\ComDlgLegacy]

; Changes from saving the *.reg files not thought to be relevant

[HKU\<ID>\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist]

; Contents of key appear to be encrypted so hard to say whether
relevant, but name of key suggests not

[HKLM\SYSTEM\CurrentControlSet\Control\Nsi\{eb004a03-9b1a-11d4-9123-0050047759bc}\24]
"ffffffffffffffffffffffffffffff02"=hex:01,00,00,00,41,c0,00,00,59,00,3f,03,ff,\
ff,ff,ff,ff,ff,ff,ff,ff,ff,ff,ff

; Seems to be some sort of counter, '59' increased to '5a'

Now I'm wondering if it is necessary somehow to have the BATch file
alert the system, presumably the Explorer instance that is running the
Desktop, that the user registry hive has changed and it needs to reload
it. I could kill that Explorer instance, actually it would have to be
all Explorer instances, and relaunch Explorer, but doing that is way too
complicated for a "quicker and simpler" method, and actually pointless
because it would be easier just to continue altering the settings manually.

Anyone any ideas?

@ECHO OFF
Rem ScreenSave.bat
Rem ==============
Rem
Rem Program to turn on & off the screen saver and power screen blanking
options

Rem Non-empty string here or /1 leading parameter turns the screen saver
on and /0 off respectively
SET Switch="1"
Rem Non-empty string here or /D leading parameter gives debugging messages
SET Debug=""

:NextPar
IF /i "%1" EQU "/0" (
SET Switch="0"
SHIFT
GOTO NextPar
)
IF /i "%1" EQU "/1" (
SET Switch="1"
SHIFT
GOTO NextPar
)
IF /i "%1" EQU "/D" (
SET Debug="Y"
SHIFT
GOTO NextPar
)

IF %Switch%=="0" GOTO Off

:On
Rem Set screensaver to 'Blank'
ECHO Setting ScreenSaver to 'Blank'
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v SCRNSAVE.EXE /t
REG_SZ /d C:\Windows\system32\scrnsave.scr /f > NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaverIsSecure
/t REG_SZ /d 1 /f > NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaveActive /t
REG_SZ /d 1 /f > NUL 2>&1
Rem Set power scheme to 'Stay Awake'
CALL :FindPowerGUID "Stay Awake" PName GUID
ECHO Setting Power Scheme to '%PName%'
powercfg /setactive %GUID%
GOTO Quit

:Off
Rem Set screensaver to 'None'
ECHO Setting ScreenSaver to 'None'
reg delete "HKEY_CURRENT_USER\Control Panel\Desktop" /v SCRNSAVE.EXE /f
NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaverIsSecure
/t REG_SZ /d 0 /f > NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaveActive /t
REG_SZ /d 0 /f > NUL 2>&1
Rem Set power scheme to 'Presentation'
CALL :FindPowerGUID "Presentation" PName GUID
ECHO Setting Power Scheme to '%PName%'
powercfg /setactive %GUID%
GOTO Quit

:FindPowerGUID
SETLOCAL EnableDelayedExpansion
for /f "usebackq tokens=1-4*" %%A in (`powercfg /list ^| find /i %1`) do (
IF %Debug% NEQ "" Echo %%D %%E
SET _Name=%%E
SET _GUID=%%D
IF %Debug% NEQ "" Echo _Name="!_Name!"
SET _Name="!_Name:(=!"
SET _Name=!_Name:"=!
IF %Debug% NEQ "" Echo _Name="!_Name!"
SET _Name="!_Name:)=!"
SET _Name=!_Name:"=!
IF %Debug% NEQ "" Echo _Name="!_Name!"
SET _Name="!_Name: *=!"
SET _Name=!_Name:"=!
IF %Debug% NEQ "" Echo _Name="!_Name!"
)
ENDLOCAL & (
IF %Debug% NEQ "" (
Echo SET %~2="%_Name%"
Echo SET %~3="%_GUID%" & Echo.
)
SET "%~2=%_Name%"
SET "%~3=%_GUID%"
)
SET _Name=
SET _GUID=
EXIT /B

:Quit
SET Switch=
SET Debug=
SET PName=
SET GUID=

ECHO.
--
Fake news kills!

I may be contacted via the contact address given on my website:
www.macfh.co.uk
JJ
2023-10-16 08:33:55 UTC
Permalink
Post by Java Jive
I have created the BATch file appended below, which is intended to
provide a quick and painless way to change the screensaver and power
modes from their normal settings, Blank & Stay Awake, to a disabled
state, None and Presentation, and back again. This is easy enough to do
via the relevant dialog boxes, but is irritatingly fiddly because some
of the settings are under Personalisation, Screensaver and others under
Power, hence the desire for a quicker and simpler method.
The power setting change between Stay Awake and Presentation appears to
be working correctly, but the screensaver change is failing. If I run,
say ...
Screensave /0
.... but then launch the control panel for the screensaver, the choice of
screensaver is correctly None, but the option "On resume, display logon
screen" is still checked and this means that the screen will still go to
the logon screen when the timer expires. Conversely if I clear the
option and do ...
Screensave /1
.... and then launch the screensaver dialog again, the option remains
unchecked, which means that if the timer expires, or I hibernate the
machine, I'm not prompted for a password, which of course is insecure.
All online sources that I've read suggest that the following registry
settings should be enough to set the screensaver ...
[HKEY_CURRENT_USER\Control Panel\Desktop]
Registry data changes in `HKEY_CURRENT_USER\Control Panel` can be notified
by broadcasting WM_SETTINGCHANGE window message, but batch file alone
doesn't have that capability. A separate tool is neeed. e.g. AutoHotkey,
AutoIt, PowerShell, etc.
Post by Java Jive
[HKU\<ID>\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32]
Notification of changes of registry data in this key is not needed, as they
are always re-read when the dialog is needed.
Post by Java Jive
[HKU\<ID>\Software\Classes\Local
Settings\Software\Microsoft\Windows\Shell\Bags\584\ComDlgLegacy]
Explorer doesn't re-read registry data under
`HKU\<ID>\Software\Classes\Local
Settings\Software\Microsoft\Windows\Shell\Bags` each time a folder view is
needed. Even if there was registry changes window message notification. Only
system restart, user re-login, or EXPLORER.EXE process restart will re-read
them.

Same thing applies to registry data in
`HKU\<ID>\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist`
key. PS: it's used to cache things. See: Nirsoft UserAssistView tool.
Post by Java Jive
[HKLM\SYSTEM\CurrentControlSet\Control\Nsi\{eb004a03-9b1a-11d4-9123-0050047759bc}\24]
NSI service registry data changes is not notifiable. The service will need
to be restarted for changes to take effect. However, the service is needed
by various other network related services. i.e. at least these:

Browser, Dhcp, Dnscache, HomeGroupProvider, iphlpsvc, LanmanWorkstation,
Netlogon, Netman, netprofm, NlaSvc, SessionEnv, SharedAccess,
WinHttpAutoProxySvc, WwanSvc

Some of above services can't be restarted and the system will need to be
restarted in order for the registry changes to take effect.

...

So, since at least one registry data changes need a system restart. It's
best to simply give a warning to the user that the registry changes will not
have any effect until the system is restarted.
Java Jive
2023-10-16 11:17:48 UTC
Permalink
Post by JJ
Post by Java Jive
All online sources that I've read suggest that the following registry
settings should be enough to set the screensaver ...
[HKEY_CURRENT_USER\Control Panel\Desktop]
"ScreenSaveActive"="1"
"ScreenSaverIsSecure"="1"
"SCRNSAVE.EXE"="C:\\Windows\\system32\\scrnsave.scr"
[HKEY_CURRENT_USER\Control Panel\Desktop]
"ScreenSaveActive"="0"
"ScreenSaverIsSecure"="0"
ie: "SCRNSAVE.EXE" setting deleted
... and those are exactly what my BATch file sets. Further, a before
and after comparison of the entire registry after changing just the
screensaver lock setting manually suggests that the ScreenSaverIsSecure
setting is the only thing of any seeming relevance which is changed by
[HKU\<ID>\Control Panel\Desktop]
"ScreenSaverIsSecure"="1"
; As expected, value changes to "0">
Registry data changes in `HKEY_CURRENT_USER\Control Panel` can be notified
by broadcasting WM_SETTINGCHANGE window message, but batch file alone
doesn't have that capability. A separate tool is neeed. e.g. AutoHotkey,
AutoIt, PowerShell, etc.
Thanks, I'll investigate that further.
Post by JJ
Post by Java Jive
[HKU\<ID>\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32]
Notification of changes of registry data in this key is not needed, as they
are always re-read when the dialog is needed.
Post by Java Jive
[HKU\<ID>\Software\Classes\Local
Settings\Software\Microsoft\Windows\Shell\Bags\584\ComDlgLegacy]
Explorer doesn't re-read registry data under
`HKU\<ID>\Software\Classes\Local
Settings\Software\Microsoft\Windows\Shell\Bags` each time a folder view is
needed. Even if there was registry changes window message notification. Only
system restart, user re-login, or EXPLORER.EXE process restart will re-read
them.
Same thing applies to registry data in
`HKU\<ID>\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist`
key. PS: it's used to cache things. See: Nirsoft UserAssistView tool.
Post by Java Jive
[HKLM\SYSTEM\CurrentControlSet\Control\Nsi\{eb004a03-9b1a-11d4-9123-0050047759bc}\24]
NSI service registry data changes is not notifiable. The service will need
to be restarted for changes to take effect. However, the service is needed
Browser, Dhcp, Dnscache, HomeGroupProvider, iphlpsvc, LanmanWorkstation,
Netlogon, Netman, netprofm, NlaSvc, SessionEnv, SharedAccess,
WinHttpAutoProxySvc, WwanSvc
Some of above services can't be restarted and the system will need to be
restarted in order for the registry changes to take effect.
...
So, since at least one registry data changes need a system restart. It's
best to simply give a warning to the user that the registry changes will not
have any effect until the system is restarted.
No, I included all the changes between Before.reg and After.reg for
completeness' sake in case someone spotted something of relevance to the
screensaver setting that I wasn't aware of, but most likely the first
under [HKCU/Control Panel/Desktop] is the only one that matters, so,
rather along the lines of what I was beginning to suspect, according to
your helpful information above, I have to explore how to broadcast a
WM_SETTINGCHANGE window message after making the registry changes.

Thanks for the helpful explanation.
--
Fake news kills!

I may be contacted via the contact address given on my website:
www.macfh.co.uk
Java Jive
2023-10-16 22:46:10 UTC
Permalink
Post by Java Jive
rather along the lines of what I was beginning to suspect, according to
your helpful information above, I have to explore how to broadcast a
WM_SETTINGCHANGE window message after making the registry changes.
Thanks for the helpful explanation.
After a search online, I adapted the following PowerShell code snippet
and saved it as WMSettingsChange.ps1, and within the BATch file after
the label :Quit added the line ...

powershell -ExecutionPolicy ByPass -File <path>\WMSettingsChange.ps1

... which runs without any discernible error, but the lockscreen is
still enabled after launching the screensaver properties.

I reckon this is a bug.

WMSettingsChange.ps1:
=====================

Add-Type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg,
UIntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out UIntPtr
lpdwResult);
"@

function Send-SettingChange {
$HWND_BROADCAST = [IntPtr] 0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [UIntPtr]::Zero

[void] ([Win32.Nativemethods]::SendMessageTimeout($HWND_BROADCAST,
$WM_SETTINGCHANGE, [UIntPtr]::Zero, "HKEY_CURRENT_USER\Control
Panel\Desktop", 2, 5000, [ref] $result))
}

For the registry key name I tried all of (as strings in quotes, an error
was generated when I tried the last without)...

HKEY_CURRENT_USER\Control Panel\Desktop
HKEY_CURRENT_USER
Control Panel
Desktop
NULL

... as per this documentation by Microsoft ...

https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-settingchange

... but none made any difference, the setting remained stubbornly enabled.
--
Fake news kills!

I may be contacted via the contact address given on my website:
www.macfh.co.uk
JJ
2023-10-17 17:31:38 UTC
Permalink
Post by Java Jive
Post by Java Jive
rather along the lines of what I was beginning to suspect, according to
your helpful information above, I have to explore how to broadcast a
WM_SETTINGCHANGE window message after making the registry changes.
Thanks for the helpful explanation.
After a search online, I adapted the following PowerShell code snippet
and saved it as WMSettingsChange.ps1, and within the BATch file after
the label :Quit added the line ...
powershell -ExecutionPolicy ByPass -File <path>\WMSettingsChange.ps1
.... which runs without any discernible error, but the lockscreen is
still enabled after launching the screensaver properties.
I reckon this is a bug.
=====================
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg,
UIntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out UIntPtr
lpdwResult);
function Send-SettingChange {
$HWND_BROADCAST = [IntPtr] 0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [UIntPtr]::Zero
[void] ([Win32.Nativemethods]::SendMessageTimeout($HWND_BROADCAST,
$WM_SETTINGCHANGE, [UIntPtr]::Zero, "HKEY_CURRENT_USER\Control
Panel\Desktop", 2, 5000, [ref] $result))
}
For the registry key name I tried all of (as strings in quotes, an error
was generated when I tried the last without)...
HKEY_CURRENT_USER\Control Panel\Desktop
HKEY_CURRENT_USER
Control Panel
Desktop
NULL
.... as per this documentation by Microsoft ...
https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-settingchange
.... but none made any difference, the setting remained stubbornly enabled.
For screen saver related settings which are covered by the
`SystemParametersInfo` Windows API function, specify the correct action
value to WParam. Multiple settings will require separate message broadcasts
for each SystemParametersInfo action.
Java Jive
2023-10-17 19:33:36 UTC
Permalink
Post by JJ
Post by Java Jive
=====================
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg,
UIntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out UIntPtr
lpdwResult);
function Send-SettingChange {
$HWND_BROADCAST = [IntPtr] 0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [UIntPtr]::Zero
[void] ([Win32.Nativemethods]::SendMessageTimeout($HWND_BROADCAST,
$WM_SETTINGCHANGE, [UIntPtr]::Zero, "HKEY_CURRENT_USER\Control
Panel\Desktop", 2, 5000, [ref] $result))
}
For the registry key name I tried all of (as strings in quotes, an error
was generated when I tried the last without)...
HKEY_CURRENT_USER\Control Panel\Desktop
HKEY_CURRENT_USER
Control Panel
Desktop
NULL
.... as per this documentation by Microsoft ...
https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-settingchange
.... but none made any difference, the setting remained stubbornly enabled.
For screen saver related settings which are covered by the
`SystemParametersInfo` Windows API function, specify the correct action
value to WParam. Multiple settings will require separate message broadcasts
for each SystemParametersInfo action.
Thanks, but made no odds when I tried it. The lock-screen setting is
still not changed.
--
Fake news kills!

I may be contacted via the contact address given on my website:
www.macfh.co.uk
Zaidy036
2023-10-16 14:58:38 UTC
Permalink
Post by JJ
Post by Java Jive
I have created the BATch file appended below, which is intended to
provide a quick and painless way to change the screensaver and power
modes from their normal settings, Blank & Stay Awake, to a disabled
state, None and Presentation, and back again. This is easy enough to do
via the relevant dialog boxes, but is irritatingly fiddly because some
of the settings are under Personalisation, Screensaver and others under
Power, hence the desire for a quicker and simpler method.
The power setting change between Stay Awake and Presentation appears to
be working correctly, but the screensaver change is failing. If I run,
say ...
Screensave /0
.... but then launch the control panel for the screensaver, the choice of
screensaver is correctly None, but the option "On resume, display logon
screen" is still checked and this means that the screen will still go to
the logon screen when the timer expires. Conversely if I clear the
option and do ...
Screensave /1
.... and then launch the screensaver dialog again, the option remains
unchecked, which means that if the timer expires, or I hibernate the
machine, I'm not prompted for a password, which of course is insecure.
All online sources that I've read suggest that the following registry
settings should be enough to set the screensaver ...
[HKEY_CURRENT_USER\Control Panel\Desktop]
Registry data changes in `HKEY_CURRENT_USER\Control Panel` can be notified
by broadcasting WM_SETTINGCHANGE window message, but batch file alone
doesn't have that capability. A separate tool is neeed. e.g. AutoHotkey,
AutoIt, PowerShell, etc.
Post by Java Jive
[HKU\<ID>\Software\Microsoft\Windows\CurrentVersion\Explorer\ComDlg32]
Notification of changes of registry data in this key is not needed, as they
are always re-read when the dialog is needed.
Post by Java Jive
[HKU\<ID>\Software\Classes\Local
Settings\Software\Microsoft\Windows\Shell\Bags\584\ComDlgLegacy]
Explorer doesn't re-read registry data under
`HKU\<ID>\Software\Classes\Local
Settings\Software\Microsoft\Windows\Shell\Bags` each time a folder view is
needed. Even if there was registry changes window message notification. Only
system restart, user re-login, or EXPLORER.EXE process restart will re-read
them.
Same thing applies to registry data in
`HKU\<ID>\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist`
key. PS: it's used to cache things. See: Nirsoft UserAssistView tool.
Post by Java Jive
[HKLM\SYSTEM\CurrentControlSet\Control\Nsi\{eb004a03-9b1a-11d4-9123-0050047759bc}\24]
NSI service registry data changes is not notifiable. The service will need
to be restarted for changes to take effect. However, the service is needed
Browser, Dhcp, Dnscache, HomeGroupProvider, iphlpsvc, LanmanWorkstation,
Netlogon, Netman, netprofm, NlaSvc, SessionEnv, SharedAccess,
WinHttpAutoProxySvc, WwanSvc
Some of above services can't be restarted and the system will need to be
restarted in order for the registry changes to take effect.
...
So, since at least one registry data changes need a system restart. It's
best to simply give a warning to the user that the registry changes will not
have any effect until the system is restarted.
in a batch run CONTROL DESK.CPL,SCREENSAVER,@SCREENSAVER
and then use AutoIt or PTFBpro to make settings and close GUI
then no need to reboot for RegEdits to work
Java Jive
2023-10-16 11:44:53 UTC
Permalink
Further background ...
Post by Java Jive
I have created the BATch file appended below, which is intended to
provide a quick and painless way to change the screensaver and power
modes from their normal settings, Blank & Stay Awake, to a disabled
state, None and Presentation, and back again.  This is easy enough to do
via the relevant dialog boxes, but is irritatingly fiddly because some
of the settings are under Personalisation, Screensaver and others under
Power, hence the desire for a quicker and simpler method.
The power setting change between Stay Awake and Presentation appears to
be working correctly, but the screensaver change is failing.  If I run,
say ...
    Screensave /0
.... but then launch the control panel for the screensaver, the choice
of screensaver is correctly None, but the option "On resume, display
logon screen" is still checked and this means that the screen will still
go to the logon screen when the timer expires.  Conversely if I clear
the option and do ...
    Screensave /1
.... and then launch the screensaver dialog again, the option remains
unchecked, which means that if the timer expires, or I hibernate the
machine, I'm not prompted for a password, which of course is insecure.
All online sources that I've read suggest that the following registry
settings should be enough to set the screensaver ...
[HKEY_CURRENT_USER\Control Panel\Desktop]
"ScreenSaveActive"="1"
"ScreenSaverIsSecure"="1"
"SCRNSAVE.EXE"="C:\\Windows\\system32\\scrnsave.scr"
[HKEY_CURRENT_USER\Control Panel\Desktop]
"ScreenSaveActive"="0"
"ScreenSaverIsSecure"="0"
ie: "SCRNSAVE.EXE" setting deleted
.... and those are exactly what my BATch file sets.
So this is the Win7+, possibly Vista+, version, which doesn't work as
Post by Java Jive
@ECHO OFF
Rem ScreenSave.bat
Rem ==============
Rem
Rem Program to turn on & off the screen saver and power screen blanking
options
Rem Non-empty string here or /1 leading parameter turns the screen saver
on and /0 off respectively
SET Switch="1"
Rem Non-empty string here or /D leading parameter gives debugging messages
SET Debug=""
:NextPar
IF /i "%1" EQU "/0" (
    SET Switch="0"
    SHIFT
    GOTO NextPar
    )
IF /i "%1" EQU "/1" (
    SET Switch="1"
    SHIFT
    GOTO NextPar
    )
IF /i "%1" EQU "/D" (
    SET Debug="Y"
    SHIFT
    GOTO NextPar
    )
IF %Switch%=="0" GOTO Off
:On
Rem Set screensaver to 'Blank'
ECHO Setting ScreenSaver to 'Blank'
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v SCRNSAVE.EXE /t
REG_SZ /d C:\Windows\system32\scrnsave.scr /f > NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaverIsSecure
/t REG_SZ /d 1 /f > NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaveActive /t
REG_SZ /d 1 /f > NUL 2>&1
Rem Set power scheme to 'Stay Awake'
CALL :FindPowerGUID "Stay Awake" PName GUID
ECHO Setting Power Scheme to '%PName%'
powercfg /setactive %GUID%
GOTO Quit
:Off
Rem Set screensaver to 'None'
ECHO Setting ScreenSaver to 'None'
reg delete "HKEY_CURRENT_USER\Control Panel\Desktop" /v SCRNSAVE.EXE /f
Post by Java Jive
NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaverIsSecure
/t REG_SZ /d 0 /f > NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaveActive /t
REG_SZ /d 0 /f > NUL 2>&1
Rem Set power scheme to 'Presentation'
CALL :FindPowerGUID "Presentation" PName GUID
ECHO Setting Power Scheme to '%PName%'
powercfg /setactive %GUID%
GOTO Quit
:FindPowerGUID
SETLOCAL EnableDelayedExpansion
for /f "usebackq tokens=1-4*" %%A in (`powercfg /list ^| find /i %1`) do (
    IF %Debug% NEQ "" Echo %%D %%E
    SET _Name=%%E
    SET _GUID=%%D
    IF %Debug% NEQ "" Echo _Name="!_Name!"
    SET _Name="!_Name:(=!"
    SET _Name=!_Name:"=!
    IF %Debug% NEQ "" Echo _Name="!_Name!"
    SET _Name="!_Name:)=!"
    SET _Name=!_Name:"=!
    IF %Debug% NEQ "" Echo _Name="!_Name!"
    SET _Name="!_Name: *=!"
    SET _Name=!_Name:"=!
    IF %Debug% NEQ "" Echo _Name="!_Name!"
    )
ENDLOCAL & (
    IF %Debug% NEQ "" (
        Echo SET %~2="%_Name%"
        Echo SET %~3="%_GUID%" & Echo.
        )
    SET "%~2=%_Name%"
    SET "%~3=%_GUID%"
    )
SET _Name=
SET _GUID=
EXIT /B
:Quit
SET Switch=
SET Debug=
SET PName=
SET GUID=
ECHO.
... but things are much easier in XP. There, when manually you set the
Screensaver to 'None', the 'On resume, password protect' setting becomes
greyed out and disabled, and my XP equivalent BATch file works exactly
as expected. The power setting change is simpler too, because you can
specify the power scheme directly by name, instead of having to go and
find its GUID. By comparison with XP I suspect the isolated and
anomalous behaviour of the lock-screen setting since W7 (possibly Vista)
is actually a bug.

Here's the working XP version:

@ECHO OFF
Rem ScreenSave.bat
Rem ==============
Rem
Rem Program to turn on & off the screen saver and power screen blanking
options

Rem Non-empty string here or /0 or /1 leading parameter turns the screen
saver off and on respectively
SET Switch="1"

:NextPar
IF /i "%1" EQU "/0" (
SET Switch="0"
SHIFT
GOTO NextPar
)
IF /i "%1" EQU "/1" (
SET Switch="1"
SHIFT
GOTO NextPar
)

IF %Switch%=="0" GOTO Off

:On
Rem Set screensaver to 'Blank'
ECHO Setting ScreenSaver to 'Blank'
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v SCRNSAVE.EXE /t
REG_SZ /d C:\Windows\system32\scrnsave.scr /f > NUL 2>&1
Rem reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v
ScreenSaverIsSecure /t REG_SZ /d 1 /f > NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaveActive /t
REG_SZ /d 1 /f > NUL 2>&1
Rem Set power scheme to 'Stay Awake'
ECHO Setting Power Scheme to 'Stay Awake'
powercfg /setactive "Stay Awake"
GOTO Quit

:Off
Rem Set screensaver to 'None'
ECHO Setting ScreenSaver to 'None'
reg delete "HKEY_CURRENT_USER\Control Panel\Desktop" /v SCRNSAVE.EXE /f
Post by Java Jive
NUL 2>&1
Rem reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v
ScreenSaverIsSecure /t REG_SZ /d 0 /f > NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaveActive /t
REG_SZ /d 0 /f > NUL 2>&1
Rem Set power scheme to 'Presentation'
ECHO Setting Power Scheme to 'Presentation'
powercfg /setactive "Presentation"
GOTO Quit

:Quit
SET Switch=
SET PName=
SET GUID=

ECHO.
--
Fake news kills!

I may be contacted via the contact address given on my website:
www.macfh.co.uk
Java Jive
2023-10-25 11:46:03 UTC
Permalink
On 15/10/2023 18:00, Java Jive wrote:
As a reminder ...
Post by Java Jive
I have created the BATch file appended below, which is intended to
provide a quick and painless way to change the screensaver and power
modes from their normal settings, Blank & Stay Awake, to a disabled
state, None and Presentation, and back again.  This is easy enough to do
via the relevant dialog boxes, but is irritatingly fiddly because some
of the settings are under Personalisation, Screensaver and others under
Power, hence the desire for a quicker and simpler method.
The power setting change between Stay Awake and Presentation appears to
be working correctly, but the screensaver change is failing.  If I run,
say ...
    Screensave /0
.... but then launch the control panel for the screensaver, the choice
of screensaver is correctly None, but the option "On resume, display
logon screen" is still checked and this means that the screen will still
go to the logon screen when the timer expires.  Conversely if I clear
the option and do ...
    Screensave /1
.... and then launch the screensaver dialog again, the option remains
unchecked, which means that if the timer expires, or I hibernate the
machine, I'm not prompted for a password, which of course is insecure.
All online sources that I've read suggest that the following registry
settings should be enough to set the screensaver ...
[HKEY_CURRENT_USER\Control Panel\Desktop]
"ScreenSaveActive"="1"
"ScreenSaverIsSecure"="1"
"SCRNSAVE.EXE"="C:\\Windows\\system32\\scrnsave.scr"
[HKEY_CURRENT_USER\Control Panel\Desktop]
"ScreenSaveActive"="0"
"ScreenSaverIsSecure"="0"
ie: "SCRNSAVE.EXE" setting deleted
.... and those are exactly what my BATch file sets.  Further, a before
and after comparison of the entire registry after changing just the
screensaver lock setting manually suggests that the ScreenSaverIsSecure
setting is the only thing of any seeming relevance which is changed by
[HKU\<ID>\Control Panel\Desktop]
BTW, ditto for [HKCU\Control Panel\Desktop], but an entire registry dump
doesn't show HKCU as we see it in Regedit, only as HKU\<ID>.
Post by Java Jive
"ScreenSaverIsSecure"="1"
; As expected, value changes to "0"
[Snip further detail included originally for completeness' sake on the
off chance of it being relevant, but now shown to be irrelevant]
Post by Java Jive
Now I'm wondering if it is necessary somehow to have the BATch file
alert the system, presumably the Explorer instance that is running the
Desktop, that the user registry hive has changed and it needs to reload
it.  I could kill that Explorer instance, actually it would have to be
all Explorer instances, and relaunch Explorer, but doing that is way too
complicated for a "quicker and simpler" method, and actually pointless
because it would be easier just to continue altering the settings manually.
As discussed most helpfully by JJ, something like the above is indeed
necessary. The BATch file is almost unchanged, the single new line to
achieve the above, by calling a powershell script, is commented below,
and said powershell script is discussed and appended below it [as
always, beware unintended line wrap in both] ...

Working BATch file:
@ECHO OFF
Rem ScreenSave.bat
Rem ==============
Rem
Rem Program to turn on & off the screen saver and power screen blanking
options

Rem Non-empty string here or /0 or /1 leading parameter turns the screen
saver off and on respectively
SET Switch="1"
Rem Non-empty string here or /D leading parameter gives debugging messages
SET Debug=""

:NextPar
IF /i "%1" EQU "/0" (
SET Switch="0"
SHIFT
GOTO NextPar
)
IF /i "%1" EQU "/1" (
SET Switch="1"
SHIFT
GOTO NextPar
)
IF /i "%1" EQU "/D" (
SET Debug="Y"
SHIFT
GOTO NextPar
)

IF %Switch%=="0" GOTO Off

:On
Rem Set screensaver to 'Blank'
ECHO Setting ScreenSaver to 'Blank'
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v SCRNSAVE.EXE /t
REG_SZ /d C:\Windows\system32\scrnsave.scr /f > NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaverIsSecure
/t REG_SZ /d 1 /f > NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaveActive /t
REG_SZ /d 1 /f > NUL 2>&1
Rem Set power scheme to 'Stay Awake'
CALL :FindPowerGUID "Stay Awake" PName GUID
ECHO Setting Power Scheme to '%PName%'
powercfg /setactive %GUID%
GOTO Quit

:Off
Rem Set screensaver to 'None'
ECHO Setting ScreenSaver to 'None'
reg delete "HKEY_CURRENT_USER\Control Panel\Desktop" /v SCRNSAVE.EXE /f
Post by Java Jive
NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaverIsSecure
/t REG_SZ /d 0 /f > NUL 2>&1
reg add "HKEY_CURRENT_USER\Control Panel\Desktop" /v ScreenSaveActive /t
REG_SZ /d 0 /f > NUL 2>&1
Rem Set power scheme to 'Presentation'
CALL :FindPowerGUID "Presentation" PName GUID
ECHO Setting Power Scheme to '%PName%'
powercfg /setactive %GUID%
GOTO Quit

:FindPowerGUID
SETLOCAL EnableDelayedExpansion
for /f "usebackq tokens=1-4*" %%A in (`powercfg /list ^| find /i %1`) do (
IF %Debug% NEQ "" Echo %%D %%E
SET _Name=%%E
SET _GUID=%%D
IF %Debug% NEQ "" Echo _Name="!_Name!"
SET _Name="!_Name:(=!"
SET _Name=!_Name:"=!
IF %Debug% NEQ "" Echo _Name="!_Name!"
SET _Name="!_Name:)=!"
SET _Name=!_Name:"=!
IF %Debug% NEQ "" Echo _Name="!_Name!"
SET _Name="!_Name: *=!"
SET _Name=!_Name:"=!
IF %Debug% NEQ "" Echo _Name="!_Name!"
)
ENDLOCAL & (
IF %Debug% NEQ "" (
Echo SET %~2="%_Name%"
Echo SET %~3="%_GUID%" & Echo.
)
SET "%~2=%_Name%"
SET "%~3=%_GUID%"
)
SET _Name=
SET _GUID=
EXIT /B

:Quit
REM Line below is only significant change from previous version
powershell -ExecutionPolicy ByPass -File
C:\Programs\Utilities\WMSettingsChange.ps1
SET Switch=
SET Debug=
SET PName=
SET GUID=

ECHO.


As far as the powershell script goes, previously I posted the following,
but no-one, including myself, noticed the embarrassingly basic bug -
it includes only a function definition, not a call to the function so
defined, and consequently does nothing. Duh! Sorry about that, my
excuse is that it's been quite a while since I last did any serious
programming.
Post by Java Jive
=====================
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(IntPtr hWnd, uint Msg,
UIntPtr wParam, string lParam, uint fuFlags, uint uTimeout, out UIntPtr
lpdwResult);
function Send-SettingChange {
$HWND_BROADCAST = [IntPtr] 0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [UIntPtr]::Zero
[void] ([Win32.Nativemethods]::SendMessageTimeout($HWND_BROADCAST,
$WM_SETTINGCHANGE, [UIntPtr]::Zero, "HKEY_CURRENT_USER\Control
Panel\Desktop", 2, 5000, [ref] $result))
}
For the registry key name I tried all of (as strings in quotes, an error
was generated when I tried the last without)...
HKEY_CURRENT_USER\Control Panel\Desktop
HKEY_CURRENT_USER
Control Panel
Desktop
NULL
.... as per this documentation by Microsoft ...
https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-settingchange
.... but none made any difference, the setting remained stubbornly enabled.
As soon as I included a function call ...

Send-SettingChange;

... all hell broke loose, but eventually I was able to remove all the
errors except one (ignore the line number, because by then other things
had changed from the above):

Cannot convert argument "6", with value:
"System.Management.Automation.PSReference", for "SendMessageTimeout" to
type "
System.UIntPtr": "Cannot convert the
"System.Management.Automation.PSReference" value of type
"System.Management.Automa
tion.PSReference" to type "System.UIntPtr"."
At C:\Programs\Utilities\WMSettingsChange.ps1:40 char:42
+ [void] ([Win32.W32N]::SendMessageTimeout <<<< ($HWND_BROADCAST,
$WM_SETTINGCHANGE, [UIntPtr]::Zero, $SPI_SCREENSA
VESECURE, 2, 5000, [System.Management.Automation.PSReference] $result));
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodArgumentConversionInvalidCastArgument

Counting from 0, parameter 6 is actually the 7th, the optional return
value, yet confusingly the above error message mentions the timeout.
AFAICT, the message is describing that the attempted cast for the return
value is somehow illegal.

However, before discovering the omission of the function call, I'd been
trying other things, including extending the above script to call ...
SystemParametersInfo
... to set the lock screen setting, and it turned out that this on its
own is sufficient to get the setting to change. Here's a powershell
script that finally works. It reads from the registry the value set by
the BATch file script and sets it into the live user profile (commented
out lines were used for debugging; $result = 1 means success):

Add-Type -Namespace Win32 -Name W32N -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern int SystemParametersInfo(
int uAction,
int uParam,
int lpvParam,
int fuWinIni
);
"@;

function Send-SettingChange {
# Set-PSDebug -Trace 1
$result = 0x0000;
$SPI_SCREENSAVESECURE = 0x0077;
$SPIF_SENDWININICHANGE = 0x0002;
$REG_SCREENSAVESECURE = (Get-ItemProperty -Path "HKCU:\Control
Panel\Desktop").ScreenSaverIsSecure;
# "ScreenSaverIsSecure = $REG_SCREENSAVESECURE";
$result = ([Win32.W32N]::SystemParametersInfo($SPI_SCREENSAVESECURE,
$REG_SCREENSAVESECURE, 0x0000, $SPIF_SENDWININICHANGE ));
# "SystemParametersInfo: Result = $result";
# Set-PSDebug -Trace 0
}

Send-SettingChange;
--
Fake news kills!

I may be contacted via the contact address given on my website:
www.macfh.co.uk
Loading...