快捷方式中的Powershell脚本能否改变桌面?

15
任何关于为什么从PowerShell中运行时这个能工作,但是从一个快捷方式中运行时不能工作的想法和建议?
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -File "C:\Users\bin\ChangeDesktop.ps1"

ChangeDesktop.ps1的内容:

set-itemproperty -path "HKCU:Control Panel\Desktop" -name WallPaper -value ""
rundll32.exe user32.dll, UpdatePerUserSystemParameters
如果我在PS“命令提示符”环境中,桌面背景会自动被移除和刷新,否则我需要手动刷新桌面来实现更改。
系统是Windows Server 2008 R2-全新安装。脚本执行策略设置为RemoteSigned,并且我没有看到任何PS错误。只是当从桌面快捷方式运行时,我没有看到桌面自动刷新。
* 摸了摸头 *

1
快捷方式的操作方式很像CMD提示符,因此请在那里测试快捷方式命令行,而不是在PowerShell提示符中。 - Jay Bazuzi
需要在PowerShell脚本中使用单引号。这样做后,它就像魔法般地运行了。感谢提供脚本。 - Roelof Briers
4个回答

29

rundll32.exe user32.dll, UpdatePerUserSystemParameters在我使用的2008 x64计算机上实际上没有改变壁纸。但是,以下方式可以改变壁纸...它调用Win32 API来实现更改壁纸。如果您将此保存为ChangeDesktop.ps1脚本,则应该能够正常工作。如下所示,它会删除任何桌面壁纸。但是,如果您想设置一个壁纸,您可以像这样编辑最后一行,添加支持的图像文件的路径:

[Wallpaper.Setter]::SetWallpaper( 'C:\Wallpaper.bmp', 0 )

第二个参数用于样式:

0:平铺 1:居中 2:拉伸 3:不改变

脚本:

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( '', 0 )

这段代码最初来源于 PoshCode:http://poshcode.org/491


1
非常感谢,安迪。这确实有效。我仍然很好奇为什么我最初尝试的另一种方法在从快捷方式运行时不起作用。Windows Powershell有时是一个奇怪的东西——至少对我来说还是这样。 - joebalt
@JoeBaltimore 我使用rundll32.exe时得到了奇怪的结果。有时它可以从手动输入的控制台中工作,有时不行;有时它可以从通过快捷方式调用的脚本中工作,有时不行...至少这种方法始终有效 :-) 看起来其他人在使用rundll32更新壁纸时也遇到了同样的问题。 - Andy Arismendi
谢谢。我已经为此挣扎了数小时。 - Jente
1
我无法使其显示纯色。 - sanepete
有人能解释一下 rundll32.exe 是什么吗? - Kellen Stuart

0

这个脚本非常好用。在域部署中,我们不希望每次用户登录时都不断更改背景。

我进行了以下更改,以便它检查计算机上所需位置的背景是否存在,如果存在,则退出,如果不存在,则继续进行文件复制并设置背景。

它首先映射隐藏共享,将文件复制到所需目录,设置壁纸,然后断开隐藏共享。如果“X”已被您的公司使用,请插入另一个驱动器号。 :D

$strFileName="C:\Users\Public\Pictures\background.jpg"
If (Test-Path $strFileName){
  # // File exists
  Exit-PSSession
}Else{
  # // File does not exist 
New-PSDrive -Name X -PSProvider Filesystem -Root   \\hiddenfileshare\wallpapers
Copy-Item X:\background.jpg C:\Users\Public\Pictures
[Wallpaper.Setter]::SetWallpaper( 'C:\Users\Public\Pictures\background.jpg',       0 )
Remove-PSDrive X
}

0
这可能听起来有些奇怪,但对我有效的方法是使用单引号而不是双引号。所以它看起来像这样:
Set-ItemProperty -path "HKCU:Control Panel\Desktop" -name 'wallpaper' -value 'some value'
rundll32.exe user32.dll, UpdatePerUserSystemParameters

0

Andy Arismendi 提供的脚本真是太棒了!

我用它做了一个有趣的项目 - 从网络上随机设置壁纸

我在这里发布给任何感兴趣的人。在使用之前,您需要更改脚本源代码顶部的一些常量。您还需要下载 HtmlAgilityPack.dll 库(脚本注释中有说明)。

享受吧!

P.S. 如果我使用的壁纸网站关闭或更改其布局,则脚本中的抓取将失败,但是即使如此,通过我的脚本示例,我敢打赌您也能构建另一个壁纸抓取器。

############## CONSTANTS ##############

# add the library for parsing html - HtmlAgilityPack - download it with nuget from https://www.nuget.org/packages/HtmlAgilityPack
# download nuget command line from https://dist.nuget.org/index.html and install HtmlAgilityPack with "nuget install HtmlAgilityPack" from the cmd

# enter the path to HtmlAgilityPack.dll library used for html parsing
$html_parser_path = "C:\Users\username\Documents\htmlagilitypack\HtmlAgilityPack.1.4.9.5\lib\Net20\HtmlAgilityPack.dll"

# choose where your wallpapers will be downloaded
$wallpaper_dir_path = "C:\Users\username\Pictures\"

# get random wallpaper category from wallpaperscraft.com - the ones below are my favourite categories, edit it if you want to get other categories

<#
you can choose your favorite wallpaper categories from the list below
    3D
    Abstract
    Animals
    Anime
    Brands
    Cars
    City
    Fantasy
    Flowers
    Food
    Games
    Girls
    Hi-Tech
    Holidays
    Macro
    Men
    Movies
    Music
    Nature
    Other
    Space
    Sport
    Textures
    TV Series
    Vector
#>

$categories = @("animals","flowers","macro","nature","space") 



# I download my wallpapers from the site below - real quality wallpapers
# don't forget to change your resolution - I'm using a 1920x1080 monitor

<#
A list of resolutions to choose from:

    1600x1200
    1400x1050
    1280x1024
    1280x960
    1152x864
    1024x768
    3840x2400
    3840x2160
    3840x1200
    2560x1600
    2560x1440
    2560x1080
    2560x1024
    2048x1152
    1920x1200
    1920x1080
    1680x1050
    1600x900
    1440x900
    1280x800
    1280x720
    2160x3840
    1440x2560
    1366x768
    1080x1920
    1024x600
    960x544
    800x1280
    800x600
    720x1280
    540x960
    480x854
    480x800
    400x480
    360x640
    320x480
    320x240
    240x400
    240x320
    2732x2732
    2048x2048
    1080x1920
    1024x1024
    750x1334
    640x1136
    640x960
    320x480
    1366x768
    1920x1080
    360x640
    1024x768
    1600x900
    1280x900
    1440x900
    1280x1024
    800x600
    1680x1050
    2560x1440
    320x480
    1920x1200
    480x800
    720x1280
#>

$resolution = "1920x1080" # default resolution
$url = "https://wallpaperscraft.com/catalog/category/$resolution" # category is a placeholder

############## END OF CONSTANT DECLARATIONS ##############

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();
      }
   }
}
"@





Add-Type -Path $html_parser_path 

$rand_index = Get-Random -minimum 0 -maximum $categories.Length
$random_category = $categories[$rand_index]

# replace the placeholder "category" with the random category chosen above

$url = $url -replace "category", $random_category

$doc = New-Object HtmlAgilityPack.HtmlDocument
$doc.LoadHtml((New-Object System.Net.WebClient).DownloadString($url))

# NOTE: the html parser I'm using locates elements by XPath only
$page_links = $doc.DocumentNode.SelectSingleNode("//div[contains(@class, 'pages')]").SelectNodes("a")

# get last page link
$last_page_link = $page_links[$page_links.Count - 1].GetAttributeValue("href", "")

# get last page number 
$last_page_number = [regex]::match($last_page_link,'.*page(\d+)').Groups[1].Value

$random_page_number = Get-Random -minimum 0 -maximum $last_page_number
$random_page_addr = ""

# page 1 doesn't add anything to the url

if ($random_page_number -gt 0){
    $random_page_addr = "/page$random_page_number"
}

$doc.LoadHtml((New-Object System.Net.WebClient).DownloadString("$url$random_page_addr"))

# get wallpaper divs
$wallpaper_divs = $doc.DocumentNode.SelectNodes("//div[contains(@class, 'wallpaper_pre')]")

$random_wallpaper_div = Get-Random -minimum 0 -maximum 15 # there are 15 wallpapers on a page

# get a sample wallpaper link which has to be substituted later
$sample_wallpaper_link = $wallpaper_divs[$random_wallpaper_div].SelectNodes("a")[0].GetAttributeValue("href", "")

# substitute the above link to get the image link itself

$sample_wallpaper_link = $sample_wallpaper_link -replace "download", "image"
$sample_wallpaper_link = $sample_wallpaper_link -replace "/$resolution", "_$resolution.jpg"
$sample_wallpaper_link = $sample_wallpaper_link -replace "//", "https://"

$wallpaper_image_name = [regex]::match($sample_wallpaper_link,'.*image/(\w+)').Groups[1].Value
$wallpaper_image_name = "$wallpaper_image_name.jpg"

$wc = New-Object System.Net.WebClient

$save_location = "$wallpaper_dir_path$wallpaper_image_name"
$wc.DownloadFile($sample_wallpaper_link, "$save_location")

[Wallpaper.Setter]::SetWallpaper($save_location, 1 )

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接