Finding wallpaper location in Windows 7 and Windows 8

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

View of Garachico, Tenerife, Spain by Diego Delso

View of Garachico, Tenerife, Spain by Diego Delso



Previously, The WinHelpOnline Blog published two scripts in VBScript, 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. Windows is unfortunately creature, in that it has a Unicode-supporting infrastructure with components on top that defy Unicode. 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 PowerShell language.

Windows 7

In Windows 7, the wallpaper’s location is stored in Windows Registry. All that a script have to do is to retrieve it. 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`""
}

Line 1 and 2 load necessary .NET components for showing 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 just show a dialog box that displays the location and ask whether the user wants to launch Windows Explorer and browse that location.

Windows 8

Windows 8 is a little tricky. It does store the location of wallpaper in the Registry but not in plain text. Instead, it is stored in raw binary form that needs to be decoded. The following simplified piece of code explains.

[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 amount code that is added is massive. Lines 4 through 16 replace the function of 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, in which computer speak fluently; hence Windows 8′s performance. The wallpaper path is inside this array. Our script must pull it out.

Processing 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, things start to look like the Windows 7 script again. This line just displays a dialog box containing the path and asks the user if he wants to have File Explorer take him to it.

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. Please 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.

Maybe I will have another article about how to do this but it is not like you are left alone: PowerShell itself tells you what to do.

About these ads

Posted on 9 December 2013, in Software Development, Windows Administration and tagged , , , , , , , , , , . Bookmark the permalink. 2 Comments.

Leave a comment

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 )

Google+ photo

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

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: