Finding wallpaper locations in Windows 7 and later

Update (2019-10-30): The scripts were moved to GitHub.

This article introduces two PowerShell scripts that help you find the wallpaper location in Windows 7 and later.

View of Garachico, Tenerife, Spain by Diego Delso
View of Garachico, Tenerife, Spain by Diego Delso



Previously, The WinHelpOnline Blog published two scripts in the VBScript language, one for retrieving the location of Wallpaper on Windows 7 (4 February 2010) and one for doing so on Windows 8.x (25 October 2013). These scripts, however, have a problem: If there is a non-English character (e.g.  Chinese characters) in the file name path, they potentially fail. Although Windows innately supports Unicode, VBScript doesn’t. Only programs based on .NET Framework are Unicode-compliant by nature. Fortunately, Windows PowerShell is built on .NET Framework and benefits from innate Unicode support. So, all I had to do was to rewrite the script in the PowerShell language.

Windows 7

In Windows 7, the wallpaper’s location is stored in the Windows Registry. Here is the PowerShell script, with error detection code stripped out for readability. (You can find an operational script with error detection code at the bottom of this article.)

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Windows.Forms.Application]::EnableVisualStyles()

$WallpaperSource=(Get-ItemProperty "HKCU:\Software\Microsoft\Internet Explorer\Desktop\General" WallpaperSource).WallpaperSource

$result=[System.Windows.Forms.MessageBox]::Show("Wallpaper location: `r$WallpaperSource`r`rLaunch Explorer?", "Script", "YesNo", "Asterisk");
if ($result -eq "Yes")
{
    Start-Process explorer.exe -ArgumentList "/select,`"$WallpaperSource`""
}

Lines 1 and 2 load necessary .NET components for showing the graphical user interface in PowerShell. Line 4 does most of the work: It browses the Registry, retrieves the location of the wallpaper and stores it in memory. Lines 6 through 10 show a dialog box that displays the location and asks whether the user wants to launch Windows Explorer to browse that location.

Windows 8 and later

Starting with Windows 8, things have become a little tricky. The location of wallpaper is in the Registry but not in plain text. It needs to be decoded. Here is how to do it:

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[System.Windows.Forms.Application]::EnableVisualStyles()

$TranscodedImageCache=(Get-ItemProperty 'HKCU:\Control Panel\Desktop' TranscodedImageCache -ErrorAction Stop).TranscodedImageCache

$Path_Start_Delta = 24
$Path_End_Delta   = $TranscodedImageCache.length-1
for ($i = $Path_Start_Delta; $i -lt ($TranscodedImageCache.length); $i += 2)
{
    if ($TranscodedImageCache[($i+2)..($i+3)] -eq 0) {
        $Path_End_Delta=$i + 1;
        Break;
    }
}
$UnicodeObject=New-Object System.Text.UnicodeEncoding
$WallpaperSource=$UnicodeObject.GetString($TranscodedImageCache[$Path_Start_Delta..$Path_End_Delta]);

$result=[System.Windows.Forms.MessageBox]::Show("Wallpaper location: `r$WallpaperSource`r`rLaunch Explorer?", "Script", "YesNo", "Asterisk");
if ($result -eq "Yes")
{
    Start-Process explorer.exe -ArgumentList "/select,`"$WallpaperSource`""
}

As you can see, the size of the add code that is significant. Lines 4 through 16 replace the function of the former line 4 in our previous script. Until line 4, everything is exactly the same as in Windows 7 script; only this time, what line 4 receives from Windows Registry is raw binary data. The wallpaper path is inside this array. Our script must pull it out.

The decoding starts at line 7. We know that the path starts at byte #24. (Remember: The first byte is byte #0, not #1.) Every character in the path occupies two bytes, so the first character is in bytes #24 and #25. But where does the path end? Apparently, the length of the path is not specified, so, our script must keep putting characters together one-by-one, until it reaches one duo of bytes that both contain zero. (As much as I hate null-terminated strings, it is indeed fortunate that NUL character is not a valid file name character in Windows.) Once the end of the path is found, we will have System.Text.UnicodeEncoding decode that portion of raw binary data into lovely human-readable text.

Starting at line 18, the code begins to look familiar.

Complete scripts

Here are two links for completed scripts:

Please note that PowerShell is very strict about running scripts, especially those that are not digitally-signed. Be sure to unblock these scripts before running them and tell PowerShell to allow execution of scripts in general.

I have implemented some error checking in these script. They check your Windows version first. But overall, they are not stress-tested. In fact, I am not equipped with a an entire fleet of computers dedicated to stress-testing.

5 thoughts on “Finding wallpaper locations in Windows 7 and later

  1. John, Can this script be updated for Windows 10… the version check code.

    Like

  2. John just to let you know that your amazing script made my life so much easier to find bugged wallpaper !! I LOVE it thanks you for this. Just a multi screen support would make it perfect !

    Like

Leave a comment (Markdown syntax accepted)

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: