所以这是我在 Hyper-V 上创建新 VM 时作为操作系统设置脚本的一部分运行的 PowerShell 函数。我很好奇是否有更好的方法来实现这一点,或者这是否尽可能好?我希望这更简单,更容易实现。
Function Set-ComputerNameOnWallPaper($ComputerName = $env:COMPUTERNAME)
{
# Pull in the types necesary to manipulate the DesktopWallPaper and the pictures
# Information for setting the desktop wallpaper from
# https://smulpuru.wordpress.com/2015/04/01/change-wallpaper-using-windows-api-systemparametersinfo-from-user32-dll/
# Basis for for manipulating the graphic from
# http://stackoverflow.com/questions/2067920/can-i-draw-create-an-image-with-a-given-text-with-powershell
$setwallpapersource = @"
using System.Runtime.InteropServices;
public class wallpaper
{
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 )
{
SystemParametersInfo( SetDesktopWallpaper, 0, path, UpdateIniFile | SendWinIniChange );
}
}
"@
if (-not ([System.Management.Automation.PSTypeName]'wallpaper').Type){
Add-Type -TypeDefinition $setwallpapersource
}
Add-Type -AssemblyName System.Drawing
# Get the paths to the current bakground Image
# Generate a path for the modified Image
# Genarate a path for a temp file in case the modified image already exists
$imgInPath = (Get-ItemProperty 'hkcu:\control panel\desktop\' -Name Wallpaper).Wallpaper
$imgOutPath = Join-Path -Path $(Split-Path $imgInPath -Parent) -ChildPath $('MyComputerName.jpg')
$imgTemp = Join-Path -Path $(Split-Path $imgInPath -Parent) -ChildPath $('Temp01.jpg')
# Clean up any existing modified images that may have been created by this function
If ($imgInPath -eq $imgOutPath){
Remove-Item -Path $imgTemp -ErrorAction SilentlyContinue
Copy-Item -Path $imgInPath -Destination $imgTemp
[wallpaper]::SetWallpaper($imgTemp)
$imgInPath = $imgTemp
Remove-Item -Path $imgOutPath -ErrorAction SilentlyContinue
}
# Get the current graphic and define where on that graphic to write the comptername
# Note: Probably need to add a bit more error handling here
$top = 850
$left= 1160
$bmp = new-object System.Drawing.Bitmap $imgInPath
if(($bmp.Width -lt $left) -or ($bmp.Height -lt $top)){
throw("This function is not configured to work with your Desktop Image size.")
break
}
# Manipulate the image here
# Set up Font properties
$font = new-object System.Drawing.Font Calibri,36
$brushFg = [System.Drawing.Brushes]::White
# Get a default color near where we are going to write
# Build the brush
$bkgColor=$bmp.GetPixel($left-10,$top-10)
$brushClr = [System.Drawing.Color]($bkgColor)
$brushBg = [System.Drawing.SolidBrush]($brushClr)
# Fill the possible space where the comptuer name will be written with a default color
$graphics = [System.Drawing.Graphics]::FromImage($bmp)
$graphics.FillRectangle($brushBg,$left-3,$top-3,480,60)
# Draw the Comptuer Name
$graphics.DrawString($ComputerName,$font,$brushFg,$left,$top)
$graphics.Dispose()
# Save the graphic, clean up the object
$bmp.Save($imgOutPath)
$bmp.Dispose()
# Set the new Wallpaper and clean up and temporary residue
[wallpaper]::SetWallpaper($imgOutPath)
Remove-Item -Path $imgTemp -ErrorAction SilentlyContinue
}