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)