Set wallpaper with a VBS script

  • Thread starter Thread starter Dave Niemeyer
  • Start date Start date
D

Dave Niemeyer

I'm a newbie, more like a "nobie" to VBS script... Couldn't find a way to
change wallpaper in Group Policy without using active desktop so I'm trying
a VBS method.
What am I doing wrong? The change in the registry is accomplished but no
change in the wallpaper is seen.
------------------------------------------
Set WshShell = WScript.CreateObject("Wscript.Shell")
WshShell.RegWrite "HKCU\Control Panel\Desktop\Wallpaper",
"C:\WINNT\FeatherTexture.bmp"
WshShell.RegWrite "HKCU\Software\Microsoft\Internet
Explorer\Desktop\General\BackUpWallpaper", "C:\WINNT\FeatherTexture.bmp"
WshShell.RegWrite "HKCU\Software\Microsoft\Internet
Explorer\Desktop\General\Wallpaper", "C:\WINNT\FeatherTexture.bmp"
 
Dave,

I'm not sure about the script itself, but if you are running this in a GPO
logon script you should make sure that policy and logon scripts are applied
synchronously in the foreground. This is not the default on XP.

Otherwise this can probably be accomplished using a Windows settings change
message, which is how Windows notifies running applications (and itself)
that system parameters have changed. You should be able to send this in the
script if you wrap the proper API calls.

Policy Maker's registry item can easily set these registry values for you,
and sends the required update messages by default. There are different
parameters for updating the environment, printers and other devices, policy,
and windows settings - however I think it has you covered with the registry
extension. Plus you get the benefits of making these settings policy vs.
script.

Regards,

Eric Voskuil
Policy Maker
http://www.autoprof.com/policy
 
Thanks for the info, Eric, but I'm not sure I follow.

How can I send a "Windows settings change message" and do so in a script
included in a group policy and "wrap the proper API calls." If this is a
very loaded question, please direct me where to investigate, thanks.

I've only tried that script, seen below, manually so far, not included it as
a parameter in any GPO. And I haven't seen how to accomplish my goal in
Group Policy without enabling Active Desktop which I think I'll have to
avoid since we "hide all desktop items" which includes the Active wallpaper.
If anyone can tell me how the Active desktop wallpaper can be seen yet hide
all items on the desktop, like all the icons, I'd be glad to know how. A
wallpaper isn't hidden if we don't use Active desktop but hide all desktop
items as far as I can see using Group Policy.

Dave Niemeyer
-------------------------------------
 
He's describing a commercial product that you can buy to
do what you want. (Though you'll apparently have to fill
out a form full of personal info. in order to find out exactly
what it is and what it costs.)

Wrapping API calls refers to writing an EXE or DLL to
change the wallpaper and then calling it from script.
The catch is that changing the Registry setting is not enough.
You must also "broadcast" the change so that Explorer will
redraw the Desktop. That requires a call to the Windows API
that cannot be done with script.

You might be able to cause an update with SendKeys if you
open the Display applet in Control Panel through
the script and go through the motions of changing wallpaper.

If you want a free component to do the job:
http://www.jsware.net/jsware/scripts.html

see the JSSys.dll component
 
Dave Niemeyer said:
Thanks for the info, Eric, but I'm not sure I follow.

How can I send a "Windows settings change message" and do so in a script
included in a group policy and "wrap the proper API calls." If this is a
very loaded question, please direct me where to investigate, thanks.

A script is a script, no matter that it runs in a GPO. I didn't elaborate
on posting messages using Windows APIs in VBScript, because if you knew how
to do it I wouldn't have to, and if you didn't I don't have the ability to
describe it to you in enough detail to make it work. However, since you
asked, this is the call as it is done in C++:

PostMessage(
HWND_BROADCAST,
WM_SETTINGCHANGE,
FALSE,
(lParam)_T("Windows") )

and this is a bit on it from MSDN:

WM_SETTINGCHANGE
==================
The system sends the WM_SETTINGCHANGE message to all top-level windows when
the SystemParametersInfo function changes a system-wide setting or when
policy settings have changed.

Applications should send WM_SETTINGCHANGE to all top-level windows when they
make changes to system parameters. (This message cannot be sent directly to
a window.) To send the WM_SETTINGCHANGE message to all top-level windows,
use the SendMessageTimeout function with the hwnd parameter set to
HWND_BROADCAST.
==================

I know you can call this API directly from VB by using the proper function
prototype, but I don't know about VB Script. This is what I meant by
"wrapping" the API.

Again, I can't say for sure that this message will force the desktop to
update once loaded, but if not it's unlikely anything else would except for
an explorer restart.

However the first thing you should do is try your *existing* script in a
synchronous GPO/logon script. Since the script will run before the
wallpaper is loaded, it would normally not have problem with refresh. And
since a restart solves your problem, this should as well. Since wallpaper
is a user profile item, I'd expect a logoff/logon to reset it - are you sure
it takes a full restart?
I've only tried that script, seen below, manually so far, not included it as
a parameter in any GPO.

Hook it into logon script policy.
And I haven't seen how to accomplish my goal in
Group Policy without enabling Active Desktop which I think I'll have to
avoid since we "hide all desktop items" which includes the Active wallpaper.
If anyone can tell me how the Active desktop wallpaper can be seen yet hide
all items on the desktop, like all the icons, I'd be glad to know how. A
wallpaper isn't hidden if we don't use Active desktop but hide all desktop
items as far as I can see using Group Policy.

I don't know about the specific wallpaper policies, but it sounds like you
are talking about ADM templates. That is different than what you are trying
to do above, and if what you are doing works - short of a reboot - then you
should be able to make it work the way you want by just running it at logon.

Regards,

Eric
 
Ok, this is an undocumented DLL call, but it should do the job:

Set the wallpaper registry entries and then execute:

RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters

Robert,
 
I got the script to work along with the GOP but it's not applying
synchronously in the foreground, I have to log out and back in for the
change to take effect. SOOO, all I gotta do now is find out how to make
this script and GPO apply synchronously in the foreground. It's asynch. by
default, so I read on the help files on the 2k3 server, but no help how to
set it synch. I don't really want to make other API calls or other things
above my head (which I am already.....)....

Dave Niemeyer
 
Dave said:
I got the script to work along with the GOP but it's not applying
synchronously in the foreground, I have to log out and back in for the
change to take effect. SOOO, all I gotta do now is find out how to make
this script and GPO apply synchronously in the foreground. It's asynch. by
default, so I read on the help files on the 2k3 server, but no help how to
set it synch. I don't really want to make other API calls or other things
above my head (which I am already.....)....

Hi

Description of the Windows XP Professional Fast Logon Optimization Feature
http://support.microsoft.com/default.aspx?scid=kb;EN-US;305293

<quote>
By default in Windows XP Professional, the Fast Logon Optimization feature
is set for both domain and workgroup members. As a result, Windows XP does
not wait for the network to be fully initialized at startup and logon.
</quote>

To disable this and see if it helps on your problem, try to set the
"Always wait for the network at computer startup and logon" policy
(a negative side effect is that it might make the startup/logon to
take longer time):

By registry edit; Set the value SyncForegroundPolicy to 1 (REG_DWORD) in this
key:

HKEY_LOCAL_MACHINE\Software
\Policies\Microsoft\Windows NT
\CurrentVersion\Winlogon\

Create the necessary keys/value, or put the vbscript below in a .vbs file and
double-click on it.

Set oShell = CreateObject("WScript.Shell")
sRegValue = "HKLM\Software\Policies\Microsoft\Windows NT\" _
& "CurrentVersion\Winlogon\SyncForegroundPolicy"

oShell.RegWrite sRegValue, 1, "REG_DWORD"

MsgBox "Please reboot the computer"
 
I found out how to set it, the script, to be running synchronously and
supposed to be visible (admin templates, system, scripts, login scripts) but
it's still not applying immediately, I have to log out and log back in for
the new wallpaper to apply. Any ideas?

Dave Niemeyer
 
Dave said:
I found out how to set it, the script, to be running synchronously and
supposed to be visible (admin templates, system, scripts, login scripts) but
it's still not applying immediately, I have to log out and log back in for
the new wallpaper to apply. Any ideas?

Hi

Could you show the script code relevant to this?
 
Dave,

Since it works when you log off and back on, I'll assume that the script is
doing its job.

Torgeir posted some good info on forcing synchronous foreground processing
on XP - using this policy:
"Always wait for the network at computer startup and logon"

You may also have to set the policy that tells logon scripts to run before
the desktop is presented. This is different than foreground processing of
GPOs. Scripts are technically not run by the script GP client side
extension (CSE), they are run as the result of registry settings that the
script CSE writes. This is why I said you'll need to make sure both the GPO
and the scripts are set to run this way. Sorry I didn't have time initially
to give you the specifics. Try this ADM policy in addition to the other:

Computer Settings\Administrative Templates\System\Scripts\Run Logon Scripts
Synchronously

Regards,

Eric Voskuil
Policy Maker
http://www.autoprof.com/policy
 
Here's the VBS script I made:
---------------------------------------
Set WshShell = WScript.CreateObject("Wscript.Shell")
WshShell.RegWrite "HKCU\Control Panel\Desktop\Wallpaper",
"C:\WINNT\FeatherTexture.bmp"
--------------------------------------
Plus I could tile the wallpaper, etc but there's the basics.
---------------------------------------
I set the script to be run from the GPO, scripts, and set it to run
synchronously and not hidden in Computer Settings\Administrative
Templates\System\Scripts\Run Logon Scripts, synchronously

Still no luck. When I go to a new machine and log the test user in he
doesn't get the new wallpaper until I log him out and back in again. So the
script is running but not before showing the desktop. So I assume I need
to make a statement to run the script before displaying the desktop. Don't
know how to do that.

(BY THE WAY: Related but different approach: I could easily live with the
Active Desktop idea of a wallpaper but that shows the icons on the screen, I
don't want to show any icons, just the desktop wallpaper (this is in a
school environment) and I can hide the icons as stated in the policy listing
of icons individually, but any icons not listed there end up being shown on
the desktop. The only way I can see to hide all icons is to choose "hide
all desktop items or something to that effect, and that hides the active
desktop wallpaper as well. Any ideas on a workaround there would be
appreciated too.)

Thanks.

Dave Niemeyer
 
Dave said:
Here's the VBS script I made:

So you didn't add this one that Robert gave you?

RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters

Without it, you need a logoff/logon whatever you do with AD settings I'm afraid.

So after the regwrite, you should add this one:

WshShell.Run _
"%windir%\System32\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters", _
1, False
 
O.K. so I add that to the script, how about parameters specified in the GPO
parameters for the script. Do I have to specify parameters there like you
did or just put it in the script as you specify here? Sorry for dumb
questions...

Dave Niemeyer

WshShell.Run _
"%windir%\System32\RUNDLL32.EXE
user32.dll,UpdatePerUserSystemParameters", _
 
Dave said:
O.K. so I add that to the script, how about parameters specified in the GPO
parameters for the script. Do I have to specify parameters there like you
did or just put it in the script as you specify here? Sorry for dumb
questions...

Hi

If you mean the ,1 , False parameters for the Run parameter, you can keep them
or remove them, it's the default values anyway.


WSH 5.6 documentation (local help file) can be downloaded from here if you
haven't got it already:
http://msdn.microsoft.com/downloads/list/webdev.asp
 
Thanks!!
Worked slicker than deer guts on a door knob!!!
Thanks for the help, everyone.
Dave N
-------------------------------------
 
Dave,

Can you please send me your working script you made?
(e-mail address removed)

Thank you,
Sam
 
Setting the wallpaper of current user without restarting

Instructions:

1. Save your wallpaper file as mywallpaper.bmp in %systemroot% (i.e. c:\windows, in most of the cases)
2. Run below script

Script:


'----------------------------Script Start -----------------------------------------------------
Dim WshShell
const HKEY_CURRENT_USER = &H80000001
strComputer = "."
Set WshShell = WScript.CreateObject("Wscript.Shell")
Set StdOut = WScript.StdOut
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" &_
strComputer & "\root\default:StdRegProv")
strKeyPath = "Control Panel\Desktop"
strEntryName = "Wallpaper"
strValue = "mywallpaper.bmp"
oReg.SetStringValue HKEY_CURRENT_USER,strKeyPath,strEntryName,strValue
WshShell.Run "%systemroot%\System32\RUNDLL32.EXE user32.dll,UpdatePerUserSystemParameters", 1, False
Set WshShell = Nothing
'--------------------------Script End -----------------------------------------------------------
 
Back
Top