If you deliver a concept of a modern managed Windows 10 desktop managed with Intune, you take care of security settings and necessary Windows configurations. One part of the important configurations, beside security settings, are the small corporate identity things like corporate logon screen or corporate wallpaper. I’m totally okay with the option in Intune to configure the logon screen to a fixed image, which can’t be modified by the end user.

It is something which provides little effort to implement and does a really good job. For example when you have a class room and all devices are locked, you get a really nice uniform appearance.
Sadly for the desktop background (aka wallpaper) this is a bit more challenging. I really do like the idea to personally enable the modern desktops today. I’m not talking about BYOD, I’m still talking about a corporate device. But a modern approach for me, is a choose your own device (CYOD) policy and the ability to personalize the device in a certain degree to you personal needs. For this I really want users to let them define their own wallpaper. They should walk away with their new device and think, “Hey, I really love my newly chosen device and I’m able to make it personal”. This way people can be productive as their device fits their individual needs. It serves how they work and they feel esteemed by their company. In fact this is for some younger people a hiring reason. Many people sit in front of their devices 8h and more a day. So the Intune native configuration profile option to set a fixed wallpaper is not going to fit in my approach. I want people to make the desktop more personal.

I want to set a predefined wallpaper and let the user change it later on if he likes to. Trying to make him happy and let his family picture generate a smile on his face :-).
As Intune only has the option to set it fixed, I wrote a small script to do this job for me. There are a lot of other solutions out there covering this topic, this is now my approach. I wanted to have a similar approach like Intune, pointing to a public URL, I’ve chosen a Azure blob storage to store the wallpaper images. To provide the best user experience I implemented a small extra logic to find the aspect ratio of the primary monitor. For example, most laptops nowadays come with a ratio of 16×9 or 3×2. So, the script is figuring out the aspect ratio and downloads a wallpaper fitting this aspect ratio. By definition for a 16×9 aspect ratio it will download the file wallpaper-16×9.jpg from the Azure blob storage. This way I can provide the correct wallpapers for every device with little effort. I just have to create them and upload them to the Azure blob storage account. If you don’t like to provide so many different wallpapers, I do a fallback. If a wallpaper for the determined aspect ratio is not found, I try to get one which is mostly compatible. For example a 4×3 display is detected and the image is not available, I will do a fallback download to 3×2.
As the lowest common denominator you have to provide 2 wallpaper images on the Azure blob storage. In the fallback case all aspect ratios will be mapped to one of these ratios:
- wallpaper-16×9.jpg
- wallpaper-3×2.jpg
Here an example of a Azure blob storage container:

The access level must be set to anonymous read access (anonymous access is totally okay for wallpapers in my opinion, nothing to hide or containing relevant information, keep it simple):

So, if everything is setup for the wallpaper storage, you have to upload the PowerShell script to Intune. The script figures out the aspect ratio and gets the correct wallpaper image and sets it for you. The script must be configured to run in user context of the logged on user:

If you later decide to update the picture you can simply replace the images on the Azure blob storage with the new wallpaper images. Then you have to re-upload the PowerShell script to Intune to trigger it again. The re-upload is necessary, otherwise Intune will not trigger the script again, as it is marked as already run.
The following logic is available in the script:
- The first run off the script, if there is no wallpaper found, the script will download and set the correct wallpaper for the aspect ratio.
- If the script is triggered to run again:
- If the current wallpaper is still our pre-defined one (registry: HKCU\Control Panel\Desktop\WallPaper) the script will go and download the correct aspect ratio image again and set/refreshes it.
- If the current wallpaper is a user-defined one, the script will not change anything.
This makes it possible to change the pre-defined wallpaper only for devices which are still having the pre-defined wallpaper set. All other devices which already set a personalized wallpapers are not touched.
Everything will be logged to “%localappdata%\temp\Set-Wallpaper.log” in the format of the ConfigMgr Tace Log Tool (cmtrace.exe), like seen below into

To get everything working just replace the Azure blob storage account with your blob container URL:

To setup an Azure blob storage account just follow this official guide here: Quickstart: Upload, download, and list blobs with the Azure portal
Update: Based on a readers comment, I would like to mention here that it is also possible to modify the wallpaper prefix, in the script example above $global:wallpaper is set to wallpaper. You can easily change this to your needs, same for the extension if you like to have .png files. Changing the prefix gives the option to target two versions of the script to different AAD groups. Example: Wallpaper script one for APAC has prefix set to apac, script two for EMEA set to emea. The blob storage can be the same(!), it just needs to have apac-16×9.jpg, apac-3×2.jpg and emea-16×9.jpg and emea-3×2.jpg. Now target APAC wallpaper script to APAC user group and EMEA wallpaper script to EMEA users group. Et voilà!
If everything went well you will see a nice fitting wallpaper applied to your device, right after enrollment with Autopilot. In this example a 16×9 wallpaper was used from the blob storage container.

If you like to give it a try go and get it from my GitHub account here:
https://github.com/okieselbach/Intune/blob/master/Set-Wallpaper.ps1
So, my final words are, make your end users happy by allowing them a nice wallpaper and still provide some good looking corporate branding after enrollment of the device.
What if you wanted the default wallpaper to be different from region to region? Could you have multiple scripts assigned by region/location? Would you need multiple blobs?
Thanks for this useful content.
Hi Mmajeres,
you could assign different scripts to different groups which have the the regional members. In your script I would use the same blob storage but in the script change the prefix for the wallpaper image here:
# Image name pattern based on variables and ratio e.g. wallpaper-16×9.jpg
$global:wallpaper = “wallpaper”
$global:ext = “jpg”
so, in script one use for example regionA as prefix and in script two use regionB as prefix. Then upload the images like this:
regionA-16×9.jpg
regionA-3×2.jpg
regionB-16×9.jpg
regionB-3×2.jpg
that’s it, your regional users are targeted with the correct script, which gets the regional wallpaper for them.
best,
Oliver
It was so easy to do this in grouo policy so why cant they do it for intune.
Good question, maybe they will in future, right now you have to do these little workarounds… maybe create a uservoice item to gather community demand for it
Nice articel Oliver!
Many thanks :-)!
Thanks for the article. When I started setting wallpapers for my company, the users came came for with pitchforks and torches because they could not change the wallpaper.
I gave up on it for a while, but I’m going to give your script a try.
I hope it will solve the problem well 😊👍
Great one, Oli!
I’d have still a missing peace of the puzzle I think: There could be another script to maintain the wallpaper settings for the default profile so when a user logs into the device for the very first time, the intended wallpaper would immediately appear instead of waiting for the script to run in user context. Of course, the Set-Wallpaper.ps1 script here would then come into play to perform any future updates to those existing profiles.
I have not looked into it yet but simply wanted to share my immediate thoughts about this great article 😉
Cheers,
—Julian
True that could be valid for some cases. In my case I use it with Autopilot devices and configured ESP. In that case I don’t have a timing issue. As soon as the user sees the desktop the wallpaper ist already set for him. But on a shared device, a second user would run into this… That could be an enhancement 👍
I love the script, I am wondering if:
The script can take into account resolution as well?
Now I don’t know a lot about aspect rations vs. resolution but on my 16:9 2560×1440 monitor it is detected as 16:9 and downloads the correct wallpaper however the wallpaper is in 1920×1080 meaning I get black bars around the wallpaper.
and also detect multiple monitors / extended desktop and download a certain wallpaper if that is the case?
^ I guess that extended desktop basically just gives you for example 2560×1440*2 = 5120×2880?
Hi Karl,
thanks 😀 and in regards to your request about taking resolution into account, that is not a big deal in the end. Monitor resolution is available in the script. In the Get-Wallpaper function I use the resolution to calculate the ratio. You can easily use the resolution stored in $x and $y to create a different filename e.g.:
$imageName = “$global:wallpaper-16×9-$($x)x$($y).$global:ext”
if (-not Invoke-WallpaperDownload $imageName) {
… do fallback download here
}
Getting all screens and adding the resolution is a bit trickier, as the .NET functions found to be not that reliable in terms of the results… that would end up in a lot of researching for suitable functions and a lot of testing to be working in general.
best,
Oliver
I’m getting the following error. any idea about it?
Split-Path : Cannot bind argument to parameter ‘Path’ because it is an empty string.
At line:84 char:59
+ … g]$Component = “$($MyInvocation.ScriptName | Split-Path -Leaf):$($MyI …
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:String) [Split-Path], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyStringNotAllowed,Microsoft.PowerShell.Commands.SplitPathCommand
Hi Lanos,
Yes I think this is because you are running it from an PS Editor directly. Try running it by calling the .ps script from command line. Otherwise the $MyInvocation variable might not be set.
Best,
Oliver
When running this in PowerShell ISE, after updating the URL I get the following error: “Invoke-WebRequest : The remote name could not be resolved: ‘companyname.blob.core.windows.net’
At C:\Users\UserName\OneDrive – CompanyName\Desktop\Wallpaper.ps1:168 char:5
+ Invoke-WebRequest -Uri $url -OutFile $imagePath -TimeoutSec 10 -U …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExceptio
n
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand”
Any ideas why that is happening and how to resolve?
Pardon my lack of in-depth PS knowledge:
I love the ratio detection in this script, but if I were to deploy the source files locally (ie C:\Resources\Wallpaper), how would I best modify the global variables to refer to this location?
I’d like to utilize blob storage more in the future, we just aren’t ready for it quite yet!
There is a function Invoke-WallpaperDownload… this you need to rewrite… I think it might actually be enough to comment the Invoke-Webrequest line and if you have placed all the images in the $imagePath it should be working. Give it a try 👍
best,
Oliver
Why not package this up as a win32 app so you can deliver without the need to have an azure blob?
Great work, I’ve also converted images to base64 and create the jpg locally on-the-fly; could be something to consider.
How does your script take into account external monitors/ multiple monitors? Does it look at both resolutions or only the one marked as the main screen?
Thanks. Actually it is looking at the primary screen. The blob was because we often use this https://oliverkieselbach.com/2019/07/16/cloud-storage-management-solution-for-intune-managed-clients/ and this gives a flexible maintenance approach. There are often various ways to solve things, this way is well received by a lot of clients, but as you said as a package would be feasible as well 👌
Nice one!, how can this be achieved in android mobile devices and android tablets. I will like to apply a wallpaper and screen locks to corporate mobile phone and tablets of different sizes enrolled in Intune.
That’s actually I never looked at until now. As we do not have scripting capabilities on the mobile phones I don’t see an easy solution for this right now.
Thanks for the guide! However I am stuck at uploading the Powershell script.
Selected file ‘Set-Wallpaper.ps1’ must be between 1 and 200000 bytes.
Any ideas?
Hey Adam,
The script is actually lower than 20KB… Did you correctly download the script? Can you check the content? Looks like something went wrong during the download, I guess.
best,
Oliver
Hi Oliver,
Great work on this one.
Is it possible to use something similar to set a unique lockscreen image based off the similar principle?
Many thanks
Hey BBurrito,
Have a look at my GitHub repo, there is a version, which also sets the lockscreen and a version dedicated for lockscreen 👍
Best,
Oliver
Hi Oliver,
Great script! A lot of our new PC’s we’re deploying have high resolution screens that have Windows display settings automatically set to 125% scaling. It seems like this might be affecting the way the calculations in your script are being performed. So for a screen with 1920×1080 resolution, I’m seeing in the log file that it is detecting as 16:9 ratio (1536×864 resolution), which causes the 16×9 version of the wallpaper to be cut off at the bottom. Any suggestions on best way to handle this?
Hi Oliver! I’m quite a beginner in Intune management and I would like to push the corporate image to all the new computers. I modified as you said in the post, but nothing happens. The image still doesn’t change, and I don’t know where I’m wrong, I still get it – not applicable in Intune, any ideas?
Hi Daniel,
not applicable, means the script is never deployed to the device. This indicates something on the Intune side is wrong in regards to grouping or filtering. Have a look at the targeting/assignment once more.
best,
Oliver
Hey Oliver,
Great article, getting the below error though?
Invoke-WebRequest : BlobNotFoundThe specified blob does not exist.
RequestId:4f1bd764-001e-000a-1595-fe710f000000
Time:2022-11-22T17:09:25.7511200Z
At C:\Users\wmills\OneDrive – SLR Consulting Limited\SLR Branding\ApplySLRWallpaper.ps1:182 char:5
+ Invoke-WebRequest -Uri $url -OutFile $imagePath -TimeoutSec 10 -U …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand
What is the access level of the container? Did you configured it to Container or Blob to allow anonymous access?
Hi sir! “The specified resource does not exist” when I tried to visit the blobs URL but no issues when accessing directly to the files, is it something wrong with my storage account settings?
What about the access level? Did you configured it to Blob or Container?
Hi Oliver! Thanks for replying. I’ve tried with both blob and container but still no luck.
It worked when I directly accessing file URL but not when I try to access the container URL.
Can you please re-check if your container has blob anonymous level access and you have named the images correctly, these are the two prerequisites. Then it must work.