I've found a PowerShell script that can change the desktop wallpaper of my Windows 7 PC of an image file whose path is supplied as a parameter. The end result of what I want is to have this script called by a batch file on startup.
[CmdletBinding()]
Param(
[Parameter(Position=0, Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
[Alias("FullName")]
[string]
$Path
,
[Parameter(Position=1, Mandatory=$false)]
$Style = "NoChange"
)
BEGIN {
try {
$WP = [Wallpaper.Setter]
} catch {
$WP = 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();
}
}
}
"@ -Passthru
}
}
PROCESS {
Write-Verbose "Setting Wallpaper ($Style) to $(Convert-Path $Path)"
$WP::SetWallpaper( (Convert-Path $Path), $Style )
}
I'm calling this script using the command:
C:\scripts\Set-Wallpaper.ps1 C:\Users\myProfile\Pictures\MyWallpaper.jpg
I'm totally new to the world of PowerShell scripts, and the issue I'm having is that when I execute the script from within PowerShell it always fails the first time with the following error:
C:\scripts\Set-Wallpaper.ps1 : Unable to cast object of type 'System.Object[]' to type 'System.Type'.
At line:1 char:29
- C:\scripts\Set-Wallpaper.ps1 <<<< C:\Users\mbaleato\Pictures\MyWallpaper.jpg
- CategoryInfo : NotSpecified: (:) [Set-Wallpaper.ps1], InvalidCastException
- FullyQualifiedErrorId : System.InvalidCastException,Set-Wallpaper.ps1
But when I call the script with the exact same command and parameter the second time it works.
It is this failing the first time that is causing my batch file to fail.
Anyone who is more experienced have some suggestions as to why it fails the first time, but works the second time? Any suggestions as to how I can get it to work the first time?
Look at line that begins with $WP = add-type @"
. That's the problem. You create two types:
$wp
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Style System.Enum
True False Setter System.Object
Try to call Add-Type
without -Passthru
and after that assign to $wp
Add-Type -typedef @"
...
"@
$WP = [Wallpaper.Setter]
I believe it's because-passthru is making $WP into an array - you could try this try this instead:
try {
$WP = [Wallpaper.Setter]
} catch {
add-type @"
....
"@
$WP = [Wallpaper.Setter]
}
You can see by running it line by line and checking the tyoe:
PS D:\bin\OpenSSL-Win32\bin> $WP
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Style System.Enum
True False Setter System.Object
PS D:\bin\OpenSSL-Win32\bin> $WP.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
PS D:\bin\OpenSSL-Win32\bin> $WP = [Wallpaper.Setter]
PS D:\bin\OpenSSL-Win32\bin> $WP.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
False True RuntimeType System.Type
The second time around the type is already there so %WP is loaded correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With