Configure Dynamic Wallpaper and Lock Screen Images Using Intune Win32 App

Overview

In an era where automation is a huge help for IT administrators, the task of changing wallpapers and lock screen backgrounds has become a real headache for many of us.

Administrators are constantly being asked to switch up wallpapers and lock screen backgrounds for special events like holidays or announcements. While this might seem like a small task to the average user, admins are often required to make changes on a monthly basis.

I work for a SaaS company where the majority of what we deploy is automated. Despite this, we still receive requests to update wallpapers for customers, which means adjusting our automation processes to accommodate these requests.

One of our new customers has a wide range of “personas” across different business units. They want to update the wallpaper for most personas monthly! While this is technically possible, what was once a “nice-to-have” option has now become a burdensome chore for the unlucky admin.

But not anymore!

Prerequisites

  • Access to uploading applications to Intune
  • Knowledge of using IntuneWinAppUtil to convert the Install.ps1 script to an .intunewin file.
  • A static URL for the wallpaper and/or the lockscreen background. This should be a publicly accessible URL, which means it can be hosted on a public Azure storage account, AWS storage, or even a public GitHub repository.
    • Note: Grant access to the marketing team for uploading files – it’ll be beneficial in the long run!

How does the dynamic wallpaper and lock screen win32 app work?

The application, which can be downloaded from my GitHub, allows administrators to package one application for both the wallpaper and the lock screen background, making it easy to set and forget.

The script is equipped with full error handling and logs to %programdata%\DynamicURL\Logs. It also stores downloaded images in %programdata%\DynamicURL\Images.

The Install.ps1 script checks for a static image URL to see if the image Etag (identifier for a version of the image) has changed. If the image was changed, the script will download the new image, set up a few registry keys, and then set the image as a new wallpaper or lock screen.

Details of Install.ps1:

The script is called with one or two functions, -DesktopImageUrl and/or -LockScreenImageUrl, if you’re calling it with -DesktopImageUrl, then you just need to specify the wallpaper URL. Something like
Install.ps1 -DesktopImageUrl "https://raw.githubusercontent.com/ahmadaoun/DynamicWallpaper/main/SampleImages/Desktop.png"

Similarly, the lockscreen background needs to be called with the URL. You can call one or both in the same scripts with something like
Install.ps1 -DesktopImageUrl "https://raw.githubusercontent.com/ahmadaoun/DynamicWallpaper/main/SampleImages/Desktop.png" -LockScreenImageUrl "https://raw.githubusercontent.com/ahmadaoun/DynamicWallpaper/main/SampleImages/LockScreen.png"

The below examples are for the desktop wallpaper function, but a similar function applies to the lockscreen background function.

The script will get the file Headers.Etag

$response = Invoke-WebRequest -Uri $DesktopImageUrl -Method Head -ErrorAction Stop
        if ($response.StatusCode -eq 200) {
            Write-Host "File found at $DesktopImageUrl"
        } else {
            Write-Error "File not found at $DesktopImageUrl (Status code: $($response.StatusCode))"
            return
        }

It checks if the hash exists in the registry path HKLM:\Software\DynamicWallpaper\ – on the first run it will obviously not find it, so it will download the image to %programdata%\DynamicWallpaper\ and then set the image accordingly.

It will then write the image hash and URL to the HKLM:\Software\DynamicWallpaper\ path. The URL is needed later for the detection.

if (-not (Test-Path $RegistryPath)) {
            New-Item -Path $RegistryPath -Force | Out-Null
            Download-Image -Url $DesktopImageUrl -Destination $DesktopImagePath
            Set-Wallpaper -DesktopImagePath $DesktopImagePath
            Update-RegistryKey -KeyName $DesktopRegistryKeyName -HashValue $DesktopImageHash
        } elseif ($CurrentDesktopImageHash -ne $DesktopImageHash) {
            Write-Host "Image has changed. Downloading..."
            Download-Image -Url $DesktopImageUrl -Destination $DesktopImagePath
            Set-Wallpaper -DesktopImagePath $DesktopImagePath
            Update-RegistryKey -KeyName $DesktopRegistryKeyName -HashValue $DesktopImageHash
        } else {
            Write-Host "Image has not changed."
        }

To set the image as a wallpaper or as a lockscreen background, the script will set the PersonalizationCSP accordingly.

$DesktopPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP"            if (-not (Test-Path -Path $DesktopPath)) 
{New-Item -Path $DesktopPath -Force | Out-Null}
            Set-ItemProperty -Path $DesktopPath -Name "DesktopImagePath" -Value $absolutePath
            Set-ItemProperty -Path $DesktopPath -Name "DesktopImageUrl" -Value $DesktopImageUrl
            Set-ItemProperty -Path $DesktopPath -Name "DesktopImageStatus" -Value 1

The Detect.ps1 script will check whether the registry keys for the DesktopImageURL and/or the LockScreenURL exist, if they do, then it will check the URL for the image Etag and cross check it with the DesktopImageHash and/or the LockScreenImageHash keys. If the Etags match the values in the registry, then it will return “Detected”, if they don’t, then the Install.ps1 will run again and set the new images as the wallpaper or the lockscreen background.

if ($DesktopImageUrl) {
    $DesktopImagetrue = $true
    $DesktopRegistryKeyName = "DesktopImageHash"
    $CurrentDesktopImageHash = (Get-ItemProperty -Path $RegistryPath -Name $DesktopRegistryKeyName -ErrorAction SilentlyContinue).$DesktopRegistryKeyName
    $DesktopImageHash = (Invoke-WebRequest -Uri $DesktopImageUrl -Method Head).Headers.ETag
    $DesktopImageHash = $DesktopImageHash -replace '^[^"]+"|"[^"]*$', ''

    # Compare hashes
    if ($CurrentDesktopImageHash -eq $DesktopImageHash) {
        $desktopSuccess = $true
    }
}

This is how it converts the $output from one or both functions to a single $output for detection purposes:

if ($DesktopImageUrl -and $LockScreenImageUrl) {
    if ($desktopSuccess -and $lockScreenSuccess) {
        $output = "Detected"
    }
} elseif ($LockScreenImageUrl) {
    if ($lockScreenSuccess) {
        $output = "Detected"
    }
} elseif ($DesktopImagetrue) {
    if ($desktopSuccess) {
        $output = "Detected"
    }
}
write-host $output

Summary

In short, with the DynamicWallpaper app, the marketing team can manage their own deployment of new wallpapers and lockscreen backgrounds. All they need is access to the storage account and to replace the existing image on with the new image making sure the name is the same so that the URL doesn’t change. And, within 8h (give or take 8h), the detection on the win32 app will run and the new image will get deployed.

Limitations

  • The desktop wallpaper requires a device reboot for it to apply.
  • The CSP settings used in this app are limited to Enterprise SKUs
  • When you create an app with a single function, such as setting a desktop wallpaper or lockscreen background, the app is restricted to that single function. If you want to add a second function later on, you will need to either create a new app that includes both functions with the install command, or create a separate app for the second function.
  • Files created by a system user in the %programdata% location are not editable by standard users, unless the user had pre-empted the app running and pre-created the image files before the app runs. In that case, the user would then have full read/write access to the files the app creates. Thanks @schenardie for the heads up!

How to setup the DynamicWallpaper app on Intune?

  1. Download the DynamicWallpaper script
  2. Download the IntuneWinAppUtil.exe
  3. Convert the Install.ps1 to Install.intunewin file
  4. Create a new Win32 app on Intune
  5. Select the Install.intunewin file
  6. Give the app a Name, Description, and Publisher
  7. Add any other details and click Next
  8. For the Install command add the below.
    Note: Change the URLs to your own URL
    %windir%\sysnative\windowspowershell\v1.0\powershell.exe -executionPolicy bypass -windowstyle hidden -file "./Install.ps1" -DesktopImageUrl "https://raw.githubusercontent.com/ahmadaoun/DynamicWallpaper/main/SampleImages/Desktop.png" -LockScreenImageUrl "https://raw.githubusercontent.com/ahmadaoun/DynamicWallpaper/main/SampleImages/LockScreen.png"
  9. You can type anything in the Uninstall command, you cannot leave it blank
  10. Click Next
  11. Add the requirements
  12. For detection, select Use a custom detection script
  13. Select the Detect.ps1 file you downloaded
  14. Leave the rest as default and click Next
  15. Add the assignments to your needs
  16. Click Next then Create

Future versions of the script will support uninstall commands. I shall update this post once done.

Published by

17 responses to “Configure Dynamic Wallpaper and Lock Screen Images Using Intune Win32 App”

  1. Navneet Singh Avatar

    Thanks for the script this is precisely what we are looking for. Just one question once we change the lockscreen or Wallpaper how the application will rerun and change it? Like once app installs with a wallpaper and later we want to change it. We can change it in Blob Storage but how come Application will kick in again on the machine where installation was success?

    Like

    1. Glad this helped you with your requirements, Navneet.

      Application detections (refresh cycle) by default run daily (24 hours) as per Microsoft’s documentation:

      In general, the report refreshes every seven days from the time of enrollment (not a weekly refresh for the entire tenant). The only exception to this refresh cycle for the Discovered apps report is application information collected through the Intune Management Extension for Win32 Apps, which is collected every 24 hours.

      If you change the lockscreen and/or the desktop wallpaper image, the change will be detected the next time the detection runs (within 24h) and it will detect the new image(s) Etag doesn’t match the old one, so it will trigger the app to install again and set the wallpaper.

      Hope this helps explain it.

      Like

      1. Navneet Singh Avatar

        Thanks for the reply. Also small question, the new jpg we want to upload should have same name as previous one or any other name we can choose, i am asking because while running the script we are adding the URL till the name of JPG. Also if uploaded new one, do we need to remove old one from the Blob storage?

        Like

      2. The new images don’t need to have the same name as the old one, but changing the image name would require you to change the URL in the install command of the app. This will obviously require access to Intune.
        The intent of this app was to allow the design and marketing team to publish new backgrounds without having to engage the IT team.
        If you’re adding a new image with a different name to the blob storage, then no need to delete the old one.

        Like

  2. Navneet Singh Avatar

    So we might have to tell the design and marketing team to upload the changes in background or lockscreen with same name as before. This is the only way they dont have to get to IT. If they upload the image with new name than they have to contact the IT to make changes in Intune. With changes to old image but same name will generate the new Ehash?

    Like

    1. Correct. The Etag is the hash of the file; and when a new file with the same name is uploaded, it will replace the old file and while the name/URL are the same, the Etag is different.

      Like

      1. Navneet Singh Avatar

        Great thanks for response, i will implement and send the communications to marketing to upload file with same name and delete old one.

        Like

  3. we are receiving this error The application was not detected after installation completed successfully (0x87D1041C), even thought the detection script has been put in place

    Like

    1. sorry I missed this. have you been able to resolve it?

      Like

      1. Hello,
        I am unable to reply through the website not opening, I wasn’t able to fix this issue.

        Best regards,
        Charbel SEIF
        Business Application Specialist


        M. Ezzat Jallad & Fils S.A.L. | Zouk Mkayel | P.O.Box 110208 | Postal Code 1107 2020, Riad Solh, Beirut, Lebanon
        T: +961.9.212077 (Ext. 202) | M: +961.70.702229 | F: +961.9.212073 |cseif@jallad.com.lb|cseif@jallad.com.lb | http://www.jalladgroup.comhttp://www.jalladgroup.com/
        [image008] https://www.facebook.com/jalladgroup/ [image010] https://www.linkedin.com/company/10442086/ [image001] https://www.youtube.com/channel/UC_h5to1-opadtAMVpciojuQ/videos

        Like

      2. I was switching DNS, bad timing 🙂 – website should be back online now.
        Are you trying to setup the desktop, lockscreen or both?
        Either way, the detect.ps1 uses registry for detection.
        Check if the registry entries exist under: `HKLM:\Software\DynamicWallpaper\`

        There should be `DesktopImageUrl` and/or `LockScreenURL` depending what you’re setting up.

        happy for you to share screenshots with me if you need any more help.

        Like

  4. I’m seeing the same issue where the “app” doesn’t appear to be installing as no files or reg keys are created but it does work manually. Any known issues?

    Like

    1. Hi Rob, I have updated the script for better error handling so you can capture logs under %programdata%\DynamicWallpaper\Logs
      I have also updated the README.md file as there was a type in the install parameters
      You need to call Install.ps1 rather than ".\Install.ps1"

      Let me know if you are still experiencing any issues.

      Like

      1. Nothing is logged, its like the PowerShell script hasn’t been executed. Logging though the Intune logs it not shedding much light but I’m still learning my way around Intune, more use to SCCM.

        Like

  5. I’m seeing, Powershell script is failed to execute errors within the Intune management logs on the machine. Reviewing event viewer logs under Microsoft-Windows-PowerShell/Operational I can see the script has been executed and logged along with the detection script. Very odd.

    Like

    1. did you get a chance to download the new code in the install.ps1 and package the new one?

      Like

  6. Yes this is with your updated script, running manually is fine just not as a deployment package. No logs get created which is very frustrating.

    Like

Leave a reply to Charbel Seif Cancel reply