Desde hace muchos años, tengo un programa que se ejecuta todas las noches y que genera una imagen que utilizo como fondo de escritorio.

En las distintas versiones de Linux que he ejecutado, simplemente reemplazar el archivo de imagen que había configurado como fondo del escritorio haría que el escritorio actualizara su fondo para usar la nueva imagen.

En las distintas versiones de Windows que he ejecutado, siempre he tenido que abrir la configuración de pantalla, cambiar el fondo a una imagen diferente y luego volver a cambiarlo a la imagen original (nueva) para obtener el fondo cambiar.

Esto sigue siendo cierto en Windows 10.

¿Alguien conoce alguna forma de hacer que Windows reconozca automáticamente cuando el archivo de imagen de fondo ha cambiado y de actualizar el fondo del escritorio para reflejar el cambio, sin tener que realizar el cambio manualmente en la GUI?

answer

El fondo del escritorio de Windows son siempre mapas de bits (BMP). Cuando configura la imagen del escritorio a través de la GUI, convierte su imagen en un BMP antes de aplicarla.

Si su software existente genera un BMP, simplemente use algo RUNDLL32.EXE USER32.DLL,UpdatePerUserSystemParameters 1, Truecomo el presentado en esta pregunta SU:

Cómo forzar la actualización o actualización del fondo del escritorio de Windows

probablemente funcionará para actualizar el escritorio después de que se haya modificado la imagen.

Pero la mayoría de las cosas no generan BMP, generalmente es JPG o PNG en estos días, por lo que este método no funciona.

Entonces, aquí hay un script de PowerShell que:

  1. Cree un nuevo mapa de bits para establecerlo como fondo del escritorio ( $activeBackgroundBMP).
  2. Verifique si la última marca de tiempo escrita del archivo a monitorear ( $fileToCheck) ha cambiado desde la última verificación. Y de ser así...
  3. Cargue su imagen que será actualizada por su software ( $fileToCheck). Puede ser BMP, GIF, EXIF, JPG, PNG o TIFF.
  4. Guárdelo en el BMP ( $activeBackgroundBMP).
  5. Configure el BMP como fondo de escritorio y actívelo.
  6. Repita un ciclo sin fin (hasta que presione Ctrl-C o finalice la sesión de Powershell).

Para usarlo:

  1. Establezca $fileToCheckla ruta y el nombre de archivo del archivo que actualiza su software.
  2. Establezca $activeBackgroundBMPla ruta y el nombre de archivo con los que desea que se guarde el BMP (utilizado como fondo de pantalla).
  3. Ejecute PowerShell "como administrador"
  4. Ejecute el script y debería crear el archivo BMP que especificó en $activeBackgroundBMP(si aún no existe), y luego comenzar a recorrer para verificar los cambios $fileToCheck(cada 15 segundos de manera predeterminada).
  5. Configure la imagen de fondo de su escritorio en el BMP.

Mientras se está ejecutando, cuando $fileToCheckcambia la marca de tiempo de modificación, debería actualizar el fondo del escritorio.

Si lo desea, debería poder crear una tarea programada para iniciar el script "Como administrador" cuando el usuario inicie sesión ...

Aquí está el guión:

# Initalize last checked "timestamp" holder.
$lastCheck = 0

# Set file paths.
$fileToCheck = "c:\temp\back.jpg"
$activeBackgroundBMP = "c:\temp\dtback.bmp"

# Load required assemblies and get object reference for System.Drawing.
$ret = [Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms");

# Setup definitions so we can use User32.dll's SystemParametersInfo's SPI_SETDESKWALLPAPER.
# We only want to add the type definition of "params" if the "params" class hasn't been previously created in this PS session.
if (-not ([System.Management.Automation.PSTypeName]'Params').Type) {
    Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;

public class Params
{
    [DllImport("User32.dll",CharSet=CharSet.Unicode)]
    public static extern int SystemParametersInfo (Int32 uAction,
                                                   Int32 uParam,
                                                   String lpvParam,
                                                   Int32 fuWinIni);
}
"@
}

# Setup some constants to be used with User32.dll's SystemParametersInfo.
$SPI_SETDESKWALLPAPER = 0x0014
$UpdateIniFile = 0x01
$SendChangeEvent = 0x02
$fWinIni = $UpdateIniFile -bor $SendChangeEvent

# If the target BMP doesn't exist, create a new one.
if (-Not (Test-Path $activeBackgroundBMP)) {
    # Create a new 1x1 bitmap, and save it.
    $ret = (new-object System.Drawing.Bitmap(1,1)).Save($activeBackgroundBMP,"BMP")
    Write-Host "New BMP created ($activeBackgroundBMP)."
}

# Check if file exists before monitoring.
if (Test-Path $fileToCheck) {
    # Loop endlessly (hit Ctrl-C to break).
    while ($true) {
        # Get the last write timestamp from file.
        $lastWrite = (Get-Item $fileToCheck).LastWriteTime

        # If it's different than the Last Check time...
        if ($lastWrite -ne $lastCheck) {
            # Load the updated background image into a BMP, and save it as the target BMP.
            $img = new-object System.Drawing.Bitmap($fileToCheck)
            $img.Save($activeBackgroundBMP,"BMP")

            # Dispose of the System.Drawing object, to release the $fileToCheck file (so it can be overwritten by other processes).
            $img.Dispose()
            $img = $null

            # Refresh desktop background with the updated BMP image.
            $ret = [Params]::SystemParametersInfo($SPI_SETDESKWALLPAPER, 0, $activeBackgroundBMP, $fWinIni)

            # Update Last Check timestamp to match file's current timestamp.
            $lastCheck = $lastWrite

            Write-Host "Refeshed."
        }

        # Pause 15 seconds before looping back.
        Start-Sleep -s 15
    }
} else {
    # File doesn't exist.
    Write-Host "$fileToCheck not found, aborting."
}