Deploying a consistent desktop background across an organization not only reinforces brand identity but also enhances the overall user experience.
Traditionally, achieving this through Microsoft Intune has involved methods such as deploying Win32 applications, configuring profiles, or hosting images on the cloud. However, these approaches can introduce complexities and dependencies.
In this guide, we present an alternative solution: utilizing a PowerShell script with an embedded Base64-encoded image to set the desktop background. This method offers a self-contained deployment, eliminating the need for external image hosting and simplifying the process. By embedding the image directly within the script, we can streamline the deployment, enhance security by reducing external dependencies, and ensure that the desired background is applied uniformly across all targeted devices.
Throughout this post, we will walk you through the steps to convert your desired image into a Base64 string, create a PowerShell script to decode and apply the image as the desktop background, and deploy this script using Intune. This approach ensures a seamless and secure method to standardize desktop backgrounds within your organization.

Table of Contents
Understanding the Concept
Deploying a standardized desktop background across an organization using Microsoft Intune typically involves hosting the desired image on a cloud storage and configuring device profiles to apply the wallpaper from that location. Other approach would be to use a Win32 application, to deploy the image to the devices and copy it to the correct location, to apply the background. However, these approaches can introduce challenges, such as dependency on external hosting solutions and potential security concerns.
An alternative method involves embedding the image directly within a PowerShell script using Base64 encoding. This technique allows the image to be included as a text string within the script, which is then decoded and applied as the desktop background on target devices.
Advantages of This Approach:
- Self-Contained Deployment: By embedding the image within the script, there is no need for external image hosting, simplifying the deployment process.
- Enhanced Security: Eliminating external dependencies reduces potential security risks associated with accessing resources over the internet.
- Offline Accessibility: Since the image is part of the script, devices can apply the wallpaper without requiring immediate communication with the hosting provider.
Implementation Overview:
- Convert the Image to Base64: Use PowerShell to read the image file and convert its binary data into a Base64-encoded string.
- Create the Deployment Script: Develop a PowerShell script that includes the Base64 string, decodes it back into an image file on the target device, and sets it as the desktop background.
- Deploy via Intune: Utilize Intune’s Remediations or Platform Scripts capabilities to distribute and execute the PowerShell script across the organization’s devices.
This method offers a streamlined and secure alternative to traditional approaches, ensuring a consistent desktop environment without relying on external resources.
Step 1: Convert the Image to Base64
As described already in one of my previous blogs, we can utilize a PowerShell script (can also be found here) to convert an image (it works with jpeg, png, ico and webp image files) to a Base64 string.
You can find all the PowerShell scripts in my GitHub repo.
# Start transcript for logging
$LogPath = "C:\Temp\ImageToBase64Conversion.log"
Start-Transcript -Path $LogPath -Append
function Convert-ImageToBase64 {
param (
[Parameter(Mandatory=$true)]
[string]$ImagePath
)
Write-Host "Converting image to Base64: $ImagePath"
if (-not (Test-Path $ImagePath)) {
throw "File not found: $ImagePath"
}
$imageBytes = [System.IO.File]::ReadAllBytes($ImagePath)
$base64String = [System.Convert]::ToBase64String($imageBytes)
Write-Host "Conversion completed. Base64 string length: $($base64String.Length)"
return $base64String
}
try {
# Prompt for image path
$imagePath = Read-Host "Enter the full path to your image file (e.g., C:\Path\To\Your\Image.ico,png or jpeg or webp)"
# Convert image to Base64
$base64String = Convert-ImageToBase64 -ImagePath $imagePath
# Prompt for output option
$outputChoice = Read-Host "Do you want to (1) Display the Base64 string or (2) Save it to a file? Enter 1 or 2"
switch ($outputChoice) {
"1" {
Write-Host "`nBase64 string:"
Write-Host $base64String
}
"2" {
$outputPath = Read-Host "Enter the full path where you want to save the Base64 string (e.g., C:\Path\To\Output\base64output.txt)"
$base64String | Out-File -FilePath $outputPath
Write-Host "Base64 string saved to: $outputPath"
}
default {
Write-Host "Invalid choice. The Base64 string will be displayed:"
Write-Host $base64String
}
}
Write-Host "`nScript execution completed. Log file location: $LogPath"
} catch {
Write-Error "An error occurred: $_"
} finally {
Stop-Transcript
}
Read-Host "Press Enter to exit"
This PowerShell script is a simple utility that converts an image file into a Base64-encoded string, which we can later embed in our wallpaper deployment script. It starts by logging all activity to a file, then prompts us to provide the path to the image. Once the file is validated, it reads the image content, converts it to Base64, and gives us the option to either display the result in the console or save it to a text file. It includes basic error handling and ensures the process is logged and neatly wrapped up.
Step 2: Deploy the image
Now that we’ve successfully converted our image into a Base64 string, the next step is to bring it to life on our users’ desktops. To do that, we’ll create a PowerShell script that can be deployed a Win32 package.
Unfortunately most of the times here we cannot use Intune Remediations or Platform scripts since the total characters of the script would be more than 200000 bytes. This is the negative of using such an approach since the conversion of the image to Base64 will be a very very long string.
The concept is simple: the script will decode the Base64 string back into an image file, save it locally on the target device, and then set that image as the desktop background using built-in Windows methods.
This approach ensures that we don’t need any external hosting or configuration profiles. Everything is self-contained within the script—just copy, deploy, and go.
In this section, we’ll walk through the actual PowerShell script that handles the conversion, file saving, and background application. But first, let’s quickly outline what the script will do:
- Create a target folder (if it doesn’t exist) for storing the wallpaper locally.
- Decode the embedded Base64 string and save it as an image file (e.g.,
.jpg
). - Apply the image as the user’s desktop background using registry settings and a refresh command.
- The background image will be applied the next time a user logs in.
This lightweight method is reliable, fast to deploy, and clean.
Script to apply the desktop background
# Initialize the variable for collecting log messages
$script:intuneOutput = ""
# Define the LogMessage function
function LogMessage {
param (
[string]$message
)
Write-Host $message
$script:intuneOutput += $message + "`n"
}
# Define variables
$LogPath = "C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\DeployWallpaper.log"
$WallpaperDirectory = "C:\Temp\IntuneWallpaper"
$WallpaperPath = "$WallpaperDirectory\CorporateWallpaper.jpg"
$RegKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP"
$Base64Image = "YOUR BASE 64 STRING"
# Start logging
Start-Transcript -Path $LogPath -Append
LogMessage "Script execution started."
try {
# Ensure the directory exists
if (-not (Test-Path -Path $WallpaperDirectory)) {
New-Item -Path $WallpaperDirectory -ItemType Directory -ErrorAction Stop -Force
LogMessage "Created directory: $WallpaperDirectory"
} else {
LogMessage "Directory already exists: $WallpaperDirectory"
}
# Decode the Base64 string to bytes
LogMessage "Decoding Base64 string to byte array."
$ImageBytes = [Convert]::FromBase64String($Base64Image)
# Write the bytes to create the image file
[System.IO.File]::WriteAllBytes($WallpaperPath, $ImageBytes)
LogMessage "Wallpaper image saved to: $WallpaperPath"
# Ensure the registry key exists
if (-not (Test-Path $RegKeyPath)) {
New-Item -Path $RegKeyPath -ErrorAction Stop -Force | Out-Null
LogMessage "Created registry key: $RegKeyPath"
} else {
LogMessage "Registry key already exists: $RegKeyPath"
}
# Set the registry values
New-ItemProperty -Path $RegKeyPath -Name "DesktopImagePath" -Value $WallpaperPath -PropertyType String -ErrorAction Stop -Force | Out-Null
New-ItemProperty -Path $RegKeyPath -Name "DesktopImageStatus" -Value 1 -PropertyType DWord -ErrorAction Stop -Force | Out-Null
LogMessage "Updated registry with new wallpaper path and status."
# Refresh the desktop background using SystemParametersInfo
# THIS PART does not work when the script is executed at system context, but I leave it here for any future references
# LogMessage "Attempting to refresh desktop wallpaper."
# Add-Type @"
# using System;
# using System.Runtime.InteropServices;
# public class Wallpaper {
# [DllImport("user32.dll", CharSet = CharSet.Auto)]
# public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
# }
# "@
# [Wallpaper]::SystemParametersInfo(0x0014, 0, $WallpaperPath, 0x0001)
# LogMessage "Desktop background refreshed."
} catch {
LogMessage "An error occurred during execution: $_"
} finally {
Stop-Transcript
LogMessage "Script execution completed."
}
This script handles a few key technical steps behind the scenes to make the desktop background deployment seamless. One important part is the decoding of the Base64 string using [Convert]::FromBase64String()
—this transforms the encoded image data back into its binary form so it can be written as a .jpg
file. Once decoded, the script writes the image to a specific folder using [System.IO.File]::WriteAllBytes()
, effectively recreating the wallpaper locally on the machine. Another subtle but crucial section is the registry configuration under HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP
. This is where the script sets DesktopImagePath
and DesktopImageStatus
, which are necessary for Windows to recognize and apply the image as a managed background.
Script to remove the desktop background
# Initialize the variable for collecting log messages
$script:intuneOutput = ""
# Define the LogMessage function
function LogMessage {
param (
[string]$message
)
Write-Host $message
$script:intuneOutput += $message + "`n"
}
# Define variables
$LogPath = "C:\ProgramData\Microsoft\IntuneManagementExtension\Logs\RemoveWallpaper.log"
$WallpaperDirectory = "C:\Temp\IntuneWallpaper"
$WallpaperPath = "$WallpaperDirectory\CorporateWallpaper.jpg"
$RegKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP"
# Start logging
Start-Transcript -Path $LogPath -Append
LogMessage "Wallpaper removal script execution started."
try {
# Remove the wallpaper file if it exists
if (Test-Path -Path $WallpaperPath) {
Remove-Item -Path $WallpaperPath -Force
LogMessage "Wallpaper file removed: $WallpaperPath"
} else {
LogMessage "Wallpaper file not found at: $WallpaperPath"
}
# Optionally remove the wallpaper directory if empty
if ((Test-Path $WallpaperDirectory) -and ((Get-ChildItem -Path $WallpaperDirectory).Count -eq 0)) {
Remove-Item -Path $WallpaperDirectory -Force
LogMessage "Wallpaper directory removed: $WallpaperDirectory"
}
# Remove registry values if they exist
if (Test-Path $RegKeyPath) {
$properties = Get-ItemProperty -Path $RegKeyPath
if ($properties.DesktopImagePath -or $properties.DesktopImageStatus) {
Remove-ItemProperty -Path $RegKeyPath -Name "DesktopImagePath" -ErrorAction SilentlyContinue
Remove-ItemProperty -Path $RegKeyPath -Name "DesktopImageStatus" -ErrorAction SilentlyContinue
LogMessage "Registry values removed from: $RegKeyPath"
} else {
LogMessage "No wallpaper-related registry values found to remove."
}
} else {
LogMessage "Registry key not found: $RegKeyPath"
}
# Refresh the desktop to clear the wallpaper
# THIS PART does not work when the script is executed at system context, but I leave it here for any future references
# LogMessage "Refreshing desktop to clear wallpaper."
# Add-Type @"
# using System;
# using System.Runtime.InteropServices;
# public class Wallpaper {
# [DllImport("user32.dll", CharSet = CharSet.Auto)]
# public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
# }
# "@
# [Wallpaper]::SystemParametersInfo(0x0014, 0, "", 0x0001)
# LogMessage "Desktop background cleared."
} catch {
LogMessage "An error occurred during wallpaper removal: $_"
} finally {
Stop-Transcript
LogMessage "Script execution completed."
}
This script is designed to cleanly remove a previously deployed desktop wallpaper, along with its related configuration. One key element is the conditional cleanup of the wallpaper directory—after deleting the image, it checks if the folder is empty using (Get-ChildItem).Count
and removes it only if needed, preventing unnecessary leftover directories. The script also inspects the PersonalizationCSP
registry key and specifically targets the DesktopImagePath
and DesktopImageStatus
values, removing them only if they exist. This makes it safe to run even if the wallpaper wasn’t deployed.
By deploying and running the above script using a Win32 package you are able to apply the desktop background easily without any external dependencies.
One important note about this approach is that setting the wallpaper through the PersonalizationCSP registry keys effectively locks the background. Windows considers it a managed setting, meaning the user will no longer be able to change their wallpaper through the normal personalization settings—those options will appear greyed out.
If at any point you want to give users back control over their desktop background, you’ll need to remove the DesktopImagePath and DesktopImageStatus registry values under the PersonalizationCSP key. Our removal script already takes care of this, making it easy to revert the device to an unmanaged state where users are free to personalize their background again.
Step 3: Deployment
Now let’s create an Intune package to deploy the background.
First we have to package the script using the Microsoft Win32 Content Prep Tool (which can be found here).

Make sure to include both the scripts that applies and removes the background.
After that create we have to create the app in Intune.


One thing to keep in mind: when deploying via Intune as System, the script won’t be able to directly refresh the user’s desktop. This is because it’s running in a background session that doesn’t interact with the user’s desktop UI. The wallpaper is correctly configured and ready—but won’t visually apply until the user logs off/on, restarts Explorer, or until we run a lightweight follow-up script in the user context. So while the background is technically set, seeing it may require a small nudge. In this case we will just wait for the user to log off or restart the device.
Use the below as install and uninstall commands:
- Install Command: %windir%\sysnative\WindowsPowerShell\v1.0\powershell.exe -Executionpolicy Bypass .\applyBackground.ps1
- Uninstall Command: %windir%\sysnative\WindowsPowerShell\v1.0\powershell.exe -Executionpolicy Bypass .\removeBackground.ps1
At this point I highly recommend going through the below blog posts to fully understand the difference between the x86 and x64 PowerShell and how to launch each one of them using Intune (you will thank me later):
– The Sysnative 64 bit Witch Project by Rudy Ooms
– Make Registry Changes with Intune Win32 Apps by Gannon Novak
– Sysnative folder in Windows 64-bit explained by Anand Khanse (TheWindowsClud)

As detection script we are going to use 2 conditions for the 2 registry values that we are creating with the script:
- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP -> DesktopImagePath

- HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP -> DesktopImageStatus

Assign the app to the appropriate groups and create it.
Step 4: End-User Experience
The user will not see a specific notification and will not be disturbed. The only thing that will happen is (at the next login or restart), a new desktop background will be applied.

Final Verdict
Concluding this post, we’ve successfully managed to deploy a desktop background to our managed devices using nothing more than a PowerShell script and a Base64-encoded image. This method is clean, self-contained, and efficient. I personally like this approach because it avoids the overhead of bundling image files, uploading them to cloud storage, or creating complex Win32 packages. Instead, we simply convert the image to a Base64 string, embed it in the script, and let PowerShell do the rest.
Not only does this keep things lightweight, but it also reduces external dependencies, improves security, and gives us full control over the deployment process. Plus, by leveraging the PersonalizationCSP
registry settings, we ensure that the background is enforced consistently across devices.
Of course, with great power comes a bit of trade-off—the wallpaper is considered managed, so users can’t change it unless we explicitly remove those registry keys. But that can easily be handled with the removal script we built alongside the deployment.
In the end, this is a flexible and scalable solution, especially for environments where branding and consistency matter. Whether you’re managing 10 or 10,000 devices, this method will serve you well.
References and Documentation
- Win32 app management in Microsoft Intune
- Prepare Win32 app content for upload
- Microsoft-Win32-Content-Prep-Tool
Other Interesting Posts