2019-04-07 的更新

此工具迎来了 2.0 版本,更新内容如下:

  • 自解压的输出路径由原来的 当前目录 更改至 Windows\Temp 目录
  • 修复重启系统后壁纸设置无效的问题
    • 其实是添加了一个自启项,每次开机后自动设置壁纸
    • 如果想去掉自启项,删除 %AppData%\Microsoft\Windows\Start Menu\Programs\Startup 目录下的 add-on_set_wallpaper.exe 即可
  • 使用新的压缩选项,打包后体积更小
    • 其实并没有减小,眼花看错了,上传到网盘时才发现,只是比较懒就懒得去掉了

除非不能使用,就不会再更新了。

写在前面

前几日,写了一篇博文 (写段 Bash Script 获取 Bing 的每日美图)。

有网友反馈,在 Windows 上使用还是太麻烦了。 那能怎么办?满足他呗。

于是就有了这个小工具。

下载与使用

下载

点击这里 下载已打包好的版本 (打包工具为 WinRAR)。

我可以保证引入的外部工具是安全的,如果你使用的反病毒软件报毒的话。

可以将本工具添加至白名单,或者停止使用并删除本工具 (目前已知 Windows Defender 会误报)。

使用

下载完成后,双击运行即可。

运行中会弹出一个黑底白字的窗口,只需稍等片刻, 就能下载今日的 Bing 美图并设为壁纸。

  • 程序运行中,可能会弹出 UAC 窗口 (因为需要输出日志到系统盘),点击 “是” 即可

  • 你可以设定一个定时任务,每 24 小时运行一次本工具

  • 下载的图片都会保留一份复本 (不含重复的图片), 复本存放在当前用户的用户目录中的 Pictures 文件夹中。

波涛汹涌又波澜不惊

最开始准备使用纯 Batch Script 实现的, 结果发现这脚本语言写起来比吃屎还难受。

就引入了几个外部工具 (cURL, gawk, cut) 想简化一下, 结果 gawk 在 Batch 中使用又会出现各种问题 (特殊字符,参数会有问题)。

那就把 上篇博文 中的 Bash Script 拿来用吧,这样还可以降低维护成本,然后引入了 BusyBoxcURL 这两个外部工具。


总算是可以解析并下载图片了。 谁知刚爬出一个坑,又掉进另一个坑。

遇到了在 Windows 7 系统上设置壁纸会玄学无效 (偶尔又有效) 的问题 (因为尽管 Windows 7 支持使用 .jpg 格式的图片作为壁纸,但需要图片的 DPI 信息完备)。

那就转化成 .bmp 呗。

使用 PowerShell 实现了 jpg2bmp 的功能,结果在其它电脑上却不能正确执行。

不想再折腾了,就使用 jpg2bmpcmd 这个外部工具来实现吧。


这就完事了?我也想呀。

结果设置壁纸也是个麻烦事。

网上介绍的几个方法都有各种的瑕疵, 无奈只能自己用 AutoHotkey 实现设置壁纸的功能了。


这样的后果就是, 程序里面充斥着各种语言间的相互调用 (至少有 5 种语言)。

简直是混乱不堪,不堪入目。 就好像自己把几种屎搅在了一起。

要是一开始就用 Python 或者 AutoHotkey 实现, 应该就不会这么折腾了。

具体实现

直接上代码。

首先是程序入口处的脚本 (使用的是 Batch Script)

@ECHO OFF

::
:: 获取 Bing 的每日美图并设置成壁纸
::

:: 设置窗口背景和字体颜色
COLOR 0F
:: 设置窗口标题
TITLE=获取 Bing 的每日美图并设置成壁纸
:: 设置窗口大小
MODE CON COLS=50 LINES=25

:: 输出作者信息
ECHO "+ Author: 文正•喵"
ECHO "+ E-Mail: ivlioioilvi@outlook.com"
ECHO "---------------------------------"
ECHO "The program is in progress."
ECHO "Please wait ..."

:: 让脚本获取管理员权限
::
:: 方案一 (推荐使用)
%1 START mshta VBScript:CreateObject("Shell.Application").ShellExecute("cmd.exe","/C %~s0 :: %CD%","","runas",1)(window.close)&&exit
:: 方案二 (不推荐使用。因为脚本如果放在 C 盘中,可能会因没有写入权限而执行失败)
::%1 ECHO Set objShell = CreateObject("Shell.Application") > Admin.vbs
::%1 ECHO objShell.ShellExecute "cmd.exe", "/C %~s0 :: %CD%", "", "runas", 1 >> Admin.vbs
::%1 ECHO WScript.Quit >> Admin.vbs
::%1 CALL Admin.vbs && del /f /q Admin.vbs
::%1 EXIT

:: 定义变量
::
:: 获取传入的参数二 (脚本自身所在的路径)
SET SELF_PATH=%2
:: 临时设置 PATH 变量
SET PATH=%SELF_PATH%\bin;%PATH%
:: Bing 的网址
SET BING_URL=https://bing.com
:: 存放壁纸的文件夹
SET BG_DIR_PATH=%HOMEDRIVE%\Users\%USERNAME%\Pictures\Wallpaper
SET BG_DIR_PATH_BACKUPS=%HOMEDRIVE%\Users\%USERNAME%\Pictures\Wallpaper\Backups

:: 准备工作
:preparation_Action
    :: 判断存放壁纸的目录是否存在
    IF EXIST "%BG_DIR_PATH_BACKUPS%" (
        :: 目录已存在
        ECHO "---------------------------------"
    ) ELSE (
        MKDIR "%BG_DIR_PATH_BACKUPS%"
    )

    :: 开始执行 get_Pictures 函数
    CALL:get_Pictures_URL
GOTO:EOF

:: 下载和设置壁纸
:download_And_Set_Wallpaper
    :: 从文件读取变量并赋值
    FOR /F "delims=" %%u IN (%SystemRoot%\Temp\tmp_full_url.txt) DO (
        SET IMG_FULL_URL=%%u
    )
    FOR /F "delims=" %%n IN (%SystemRoot%\Temp\tmp_file_name.txt) DO (
        SET IMG_FILE_NAME=%%n
    )
    FOR /F "delims=" %%t IN (%SystemRoot%\Temp\tmp_file_type.txt) DO (
        SET IMG_FILE_TYPE=%%t
    )

    :: 下载图片到备份目录
    curl.exe -sL "%IMG_FULL_URL%" -o "%BG_DIR_PATH_BACKUPS%\%IMG_FILE_NAME%%IMG_FILE_TYPE%"
    :: 复制壁纸到工作目录 (当前需要使用的壁纸一律复制到此文件夹中)
    COPY /Y "%BG_DIR_PATH_BACKUPS%\%IMG_FILE_NAME%%IMG_FILE_TYPE%" "%BG_DIR_PATH%\Current%IMG_FILE_TYPE%"

    :: 转化 .jpg 图像到 .bmp
    :: + Windows XP:壁纸只能使用 .bmp 格式
    :: + Windows 7 :壁纸虽然支持使用 .jpg 格式,但 .jpg 格式的图片需要 DPI 信息完备
    ::
    :: 方案一 (推荐使用)
    jpg2bmpcmd.exe -i "%BG_DIR_PATH%\Current%IMG_FILE_TYPE%" -o "%BG_DIR_PATH%" -q
    DEL /F /Q "%BG_DIR_PATH%\Current%IMG_FILE_TYPE%"
    ::
    :: 方案二 (不推荐使用。因为在 Windows 10 上可能会失效 )
    ::CALL add-on_jpg2bmp.bat
    ::MOVE /Y "%SELF_PATH%\Current.bmp" "%BG_DIR_PATH%\Current.bmp"
    ::DEL /F /Q "%BG_DIR_PATH%\Current%IMG_FILE_TYPE%"

    :: 设置壁纸
    :: 你也可以注释掉下面的行,转而使用其它壁纸设置工具,如果你想的话
    ::
    :: 方案一 (推荐使用)
    add-on_set_wallpaper.exe
    ::
    :: 方案二 (不推荐使用。因为可能会因为缺少 .net 运行库而失效)
    ::CALL add-on_set_wallpaper.bat
    ::
    :: 方案三 (不推荐使用。可能经常会失效,也可能会随缘有效)
    ::REG ADD "HKEY_CURRENT_USER\Control Panel\Desktop" /v Wallpaper /d "%BG_DIR_PATH%\Current.bmp" /f
    ::GPUPDATE /Force
    ::RunDll32.exe USER32.DLL,UpdatePerUserSystemParameters
    ::TASKKILL /IM explorer.exe /F & START explorer.exe

    :: 开机自动设置当前已下载的壁纸
    COPY /Y "%SELF_PATH%\bin\add-on_set_wallpaper.exe" "%AppData%\Microsoft\Windows\Start Menu\Programs\Startup"

    :: 清理临时文件
    DEL /F /Q "%SystemRoot%\Temp\tmp_full_url.txt"
    DEL /F /Q "%SystemRoot%\Temp\tmp_file_name.txt"
    DEL /F /Q "%SystemRoot%\Temp\tmp_file_type.txt"

    :: 删除自解压出的文件 (让程序行为看起更整洁有序)
    RD /S /Q "%SystemRoot%\Temp\bin"
    DEL /F /Q "%SystemRoot%\Temp\License"
    DEL /F /Q "%SystemRoot%\Temp\Version"
    DEL /F /Q "%SystemRoot%\Temp\Start.bat"
GOTO:EOF

:: 获取图片的链接地址
:get_Pictures_URL
    :: 获取 Bing 网站的源码
    curl.exe -sL "%BING_URL%" > "%SystemRoot%\Temp\tmp_source_code.txt"

    :: 过滤出图片链接
    busybox.exe bash "%SELF_PATH%/bin/add-on_filter.sh"
    :: 清理临时文件
    DEL /F /Q "%SystemRoot%\Temp\tmp_source_code.txt"

    :: 开始执行 download_And_Set_Wallpaper 函数
    CALL:download_And_Set_Wallpaper
GOTO:EOF

:: 开始执行 preparation_Action 函数
CALL:preparation_Action

然后是用于解析图片链接的 Bash Script

#!/bin/bash

# @Author: 文正•喵
# @E-Mail: ivlioioilvi@outlook.com

#
# 提取出图片的链接, 名字, 后缀
#

# 定义变量
#
# Bing 的网址
BING_URL="https://bing.com"
# 第一次粗略过滤时的关键字 (定位到图片链接所在行)
FIRST_FILTERING_RULE='<link id="bgLink" rel="preload"'
# 第二次精确过滤时的规则 (提取出未拼接的图片链接)
SECOND_FILTERING_RULE='BEGIN { FS = "\"|\"" } { print $6 }'

# 提取出图片的文件名和后缀
get_File_Name() {
    # 获取传入的参数 1 (已拼接的图片链接)
    FULL_URL="$1"
    # 获取传入的参数 2 (未拼接的图片链接)
    HALF_URL="$2"

    # 提取出图片的名字
    FILE_NAME=$(echo -e "$HALF_URL" | cut -d "&" -f 1 | cut -d "_" -f 1 | cut -d "." -f 2)

    # 提取出图片的后缀
    TMP_FILE_TYPE=$(echo -e "$HALF_URL" | cut -d "&" -f 1 | cut -d "." -f 3)
    FILE_TYPE=".$TMP_FILE_TYPE"

    # 写入图片已拼接的链接, 名字, 后缀到文件
    echo "$FULL_URL"  > "$SYSTEMROOT/Temp/tmp_full_url.txt"
    echo "$FILE_NAME" > "$SYSTEMROOT/Temp/tmp_file_name.txt"
    echo "$FILE_TYPE" > "$SYSTEMROOT/Temp/tmp_file_type.txt"
}

# 提取出图片的链接
get_Pictures_URL() {
    # 定义局部变量 (未拼接的图片链接)
    INCOMPLETE_URL=$(

    # 读取 Bing 网站的源码
    cat "$SYSTEMROOT/Temp/tmp_source_code.txt" |

    # 进行第一次粗略的过滤 (定位到图片链接所在行)
    grep "$FIRST_FILTERING_RULE" |

    # 进行第二次精确过的滤时 (提取出图片链接)
    awk "$SECOND_FILTERING_RULE" )

    # 开始执行 file_Name 函数,并传入已拼接的 URL 和未拼接的 URL 两个参数
    get_File_Name "$BING_URL$INCOMPLETE_URL" "$INCOMPLETE_URL"
}

# 开始执行 get_Pictures 函数
get_Pictures_URL

最后就是设置壁纸的功能 (使用的是 AutoHotkey)

; @Author: 文正•喵
; @E-Mail: ivlioioilvi@outlook.com

;
; 设置系统壁纸
;

; 获取系统的环境变量
EnvGet, SYS_HOME_DRIVE, HOMEDRIVE
EnvGet, SYS_USER_NAME, USERNAME

; 定义变量
BMP_PATH=%SYS_HOME_DRIVE%\Users\%SYS_USER_NAME%\Pictures\Wallpaper\Current.bmp

; 开始设置壁纸
DllCall("SystemParametersInfo", UInt, 0x14, UInt, 0, Str, BMP_PATH, UInt, 2)