最近在弄一個較複雜的測試環境,有多台主機扮演不同前中後台角色,且角色可能機動調整,使用遠端桌面登入操作時,除了由 IP 查 Email 更新通知,還希望有更直覺方便的識別方式。我想到一個簡單做法 - 做一張標示主機資訊的桌布,登入時馬上可看到提示。

真要做,其實用小畫家弄一下就好了,但我硬是把它當成 PowerShell 練習題寫成小工具,輸入提示資訊、字型大小、背景色、背景色透明度(0-255)、文字顏色,由程式自動產生桌布圖檔並換掉桌布。示範如下:

裡面用到了 C# Bitmap、Graphics 繪圖、Interop 呼叫原生 Windows API、Add-Type -TypeDefinition 動態編譯 C# 型別供 PowerShell 呼叫... 等綜合技,當成日常伸展維持手感還不錯。完整程式如下:

param (
    [Parameter(Mandatory=$true)]
    [string]$msg,
    [int]$fontSize = 32,
    [string]$bgColor = 'Black',
    [int]$alpha = 226,
    [string]$fgColor = 'White'
)
$cs = @"
using Microsoft.Win32;
using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Runtime.InteropServices;


public class WallPaperUtil
{
    static SizeF MeasureStringSize(string msg, Font font)
    {
        using (var bmp = new Bitmap(1,1))
        {
            using (var g = Graphics.FromImage(bmp))
            {
                return g.MeasureString(msg, font);
            }
        }
    }

    [DllImport("User32.dll", CharSet = CharSet.Unicode)]
    public static extern int SystemParametersInfo(Int32 uAction, Int32 uParam, string lpvParam, Int32 fuWinIni);
    const int SPI_SETDESKWALLPAPER = 0x0014;
    const int UpdateIniFile = 0x01;
    const int SendChangeEvent = 0x02;
    public static void SetWallPaper(string msg, int fontSize, string bgColor, int alpha, string fgColor)
    {
        var font = new Font("微軟正黑體", fontSize);
        var size = MeasureStringSize(msg, font);
        var padding = fontSize / 4;
        using (var bmp = new Bitmap((int)(size.Width + padding * 2), (int)(size.Height + padding * 2)))
        {
            using (var g = Graphics.FromImage(bmp))
            {
                g.FillRectangle(new SolidBrush(Color.FromName("White")), 0, 0, bmp.Width, bmp.Height);
                g.FillRectangle(new SolidBrush(Color.FromArgb(alpha, Color.FromName(bgColor))), 0, 0, bmp.Width, bmp.Height);
                g.DrawString(msg, font, new SolidBrush(Color.FromName(fgColor)), padding, padding);
                var imgPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyPictures), "MessageWallPaper.png");
                bmp.Save(imgPath, ImageFormat.Png);
                Registry.SetValue(@"HKEY_CURRENT_USER\Control Panel\Desktop", "TileWallPaper", "0");
                Registry.SetValue(@"HKEY_CURRENT_USER\Control Panel\Desktop", "WallPaperStyle", "0");
                SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, imgPath, UpdateIniFile | SendChangeEvent);
            }
        }
    }

}
"@
if (!('WallPaperUtil' -as [type])) {
    Add-Type -TypeDefinition $cs -ReferencedAssemblies ('System.Drawing')
}
[WallPaperUtil]::SetWallPaper($msg, $fontSize, $bgColor, $alpha, $fgColor)

參考資料:Set-Wallpaper Powershell Function by Jose Espitia

2021-12-23 補充 - 網友 Scott Kao 分享 SystemInternals 有功能相似的好東西 - bgInfo,每次開機時可在桌布加上 CPU、RAM、Disk、IP 等系統資訊,有類似需求的話可多加利用。


圖片來源

PowerShell example to create image dynamically and set it as Windows wallpaper.


Comments

Be the first to post a comment

Post a comment