Skip to content

Repository files navigation

WallpaperAgent

Agente para Windows que baixa um manifesto JSON público, valida os arquivos por SHA-256 e aplica o wallpaper da área de trabalho e a tela de bloqueio no contexto do usuário interativo.

Configuração da organização

Toda a identidade da organização fica centralizada em uma única chave no arquivo WallpaperAgent.Config.psd1:

OrganizationName = 'orgname'   # altere para o nome da organização

A partir desse valor, o projeto deriva automaticamente:

  • instalação: C:\ProgramData\{OrganizationName}\WallpaperAgent;
  • dados por usuário: %LOCALAPPDATA%\{OrganizationName}\WallpaperAgent;
  • registro: HKLM:\SOFTWARE\{OrganizationName}\WallpaperAgent;
  • pasta de tarefas: \{OrganizationName}\;
  • tarefa de atualização: {OrganizationName} - Wallpaper Update;
  • tarefa de aplicação: {OrganizationName} - Wallpaper Apply;
  • nomes dos mutexes usados para impedir execuções simultâneas.

Todos esses valores podem ser sobrescritos individualmente no arquivo de configuração.

Repositório de conteúdo obrigatório

Cada organização que utilizar o projeto deve criar um repositório separado exclusivamente para armazenar o manifesto e as imagens publicadas. O correto é manter dois repositórios independentes:

  • WallpaperAgent: código do agente, instalação, detecção e documentação;
  • repositório de conteúdo, por exemplo WallpaperContent: manifest.json, wallpapers e lock screens.

Não publique imagens e releases dentro do repositório do agente. Essa separação permite atualizar o conteúdo sem alterar, recompilar ou redistribuir o pacote instalado pelo Intune.

O repositório de conteúdo deve ser configurado em WallpaperAgent.Config.psd1:

RepositoryOwner = 'github-owner'
RepositoryName = 'WallpaperContent'
RepositoryBranch = 'main'
RepositoryManifestPath = 'windows/manifest.json'
PublisherTokenEnvironmentVariable = 'WALLPAPER_REPOSITORY_TOKEN'
ManifestUrl = ''

Com ManifestUrl vazio, o agente deriva automaticamente:

https://raw.githubusercontent.com/{RepositoryOwner}/{RepositoryName}/{RepositoryBranch}/{RepositoryManifestPath}

Token de publicação

Crie um fine-grained personal access token limitado somente ao repositório de conteúdo e conceda a permissão de repositório Contents: Read and write. Esse token é usado pelo servidor, portal ou processo que publica as imagens e atualiza o manifesto.

O valor do token deve ficar em um cofre de segredos ou variável de ambiente no servidor de publicação, usando por padrão o nome configurado em PublisherTokenEnvironmentVariable:

[Environment]::SetEnvironmentVariable(
    'WALLPAPER_REPOSITORY_TOKEN',
    'github_pat_REPLACE_WITH_REAL_TOKEN',
    'Machine'
)

Nunca coloque o token no PSD1, no manifesto, no Git, no pacote .intunewin ou nos computadores clientes. O WallpaperAgent somente lê URLs HTTPS e não utiliza o token de escrita. Para esse modelo, o repositório de conteúdo deve ser público. Caso o conteúdo precise ser privado, publique-o por um endpoint intermediário somente leitura; não distribua um token read/write aos dispositivos.

Arquitetura

O agente usa duas tarefas agendadas:

  1. Wallpaper Update

    • executada como SYSTEM;
    • inicia com o Windows;
    • repete no intervalo definido em CheckIntervalMinutes;
    • baixa o manifesto e os assets;
    • valida URL, extensão, tamanho, integridade SHA-256 e leitura da imagem;
    • mantém o release anterior quando a atualização falha.
  2. Wallpaper Apply

    • executada no grupo interno INTERACTIVE;
    • inicia no logon do usuário;
    • repete no mesmo intervalo;
    • aplica desktop e lock screen no contexto correto do usuário;
    • reaplica o padrão caso o usuário altere manualmente a imagem.

Quando o updater detecta conteúdo novo, ele tenta iniciar imediatamente a tarefa de aplicação. Sem usuário conectado, o conteúdo fica preparado para o próximo logon.

Estrutura do projeto

WallpaperAgent/
|-- Agent/
|   |-- Apply-Wallpaper.ps1
|   `-- Update-Wallpaper.ps1
|-- Intune/
|   |-- Detect-WallpaperAgent.ps1
|   `-- Detect-WallpaperAgent.template.ps1
|-- docs/
|   |-- ARCHITECTURE.md
|   |-- CONFIGURATION.md
|   |-- INTUNE.md
|   `-- MANIFEST.md
|-- WallpaperAgent.Config.psd1
|-- WallpaperAgent.Helpers.psm1
|-- Install-WallpaperAgent.ps1
|-- Uninstall-WallpaperAgent.ps1
|-- Test-WallpaperAgent.ps1
|-- Get-WallpaperAgentDiagnostics.ps1
|-- Build-WallpaperAgentPackage.ps1
|-- Install.cmd
|-- Uninstall.cmd
|-- Install.ps1
|-- Uninstall.ps1
|-- Diagnostics.ps1
|-- CHANGELOG.md
`-- README.md

Os arquivos Install.ps1, Uninstall.ps1 e Diagnostics.ps1 são wrappers de compatibilidade com os nomes do projeto anterior.

1. Preparar a configuração

Antes de instalar, crie o repositório separado de conteúdo e edite WallpaperAgent.Config.psd1:

OrganizationName = 'orgname'
AgentVersion = '1.0.0'

RepositoryOwner = 'github-owner'
RepositoryName = 'WallpaperContent'
RepositoryBranch = 'main'
RepositoryManifestPath = 'windows/manifest.json'
PublisherTokenEnvironmentVariable = 'WALLPAPER_REPOSITORY_TOKEN'

ManifestUrl = ''
CheckIntervalMinutes = 15

Deixe ManifestUrl vazio para gerar a URL pública a partir da configuração do repositório. Use um valor explícito somente para um proxy, CDN ou endpoint HTTPS diferente do GitHub Raw.

2. Validar o pacote

Abra o Windows PowerShell 5.1 e execute:

Set-ExecutionPolicy -Scope Process Bypass -Force
.\Test-WallpaperAgent.ps1

Para validar também o manifesto remoto:

.\Test-WallpaperAgent.ps1 -TestManifest

A validação verifica a configuração, os arquivos do pacote, a plataforma Windows, arquitetura de 64 bits, Scheduled Tasks, System.Drawing e Windows Runtime.

3. Instalar localmente

Abra o Windows PowerShell como administrador:

Set-ExecutionPolicy -Scope Process Bypass -Force
.\Install-WallpaperAgent.ps1 -ForceConfig

Também é possível usar:

.\Install.ps1 -ForceConfig

ou:

Install.cmd

-ForceConfig substitui a configuração instalada pela configuração do pacote. Sem esse parâmetro, uma configuração já instalada é preservada durante a atualização.

Para instalar sem tentar baixar o primeiro release imediatamente:

.\Install-WallpaperAgent.ps1 -ForceConfig -SkipInitialUpdate

4. Validar a instalação

.\Test-WallpaperAgent.ps1 -TestInstalledState

Confirme também as tarefas:

Get-ScheduledTask -TaskPath '\orgname\' |
    Select-Object TaskName, State

O caminho real depende de OrganizationName ou de uma sobrescrita em TaskPath.

5. Diagnóstico

.\Get-WallpaperAgentDiagnostics.ps1

Ou pelo comando compatível:

.\Diagnostics.ps1

O diagnóstico mostra:

  • configuração resolvida;
  • chave de registro de detecção;
  • estado e último resultado das tarefas;
  • status.json;
  • release atual;
  • log de instalação;
  • log do updater;
  • log de aplicação do usuário atual.

Caminhos gerados

Com OrganizationName = 'orgname':

C:\ProgramData\orgname\WallpaperAgent\
|-- Agent\
|   |-- Apply-Wallpaper.ps1
|   |-- Update-Wallpaper.ps1
|   |-- WallpaperAgent.Config.psd1
|   `-- WallpaperAgent.Helpers.psm1
|-- Assets\
|   |-- Desktop\
|   `-- LockScreen\
|-- State\
|   |-- current.json
|   |-- manifest.json
|   `-- status.json
`-- Logs\
    |-- install.log
    `-- update.log

Dados por usuário:

%LOCALAPPDATA%\orgname\WallpaperAgent\
|-- current.json
`-- Logs\apply.log

Comportamento esperado

  • uma nova release é detectada no intervalo configurado;
  • os arquivos só substituem o conteúdo anterior após validação completa;
  • falha de rede, JSON inválido, hash incorreto ou imagem corrompida não remove o release funcional;
  • sem usuário conectado, o download ocorre normalmente e a aplicação é feita no próximo logon;
  • alterações manuais de wallpaper ou lock screen são corrigidas na próxima execução da tarefa de aplicação;
  • logs são rotacionados para um arquivo .1 quando atingem o limite configurado.

Empacotamento para Intune

Gere uma área limpa de empacotamento:

.\Build-WallpaperAgentPackage.ps1

A saída será criada em:

Build\WallpaperAgent-{AgentVersion}\
|-- Source\
|-- Detection\Detect-WallpaperAgent.ps1
|-- IntuneWin\
`-- WallpaperAgent-{AgentVersion}-Source.zip

Para também gerar o .intunewin:

.\Build-WallpaperAgentPackage.ps1 `
    -IntuneWinAppUtilPath 'C:\Tools\IntuneWinAppUtil.exe'

Configuração recomendada do aplicativo Win32:

Campo Valor
Install command Install.cmd
Uninstall command Uninstall.cmd
Install behavior System
Device restart behavior No specific action
Architecture 64-bit
Detection rules Use a custom detection script
Detection script arquivo gerado em Detection\Detect-WallpaperAgent.ps1
Run as 32-bit on 64-bit clients No
Enforce script signature check No, até os scripts serem assinados

O script de detecção gerado contém a versão esperada do pacote, mas não contém o nome da organização. Ele localiza a instalação pela chave ProductCode = WallpaperAgent e valida os arquivos e tarefas registrados.

Desinstalação

Por padrão, a desinstalação mantém Assets para evitar que o Windows continue apontando para uma imagem removida:

.\Uninstall-WallpaperAgent.ps1 -Confirm:$false

Para visualizar antes:

.\Uninstall-WallpaperAgent.ps1 -WhatIf

Para remover também os assets:

.\Uninstall-WallpaperAgent.ps1 -RemoveAssets -Confirm:$false

O Uninstall.cmd usa o modo não interativo e preserva os assets.

Segurança

  • somente URLs HTTPS são aceitas;
  • o nome do arquivo do asset não pode conter caminho relativo ou absoluto;
  • somente .jpg, .jpeg e .png são aceitos;
  • cada arquivo é validado por SHA-256 antes da ativação;
  • o arquivo baixado é validado como imagem;
  • há limites de tamanho para manifesto e assets;
  • downloads usam arquivo temporário e promoção atômica;
  • o updater executa como SYSTEM, enquanto a aplicação ocorre no contexto interativo;
  • a pasta de instalação concede controle total apenas a SYSTEM e Administradores; usuários recebem leitura e execução.

Atualização de versão

Ao publicar uma nova versão:

  1. altere AgentVersion em WallpaperAgent.Config.psd1;
  2. atualize CHANGELOG.md;
  3. execute Build-WallpaperAgentPackage.ps1;
  4. use o novo .intunewin e o script correspondente em Detection;
  5. atribua primeiro ao grupo piloto.

Consulte os arquivos da pasta docs para detalhes de configuração, arquitetura, manifesto e Intune.