Hyper Expert /Blog
About
Archives

PowerShell script to download Bing’s daily image as a wallpaper

Update: Python way for Mac posted here

There are few ways you can download Bing’s daily image and set it up as your wallpaper. The easiest way at the time of writing this post is to download Bing Desktop program by Microsoft. Or, you can just head over to Bing.com and download the image manually if you do not want to install more bloatware on your computer. Lastly, if you are like me, create a PowerShell script to automate downloading Bing’s daily image for you and set it up as your wallpaper without having to install any programs.

Jump to the script download at the end of this post if you wish to skip all the technical details.

Bing has an XML page that changes daily reflecting the wallpaper name, region, and resolution. Luckily for us, we can have PowerShell parse that XML info and download the Bing image for us.

First of, if you just want a simple script to download the latest Bing image to your computer, use this:
Note: Make sure you create a “Bing Wallpaper” folder inside your “Pictures” folder. This is where the Bing image will be downloaded

$Market = "en-US"
$Resolution = "1920x1080"
$ImageFileName = "wallpaper.jpg"
$DownloadDirectory = "$env:USERPROFILE\Pictures\Bing Wallpaper"
$BingImageFullPath = "$($DownloadDirectory)\$($ImageFileName)"

New-Item -ItemType directory -Path $DownloadDirectory

[ xml ]$Bingxml = (New-Object System.Net.WebClient).DownloadString("http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=$($Market)");
$ImageUrl = "http://www.bing.com$($Bingxml.images.image.urlBase)_$($Resolution).jpg";

Invoke-WebRequest -UseBasicParsing -Uri $ImageUrl -OutFile "$BingImageFullPath";

Save the above code as “Get-Bing.ps1” or any other name you like. Launch PowerShell and execute the script .\Get-Bing.ps1

The above code simply goes to Bing’s XML page, finds the Bing image urlBase, adds the approperiate resolution and download the image. Very simple! And it can be simplified even more if needed be. This maybe all you need if you only want to manually download Bing’s daily image and move on. However, this code does not apply the image as a wallpaper.

At the very top of the script, you see parameters like market, resolution, file name, etc. Bing sometimes has different images for different geographical regions. There you can tell the script which region you want to download from. The available regions are: “en-US”,”zh-CN”,”ja-JP”,”en-AU”,”en-UK”,”de-DE”,”en-NZ”.

Resolution can also be changed to one of the following: 1366×768, 1920×1080, 1920×1200
1920×1080 is the highest resolution you can request WITHOUT the Bing logo watermark on it. Any higher resolution will have “Bing” logo watermark on the bottom right of the image.

$ImageFileName and $DownloadDirectory can be changed to anything you want. $ImageDirectory is where you want Bing image to download – In our case, this will be a folder called “Bing Wallpaper” inside your “Pictures” folder. $ImageFileName is what the downloaded Bing image will be called.

1920×1080 is the highest resolution you can request WITHOUT the Bing logo watermark on it

Setting downloaded Bing image as wallpaper

So far, everything is good and we get our Bing image downloaded to our desired location. We can also have the script set the downloaded image as a wallpaper immediately after download.

Note: the code below includes the code above plus new code

$Market = "en-US"
$Resolution = "1920x1080"
$ImageFileName = "wallpaper.jpg"
$DownloadDirectory = "$env:USERPROFILE\Pictures\Bing Wallpaper"
$BingImageFullPath = "$($DownloadDirectory)\$($ImageFileName)"

New-Item -ItemType directory -Path $DownloadDirectory

[ xml ]$Bingxml = (New-Object System.Net.WebClient).DownloadString("http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=$($Market)");
$ImageUrl = "http://www.bing.com$($Bingxml.images.image.urlBase)_$($Resolution).jpg";

Invoke-WebRequest -UseBasicParsing -Uri $ImageUrl -OutFile "$BingImageFullPath";

Add-Type @"
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace Wallpaper
{
   public enum Style : int
   {
       Tile, Center, Stretch, NoChange
   }
   public class Setter {
      public const int SetDesktopWallpaper = 20;
      public const int UpdateIniFile = 0x01;
      public const int SendWinIniChange = 0x02;
      [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
      private static extern int SystemParametersInfo (int uAction, int uParam, string lpvParam, int fuWinIni);
      public static void SetWallpaper ( string path, Wallpaper.Style style ) {
         SystemParametersInfo( SetDesktopWallpaper, 0, path, UpdateIniFile | SendWinIniChange );
         RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
         switch( style )
         {
            case Style.Stretch :
               key.SetValue(@"WallpaperStyle", "2") ; 
               key.SetValue(@"TileWallpaper", "0") ;
               break;
            case Style.Center :
               key.SetValue(@"WallpaperStyle", "1") ; 
               key.SetValue(@"TileWallpaper", "0") ; 
               break;
            case Style.Tile :
               key.SetValue(@"WallpaperStyle", "1") ; 
               key.SetValue(@"TileWallpaper", "1") ;
               break;
            case Style.NoChange :
               break;
         }
         key.Close();
      }
   }
}
"@
[Wallpaper.Setter]::SetWallpaper( "$BingImageFullPath", 3 )

You see here the last line of the script, will take the downloaded Bing image and set it as a Wallpaper immediately after download.

The above two scripts will work great assuming that everything executed without a hiccup. However, they will NOT work and cause “black” desktop screen if:

– The script can not find the right directoty to download the image to.
– If there is no internet connectivity
– You may get a black wallpaper if the Bing image is corrupted or did not download correctly.

We can make few additions to the script to avoid any problems if any, for example:

– have the script automatically create a download directory for us if one does not exist.
– Check if we already have the latest image before fetching for a new one. (No point to download the same image again)
– Make sure the script downloaded an image before setting it as a wallpaper to avoid black wallpaper screen.
– Make sure we have internet connectivity before executing the script.

Making the script smart

$Market = "en-US"
$Resolution = "1920x1080"
$ImageFileName = "wallpaper.jpg"
$DownloadDirectory = "$env:USERPROFILE\Pictures\Bing Wallpaper"
$BingImageFullPath = "$($DownloadDirectory)\$($ImageFileName)"

While (!(Test-Connection -ComputerName bing.com -count 1 -Quiet -ErrorAction SilentlyContinue )) {
    Write-Host -ForegroundColor Red "Waiting for internet connection to continue..."
    Start-Sleep -Seconds 10
}

New-Item -ItemType directory -Force -Path $DownloadDirectory | Out-Null

[ xml ]$Bingxml = (New-Object System.Net.WebClient).DownloadString("http://www.bing.com/HPImageArchive.aspx?format=xml&idx=0&n=1&mkt=$($Market)");
$ImageUrl = "http://www.bing.com$($Bingxml.images.image.urlBase)_$($Resolution).jpg";

if ((Test-Path "$BingImageFullPath") -And ((Get-ChildItem "$BingImageFullPath").LastWriteTime.ToShortDateString() -eq (get-date).ToShortDatesTring())){
    Write-Host -ForegroundColor Green "You already have today's Bing image in: $DownloadDirectory"   
}
else {
    Invoke-WebRequest -UseBasicParsing -Uri $ImageUrl -OutFile "$BingImageFullPath";
    Write-Host -ForegroundColor Green "Today's Bing image downloaded to: $DownloadDirectory" 
}

While (!(Test-Path "$BingImageFullPath")) {
    Write-Host -ForegroundColor Yellow "Waiting for Bing image to finish downloading..."
    Start-Sleep -Seconds 10
}
Add-Type @"
using System;
using System.Runtime.InteropServices;
using Microsoft.Win32;
namespace Wallpaper
{
   public enum Style : int
   {
       Tile, Center, Stretch, NoChange
   }
   public class Setter {
      public const int SetDesktopWallpaper = 20;
      public const int UpdateIniFile = 0x01;
      public const int SendWinIniChange = 0x02;
      [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
      private static extern int SystemParametersInfo (int uAction, int uParam, string lpvParam, int fuWinIni);
      public static void SetWallpaper ( string path, Wallpaper.Style style ) {
         SystemParametersInfo( SetDesktopWallpaper, 0, path, UpdateIniFile | SendWinIniChange );
         RegistryKey key = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", true);
         switch( style )
         {
            case Style.Stretch :
               key.SetValue(@"WallpaperStyle", "2") ; 
               key.SetValue(@"TileWallpaper", "0") ;
               break;
            case Style.Center :
               key.SetValue(@"WallpaperStyle", "1") ; 
               key.SetValue(@"TileWallpaper", "0") ; 
               break;
            case Style.Tile :
               key.SetValue(@"WallpaperStyle", "1") ; 
               key.SetValue(@"TileWallpaper", "1") ;
               break;
            case Style.NoChange :
               break;
         }
         key.Close();
      }
   }
}
"@
[Wallpaper.Setter]::SetWallpaper( "$BingImageFullPath", 3 )

The script above will work every time you launch it. It will not download a new Bing image if you already have the latest one. It will automatically create a download directory for you if one doesn’t exist. It will download a new Bing image if the one you have is old. Lastly, wait for the Bing image to finish downloading and set it as a wallpaper.

Let me know in the comments if I have missed any scenario that may cause the script to error out and not run correctly.

Set the script to start every time you log on to Windows with Windows Task Scheduler.

Bonus

When you set a PowerShell script to run at startup, you get a little PowerShell window that quickly pops up and disappear on your desktop every time it loads. To avoid that, you can create a small VBS script that silently call the PowerShell script. That way, you will not see any quick popups every time the script loads. Both PowerShell and VBS scripts are included in the download below.

VBS script to silently call the PowerShell script

command = "powershell.exe -nologo -command .\Get-Bing.ps1"
set shell = CreateObject("WScript.Shell")
shell.Run command,0


Download Scripts

//////

Hi, my name is Ali. I am a Systems Engineer. I live in the beautiful Evergreen state. I have a Bachelor degree of science in Information Technology with a handful of accompanying I.T. certificates. I also have a degree in Computer Networking. I am an Apple Certified Technician, Microsoft MCITP and a Linux expert.

25 Comments

  1. Python script to download Bing’s daily image for Mac | Hyper Expert · September 21, 2015

    […] previously wrote about downloading Bing’s daily image and set it as your wallpaper using PowerShell script. However, if you are a Mac user, this simple Python script will do a similar […]

    Reply
  2. corazon · September 21, 2015

    Hi Ali,

    Im already save script wih Get-Bing.ps1 and running command .\Get-Bing.ps1
    but got error :

    PS C:\Windows\system32> .\Get-Bing.ps1
    .\Get-Bing.ps1 : The term ‘.\Get-Bing.ps1’ is not recognized as the name of a cmdlet, function, script file, or operabl
    e program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At line:1 char:1
    + .\Get-Bing.ps1
    + ~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (.\Get-Bing.ps1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Reply
    • Ali · September 22, 2015

      Did you save the script to your System32 folder? If not, then thats the problem. From the error you have posted, looks like PowerShell can not find the script. If you have saved it to your Desktop for example, then you need to browse to it first before calling the script. Or, include the script path like so (Depending on where you are launching the script from):
      .\Desktop\Get-Bing.ps1

      Reply
  3. corazon · September 22, 2015

    Thank you for reply.

    script Get-Bing.ps1 im moved to c:/windows/system32
    i got error

    PS C:\windows\system32> .\Get-Bing.ps1
    .\Get-Bing.ps1 : File C:\windows\system32\Get-Bing.ps1 cannot be loaded because running scripts is disabled on this sys
    tem. For more information, see about_Execution_Policies at http://go.microsoft.com/fwlink/?LinkID=135170.
    At line:1 char:1
    + .\Get-Bing.ps1
    + ~~~~~~~~~~~~~~
    + CategoryInfo : SecurityError: (:) [], PSSecurityException
    + FullyQualifiedErrorId : UnauthorizedAccess

    Reply
  4. Corazon · September 22, 2015

    it’s working with warning..

    PS C:\windows\system32> Set-ExecutionPolicy RemoteSigned

    Execution Policy Change
    The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose
    you to the security risks described in the about_Execution_Policies help topic at
    http://go.microsoft.com/fwlink/?LinkID=135170. Do you want to change the execution policy?
    [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is “N”): a

    PS C:\windows\system32> .\Get-Bing.ps1
    Today’s Bing image downloaded to: C:\Users\T-6666\Pictures\Bing Wallpaper

    How to make this script more secure…

    Reply
    • Ali · September 22, 2015

      The script is secure! By default, PowerShell has a strong restriction policy about running scripts on your computer.

      Reply
  5. Corazon · September 22, 2015

    Thank You for awasome wallpaper script

    Reply
  6. Shell script to download Bing’s daily image as a wallpaper for Mac | Hyper Expert · September 28, 2015

    […] previously wrote about downloading Bing’s daily image and set it as your wallpaper using PowerShell for Windows. Or, Python for Mac. This time around, I will show you how to do a Shell script to achieve the same […]

    Reply
  7. Ted · October 2, 2015

    Hi Ali,

    Thanks for the script. Works awesome but I needed a few small changes to get it running as a daily task:

    Get-Bing.ps1:
    I removed the daily check because the task is set to run twice a day. I’m not sure when Bing updates the pictures, but now I get them more often. By setting a task it’s possible to run the script only when connected to the internet and when not running on battery mode. Furthermore I changed the url’s to SSL.

    StartHidden.vbs:
    I placed the files in the “%userprofile%\Pictures\Bing Wallpaper\” folder. Also I changed the parameters to “-ExecutionPolicy Bypass -nologo -file”. This way the script runs without any permission problems.

    command = “powershell.exe -ExecutionPolicy Bypass -nologo -file “”%userprofile%\Pictures\Bing Wallpaper\Get-Bing.ps1″””
    set shell = CreateObject(“WScript.Shell”)
    shell.Run command,0

    Task Scheduler:
    Use the following trigger to call the Starthidden.vbs script:
    wscript.exe “%userprofile%\Pictures\Bing Wallpaper\StartHidden.vbs”

    Cheers,
    Ted

    Reply
    • Ali · October 2, 2015

      Great! I’m glad this helped. I know Bing change their wallpaper at midnight Pacific time. However, I do like your suggestions. Will try to adjust my running task on my computer 😉

      Reply
    • Aric · January 5, 2017

      I’m trying to use this solution – though I keep getting an error whenever my task runs – it says “There is no file extension in “C:\WINDOWS\system32\”C:\Users\\Pictures\Bing”.”
      Am I supposed to have the StartHidden.vbs file in the system32 folder?

      Reply
      • Ali · January 5, 2017

        Why do you have “C:\WINDOWS\system32\”? You shouldnt need that.

        You can put StartHidden.vbs anywhere you want as long as it is in the same folder the powershell script is in. Or, you can manually edit StartHidden.vbs to reference to the powershell script if its in a different folder.

        Reply
  8. Ali · October 18, 2015

    This is great stuff dude!

    Reply
  9. Daniel · November 18, 2015

    Hi

    Nice script, thanks; how do you make use of the tile/stretch/center variables? I’m using a Microsoft Surface tablet and I get a black box around the edge of the picture. I’d like to be sensibly scaled up so that the aspect ratio isn’t messed about with… is this possible?

    Reply
    • Ali · November 18, 2015

      Daniel, in the last line “[Wallpaper.Setter]::SetWallpaper( “$BingImageFullPath”, 3 )” the number 3 at the end is actually telling the script to keep the styling to whatever you had set previously and not touch it. So, its up to you to go ahead and change the styling of your wallpaper. The script will remember your last setting and only change the picture.

      However, if you want to tell the script to change the styling for you (Does not always work when I tested it on Windows 10) – the number 3 at the end can be changed to one of the following options:
      0 = Tile
      1 = Center
      2 = Stretch
      and finally:
      3 = No Change

      Hope this helps

      Reply
  10. jullebarge · January 28, 2016

    Hi,

    Thanks for this script that works like a charm at home.
    but I’m trying to make it work at office but it doesn’t work because of a proxy.
    I’ve tried several things to use a proxy and use credentials, it works well for the DownloadString command but not for the Invoke-WebRequest. I go this error:
    Invoke-WebRequest : Proxy Authentication Required
    Description: Please login with username and password.

    I use this command:
    $pw = ConvertTo-Securestring -AsPlainText -Force -String “myPSWD”
    $cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList (“myLogin”,$pw)

    Invoke-WebRequest -Credential $cred -UseBasicParsing -Uri $ImageUrl -OutFile “$BingImageFullPath”;

    Can you help me ?

    Reply
    • Ali · January 28, 2016

      You can change line 21 and see if that works 😉
      from:
      Invoke-WebRequest -UseBasicParsing -Uri $ImageUrl -OutFile “$BingImageFullPath”;
      to:
      (New-Object System.Net.WebClient).DownloadFile($ImageUrl, $BingImageFullPath)

      Reply
      • jullebarge · January 29, 2016

        Thanks, I managed to make it work using DownloadFile.

        But now I have another problem: the wallpaper is not refreshed after the download: when I open Windows 7 wallpaper settings, I can see that the new downloaded file is set as a wallpaper, but it doesn’t show it on the desktop.

        Reply
  11. Stoynov · May 3, 2016

    Hi,
    very nice script, thanks!
    But I can’t run “StartHidden.vbs”. I modified the original script with this: command = “powershell.exe -ExecutionPolicy Bypass -nologo -file “”%userprofile%\Pictures\Bing Wallpaper\Get-Bing.ps1”””, but I havn’t results. Ideas?

    Reply
    • Ali · May 3, 2016

      Try this:
      command = “powershell.exe -ExecutionPolicy Bypass -nologo -file “”%userprofile%\Pictures\Bing Wallpaper\Get-Bing.ps1″” ”
      You have it right, except, you need a space at the very end of the line before the last quotation. Just tested it and it worked great on my PC

      Reply
  12. Masoud · February 28, 2017

    Hi Ali, great script, thanks for sharing! Just wanted to share one small change I made to it. In the $ImageFileName variable I added the get-date cmdlet so that it would stamp the downloaded with the date and keep it in the folder instead of overwriting it with the new image everyday. For all the wallpaper hoarders out there:

    $ImageFileName = “Wallpaper – $(get-date -f dd-MM-yyyy).jpg”

    Reply

Would you like to share your thoughts?