Featured image of post Corporate Lockscreen Deployment

Corporate Lockscreen Deployment

Setting the background and lockscreen image with PowerShell, plus a bonus; Using PowerShell to select a file through a file browser.

So, lets start checking off some of the goals outlined in my previous post…

At the MSP where I work, we configure a fair amount of Windows computers (like many others in the industry).

I have already created a configuration script that does most of the heavy lifting. This script is due a massive overhaul but this can wait. For now, I need to create a function that sets the background wallpaper and lockscreen images for all users.

Previously when I have looked into this, I have come across ‘Personalization CSP’ in Microsoft documentation but hit a roadblock when i found that this was restricted to Education and Enterprise SKUs only.

I recently saw in a post on Reddit (I dont remember what post but if i find it i will link here) that this is no longer the case. Looking at the documentation here: Microsoft - Personalisation CSP, the post was correct.

Lets get started then…

Unfortunately, this documentation does not include any reference on application via registry but luckily, a quick Google search tells me what keys and values will be needed. So thats half the battle done.

First off, we need to create the following registry key: "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP"

1
2
# Create PersonalizationCSP Registry Key
New-Item HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP -Force

Next, we’ll need to declare some variables to contain the registry key path and image files.

1
2
3
4
# Declare Variables 
$RegPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP"
$BackgroundImage = "C:\Images\Background.png"
$LockScreenImage = "C:\Images\Background.png"

Now, we can set the registry key values. We’ll start with the lockscreen values.

1
2
3
4
# Set Lockscreen Registry Keys
New-ItemProperty -Path $RegPath -Name LockScreenImagePath -Value $LockScreenImage -PropertyType String -Force | Out-Null
New-ItemProperty -Path $RegPath -Name LockScreenImageUrl -Value $LockScreenImage -PropertyType String -Force | Out-Null
New-ItemProperty -Path $RegPath -Name LockScreenImageStatus -Value 1 -PropertyType DWORD -Force | Out-Null

And finally, the desktop background image values.

1
2
3
4
#Background Wallpaper Registry Keys
New-ItemProperty -Path $RegPath -Name DesktopImagePath -Value $Backgroundimage -PropertyType String -Force | Out-Null
New-ItemProperty -Path $RegPath -Name DesktopImageUrl -Value $Backgroundimage -PropertyType String -Force | Out-Null
New-ItemProperty -Path $RegPath -Name DesktopImageStatus -Value 1 -PropertyType DWORD -Force | Out-Null

To finish this up, we can bundle all these components together to form a simple function that we can implement in the configuration script mentioned earlier.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
function Set-CorporateLockScreen{
# Create PersonalizationCSP Registry Key
New-Item HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP -Force  

# Declare Variables
$RegPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP"
$BackgroundImage = "C:\Images\Background.png"
$LockScreenImage = "C:\Images\Background.png"

# Set Lockscreen Registry Keys
New-ItemProperty -Path $RegPath -Name LockScreenImagePath -Value $LockScreenImage -PropertyType String -Force | Out-Null
New-ItemProperty -Path $RegPath -Name LockScreenImageUrl -Value $LockScreenImage -PropertyType String -Force | Out-Null
New-ItemProperty -Path $RegPath -Name LockScreenImageStatus -Value 1 -PropertyType DWORD -Force | Out-Null

#Background Wallpaper Registry Keys
New-ItemProperty -Path $RegPath -Name DesktopImagePath -Value $Backgroundimage -PropertyType String -Force | Out-Null
New-ItemProperty -Path $RegPath -Name DesktopImageUrl -Value $Backgroundimage -PropertyType String -Force | Out-Null
New-ItemProperty -Path $RegPath -Name DesktopImageStatus -Value 1 -PropertyType DWORD -Force | Out-Null
}

Calling this function in a test environment and then restarting the endpoint, I can see the specified images have been applied as the background wallpaper & lockscreen as desired.

This does prevent standard users from changing their background and lockscreens, so i may look for a less restrictive way to achieve this but for now, this’ll do.


Easy enough, lets go for bonus points…

To save from having to name our image files a generic name for all our clients, it would be helpfult to be able to declare the image “On the fly”. If this can be achieved with a familiar file explorer “Browse” window, even better.

Back to Google I go.

Again, after a short search I came across an article that appears to fit the bill: 4Sysops - How to create an open file dialog with PowerShell

So according to the article, to start off, we will need to load the System.Windows.Forms assembly.

1
2
# Load the System.Windows.Forms assembly 
Add-Type -AssemblyName System.Windows.Forms

Next, we will create a Open File Dialog instance.

1
2
# Instantiate an OpenFileDialog object using New-Object.
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ InitialDirectory = "C:\" }

If we want, we can even restrict the file type that can be selected.

1
2
3
4
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ 
    InitialDirectory = [Environment]::GetFolderPath('Desktop') 
    Filter = 'Documents (*.docx)|*.docx|SpreadSheet (*.xlsx)|*.xlsx'
}

To be more appropriate to our needs, lets filter to images instead.

1
2
3
4
$FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ 
    InitialDirectory = [Environment]::GetFolderPath('Desktop') 
    Filter = 'Images (*.jpg;*.jpeg;*.png;*.bmp)|*.jpg;*.jpeg;*.png;*.bmp'
}

Finally, we just need to display the dialog instance.

1
2
# Display the Browse dialog
$null = $FileBrowser.ShowDialog() 

We can then, yet again wrap this into a simple function which can be implemented into scripts as needed.

1
2
3
4
5
6
7
8
9
function Get-OpenFileDialog{
    # Load the System.Windows.Forms assembly 
    Add-Type -AssemblyName System.Windows.Forms
    # Instantiate an OpenFileDialog object using New-Object.
    $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ InitialDirectory = "C:\" }
    # Display the Browse dialog
    $null = $FileBrowser.ShowDialog() 
    $SelectedFile = ($FileBrowser.FileName)
}

And there we have it. When this is ran, the familiar browse or open dialog is produced. A file can then be selected, which will be stored in OpenFileDialog.

If we piece these two functions together, we have a working solution for deploying corporate lock screen and desktop images, which we can implement into our main Windows configuration script.

Something like this should do…

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
function Get-OpenFileDialog{
# Load the System.Windows.Forms assembly.
    Add-Type -AssemblyName System.Windows.Forms
# Instantiate an OpenFileDialog object using New-Object.
    $FileBrowser = New-Object System.Windows.Forms.OpenFileDialog -Property @{ 
        InitialDirectory = "C:\"
        Filter = 'Images (*.jpg;*.jpeg;*.png;*.bmp)|*.jpg;*.jpeg;*.png;*.bmp'
    }
# Display the Browse dialog.
    $null = $FileBrowser.ShowDialog()
    $SelectedFile = ($FileBrowser.FileName)
    $SelectedFile
}

function Set-CorporateLockScreen{
# Create PersonalizationCSP Registry Key.
New-Item HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP -Force | Out-Null
# Declare Variables.
    $RegPath = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\PersonalizationCSP"
    Write-Host "Please Select an Image File for the Background Image."
    $BackgroundImage = (Get-OpenFileDialog)
    Write-Host "Please Select an Image File for the Lockscreen Image."
    $LockScreenImage = (Get-OpenFileDialog)
    # Set Lockscreen Registry Keys
    New-ItemProperty -Path $RegPath -Name LockScreenImagePath -Value $LockScreenImage -PropertyType String -Force | Out-Null
    New-ItemProperty -Path $RegPath -Name LockScreenImageUrl -Value $LockScreenImage -PropertyType String -Force | Out-Null
    New-ItemProperty -Path $RegPath -Name LockScreenImageStatus -Value 1 -PropertyType DWORD -Force | Out-Null
    #Background Wallpaper Registry Keys
    New-ItemProperty -Path $RegPath -Name DesktopImagePath -Value $Backgroundimage -PropertyType String -Force | Out-Null
    New-ItemProperty -Path $RegPath -Name DesktopImageUrl -Value $Backgroundimage -PropertyType String -Force | Out-Null
    New-ItemProperty -Path $RegPath -Name DesktopImageStatus -Value 1 -PropertyType DWORD -Force | Out-Null
}

After adding this to our main configuration script, we can call the function Set-CorporateLockScreen in the execution section. We will then be prompted to select the files for the lockscreen and background and finally the registry keys will be applied.

Part of the standard workflow (when using the script I created some time ago) is already to restart the endpoint manualy upon script completion. As such, we do not need to consider this in these functions. If we were implementing these functions elsewhere, a system restart would need to be factored in.

Automate and script away - Happy Shellcode Saturday!

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy