Avvertenza: il codice di questa soluzione si trova anche su Github.
Dover installare da remoto una app UWP, ossia le app dello store di Microsoft, in Windows 10 e successivi è una delle cose più facili da fare, se si dispone di Intune.
Purtroppo, non è sempre possibile averlo a disposizione e bisogna quindi attrezzarsi diversamente. Nel mio caso, dovevo fare il deploy di una applicazione UWP di terze parti (Satispay), disponibile sullo store di Microsoft e regolarmente firmata, su una serie di pc con Windows 10 e 11 membri di un dominio AD.
Il problema che si poneva era quello di dover eseguire il deploy impersonando l’utente del pc, dato che la app non supporta installazione in scope machine (ossia per tutti gli utenti della macchina).
Ho dovuto trovare una soluzione “creativa” e quello che ho deciso quindi di fare è stato usare due script per queste due attività:
- Copiare sul computer di destinazione lo script che esegue il deploy della app vero e proprio e creare un task schedulato che lancerà questo script nel contesto dell’utente correntemente loggato.
- Installare la app in contesto utente tramite il task schedulato e creare un collegamento sul desktop.
Per l’installazione si può usare o Winget oppure la cmdlet di PowerShell Add-AppxPackage, avendo cura di scaricare prima il pacchetto di installazione. Io ho scelto quest’ultima via, dato che non ero certo che tutte le macchine avessero una versione aggiornata di Winget e non avevo tempo di curare prima l’aggiornamento di Winget.
Va quindi scaricato il pacchetto e per fare questo basta andare sul sito dello Store e cercare la nostra app. Copiamo poi la URL della app, che deve avere un formato del genere, https://apps.microsoft.com/detail/<id app> , eliminando dalla URL il superfluo.
Andare poi su https://store.rg-adguard.net/ , inserire la URL e si otterrà poi la lista di link per il download del pacchetto:
Si può quindi fare il download del pacchetto e salvarlo su una cartella condivisa di un fileserver, raggiungibile dai computer che dovranno installare l’app. Nella stessa cartella condivisa va messo anche lo script che sarà eseguito tramite task pianificato, ossia questo:
#Script Install-AppX.ps1
$packagePath = "\\server\folder\Satispay\D2E55FCB.SatispaySpot-Business_5.4.1.0_neutral_~_dng634rsnwf7y.AppxBundle"
#Installazione con pacchetto locale - commentare la riga seguente se si usa Winget
Add-AppxPackage -Path $packagePath
#Installazione con Winget - decommentare la riga seguente per usarla
#winget install -h -e --id=9NBLGGH4VVMV --accept-package-agreements --accept-source-agreements
#Creazione shortcut su desktop
$TargetPath = "shell:AppsFolder\D2E55FCB.SatispaySpot-Business_dng634rsnwf7y!App"
$ShortcutFile = "$Home\Desktop\Satispay.lnk"
$WScriptShell = New-Object -ComObject WScript.Shell
$Shortcut = $WScriptShell.CreateShortcut($ShortcutFile)
$Shortcut.TargetPath = $TargetPath
$Shortcut.Save()
Lo script è davvero basilare, basta specificare il path del pacchetto di installazione in $packagePath e customizzare le righe per la creazione della shortcut sul desktop in base alla app da installare. Al posto di creare la shortcut, si può anche prendere il file LNK da una macchina campione, metterlo nella share e copiarlo sul desktop della macchina di destinazione con Copy-Item.
L’installazione vera e propria viene eseguita dalla cmdlet Add-AppxPackage, ma ho incluso anche il comando di Winget per fare il setup via internet (va cambiato opportunamente l’ID della applicazione però), in caso vogliate usare questa strada ed abbiate Winget aggiornato sulle macchine.
Sulla nostra workstation invece creeremo questo script, che sarà eseguito sui computer target con Invoke-Command. Lo script crea sul target una cartella C:\Scripts (cambiate come preferite, se necessario) e ci copia lo script che abbiamo visto sopra, per poi creare un task schedulato “one-shot” che viene eseguito una sola volta dopo un minuto dall’esecuzione dello script:
#Script Create-TaskInstallAppX.ps1
#Preparazione della cartella per lo script e copia del file
If (!(Test-Path -Path C:\Scripts))
{
New-Item -ItemType directory -Path C:\Scripts
}
New-PSDrive -Name S -PSProvider FileSystem -Root "\\server\folder\Satispay" -Credential $using:creds
Copy-Item -Path "S:\Install-AppX.ps1" -Destination C:\Scripts -Force
#Selezione dell'utente loggato in console per l'esecuzione del task
$user = (Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object username).username
$computer = $env:COMPUTERNAME
#Impostazione dell'ora di esecuzione del task a +1 minuto dall'esecuzione dello script
$time = (Get-Date).AddMinutes(1).ToString('HH:mm')
#Creazione del task schedulato
schtasks /create /s $computer /tn "Install-Satispay" /sc once /tr "powershell.exe -ExecutionPolicy bypass -WindowStyle hidden -file C:\Scripts\Install-AppX.ps1" /st $time /ru $user
Avvertenza 1: lo script qui sopra non è in grado di recuperare il nome utente se l’utente è loggato in RDP, funziona solo per i login in console, ma nel mio caso era perfetto per l’uso. In una versione futura magari aggiungerò anche qualcosa per venire incontro a questo problema.
Come posso poi eseguire il tutto su più computer? Possiamo usare qualche riga di PowerShell sulla nostra workstation, come queste:
#Specifico un file di testo con i nomi dei pc, uno per riga
$targets = Get-Content -Path "C:\Scripts\targets\targets.txt"
#Specifico le credenziali amministrative per l'esecuzione del comando sui target
$creds = Get-Credential
#Eseguo lo script, attenzione al path e al nome dello script
foreach ($target in $targets)
{
Invoke-Command -FilePath C:\Scripts\Create-TaskInstallAppX.ps1 -ComputerName $target -Credential $creds -Verbose
}
Avvertenza 2: dovete disporre di credenziali amministrative sui pc target e deve essere stato abilitato il remoting di PowerShell per poter lanciare lo script con Invoke-Command!
Avrei potuto passare anche tutti i nomi computer al parametro ComputerName (nel formato “pc1, pc2, pc3, etc.”), ma – dato che erano diverse decine di macchine, questa soluzione mi pareva migliore… ma forse è solo una preferenza personale.
Non è da intendersi come alternativa alla software distribution, sia chiaro, ma come tool in caso di un’esigenza estemporanea può avere il suo senso.
Testatelo sempre su un pilota di pochi computer prima di lanciarlo in produzione!