Deploy FSLogix automatically through domain policy
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
#Requires -Version 5.1
|
||||
[CmdletBinding(SupportsShouldProcess)]
|
||||
param(
|
||||
[string]$GpoName = 'SGU - FSLogix client deployment',
|
||||
[string]$LaboratoryOuDn,
|
||||
[uri]$InstallerZipUri = 'https://download.microsoft.com/download/ae6d2014-e692-45fa-a88b-ee552567cdc1/FSLogix_26.08.zip',
|
||||
[string]$ExpectedInstallerSha256 = '0BAF7FE8195571060F0361B351E58FE6CD422AE521A96BAB3E66D900544E8A30',
|
||||
[string]$CacheRoot = "$env:ProgramData\SGU\FSLogixDeployment\26.08"
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$principal = [Security.Principal.WindowsPrincipal]::new($identity)
|
||||
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
||||
throw 'Run the FSLogix GPO deployment from an elevated Windows PowerShell session.'
|
||||
}
|
||||
Import-Module ActiveDirectory -ErrorAction Stop
|
||||
Import-Module GroupPolicy -ErrorAction Stop
|
||||
|
||||
$domain = Get-ADDomain
|
||||
$domainName = $domain.DNSRoot
|
||||
$domainDn = $domain.DistinguishedName
|
||||
if (-not $LaboratoryOuDn) { $LaboratoryOuDn = "OU=Laboratorio,$domainDn" }
|
||||
Get-ADOrganizationalUnit -Identity $LaboratoryOuDn -ErrorAction Stop | Out-Null
|
||||
|
||||
$zipPath = Join-Path $CacheRoot 'FSLogix_26.08.zip'
|
||||
$extractRoot = Join-Path $CacheRoot 'expanded'
|
||||
$installerPath = Join-Path $extractRoot 'x64\Release\FSLogixAppsSetup.exe'
|
||||
if (-not (Test-Path -LiteralPath $installerPath -PathType Leaf)) {
|
||||
if (-not $PSCmdlet.ShouldProcess($InstallerZipUri.AbsoluteUri, "Download official FSLogix package to $zipPath")) { return }
|
||||
New-Item -ItemType Directory -Path $CacheRoot,$extractRoot -Force | Out-Null
|
||||
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
|
||||
Invoke-WebRequest -Uri $InstallerZipUri -OutFile $zipPath -UseBasicParsing
|
||||
Expand-Archive -LiteralPath $zipPath -DestinationPath $extractRoot -Force
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $installerPath -PathType Leaf)) {
|
||||
throw "The FSLogix x64 installer is missing after extraction: $installerPath"
|
||||
}
|
||||
$signature = Get-AuthenticodeSignature -LiteralPath $installerPath
|
||||
if ($signature.Status -ne [Management.Automation.SignatureStatus]::Valid -or
|
||||
-not $signature.SignerCertificate -or
|
||||
$signature.SignerCertificate.Subject -notmatch '(^|,\s*)CN=Microsoft Corporation(,|$)') {
|
||||
throw 'FSLogixAppsSetup.exe does not have a valid Microsoft Corporation signature.'
|
||||
}
|
||||
$installerHash = (Get-FileHash -LiteralPath $installerPath -Algorithm SHA256).Hash
|
||||
if ($installerHash -ne $ExpectedInstallerSha256) {
|
||||
throw "FSLogixAppsSetup.exe SHA-256 mismatch. Expected $ExpectedInstallerSha256; received $installerHash."
|
||||
}
|
||||
|
||||
$gpo = Get-GPO -Name $GpoName -Domain $domainName -ErrorAction SilentlyContinue
|
||||
if (-not $gpo) { $gpo = New-GPO -Name $GpoName -Domain $domainName }
|
||||
$links = @(Get-GPInheritance -Target $LaboratoryOuDn -Domain $domainName).GpoLinks
|
||||
if (-not ($links | Where-Object DisplayName -eq $GpoName)) {
|
||||
New-GPLink -Name $GpoName -Target $LaboratoryOuDn -Domain $domainName -LinkEnabled Yes | Out-Null
|
||||
}
|
||||
|
||||
# Set one ordinary machine value through the supported cmdlet. Besides providing
|
||||
# a deployment marker, this initializes the computer half of the GPO and its
|
||||
# Registry client-side extension before the Scripts extension is added below.
|
||||
Set-GPRegistryValue -Name $GpoName -Domain $domainName `
|
||||
-Key 'HKLM\SOFTWARE\SGU\FSLogixDeployment' -ValueName 'Version' `
|
||||
-Type String -Value '26.08-3.26.826.17182' | Out-Null
|
||||
$gpo = Get-GPO -Name $GpoName -Domain $domainName
|
||||
$guid = $gpo.Id.ToString('B').ToUpperInvariant()
|
||||
$gpoRoot = "\\$domainName\SYSVOL\$domainName\Policies\$guid"
|
||||
$scriptsRoot = Join-Path $gpoRoot 'Machine\Scripts'
|
||||
$startupRoot = Join-Path $scriptsRoot 'Startup'
|
||||
New-Item -ItemType Directory -Path $startupRoot -Force | Out-Null
|
||||
Copy-Item -LiteralPath $installerPath -Destination (Join-Path $startupRoot 'FSLogixAppsSetup.exe') -Force
|
||||
|
||||
$startupPowerShell = @'
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$appsRoot = Join-Path $env:ProgramFiles 'FSLogix\Apps'
|
||||
$frx = Join-Path $appsRoot 'frx.exe'
|
||||
if ((Get-Service frxsvc -ErrorAction SilentlyContinue) -and (Test-Path -LiteralPath $frx)) { exit 0 }
|
||||
$source = Join-Path $PSScriptRoot 'FSLogixAppsSetup.exe'
|
||||
$signature = Get-AuthenticodeSignature -LiteralPath $source
|
||||
if ($signature.Status -ne 'Valid' -or -not $signature.SignerCertificate -or
|
||||
$signature.SignerCertificate.Subject -notmatch '(^|,\s*)CN=Microsoft Corporation(,|$)') { exit 10 }
|
||||
$targetRoot = Join-Path $env:ProgramData 'SGU\FSLogix'
|
||||
New-Item -ItemType Directory -Path $targetRoot -Force | Out-Null
|
||||
$target = Join-Path $targetRoot 'FSLogixAppsSetup.exe'
|
||||
Copy-Item -LiteralPath $source -Destination $target -Force
|
||||
$log = Join-Path $targetRoot 'install.log'
|
||||
$process = Start-Process -FilePath $target -ArgumentList @('/install','/quiet','/norestart','/log',"`"$log`"") -Wait -PassThru
|
||||
if ($process.ExitCode -notin @(0,1641,3010)) { exit $process.ExitCode }
|
||||
if (-not (Get-Service frxsvc -ErrorAction SilentlyContinue) -or -not (Test-Path -LiteralPath $frx)) { exit 11 }
|
||||
exit 0
|
||||
'@
|
||||
[IO.File]::WriteAllText(
|
||||
(Join-Path $startupRoot 'Install-SguFsLogix-Startup.ps1'),
|
||||
$startupPowerShell,
|
||||
[Text.UTF8Encoding]::new($true))
|
||||
$startupCommand = '@echo off' + [Environment]::NewLine +
|
||||
'powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File "%~dp0Install-SguFsLogix-Startup.ps1"' + [Environment]::NewLine +
|
||||
'exit /b %ERRORLEVEL%' + [Environment]::NewLine
|
||||
[IO.File]::WriteAllText(
|
||||
(Join-Path $startupRoot 'Install-SguFsLogix.cmd'),
|
||||
$startupCommand,
|
||||
[Text.Encoding]::ASCII)
|
||||
$scriptsIni = "[Startup]`r`n0CmdLine=Install-SguFsLogix.cmd`r`n0Parameters=`r`n"
|
||||
[IO.File]::WriteAllText(
|
||||
(Join-Path $scriptsRoot 'scripts.ini'),
|
||||
$scriptsIni,
|
||||
[Text.Encoding]::Unicode)
|
||||
|
||||
$policyDn = "CN=$guid,CN=Policies,CN=System,$domainDn"
|
||||
$policy = Get-ADObject -Identity $policyDn -Properties versionNumber,gPCMachineExtensionNames
|
||||
$scriptExtension = '[{42B5FAAE-6536-11D2-AE5A-0000F87571E3}{40B6664F-4972-11D1-A7CA-0000F87571E3}]'
|
||||
$extensions = @([regex]::Matches([string]$policy.gPCMachineExtensionNames, '\[\{[0-9A-Fa-f-]{36}\}\{[0-9A-Fa-f-]{36}\}\]') |
|
||||
ForEach-Object Value)
|
||||
if ($extensions -notcontains $scriptExtension) { $extensions += $scriptExtension }
|
||||
$extensionValue = ($extensions | Sort-Object { $_.Substring(1, 38) }) -join ''
|
||||
$currentVersion = [int64]$policy.versionNumber
|
||||
$machineVersion = $currentVersion -band 0xFFFF
|
||||
if ($machineVersion -ge 65535) { throw 'The computer GPO version cannot be incremented further.' }
|
||||
$newVersion = ($currentVersion -band 0xFFFF0000) -bor ($machineVersion + 1)
|
||||
$gptIniPath = Join-Path $gpoRoot 'gpt.ini'
|
||||
$gptLines = @(Get-Content -LiteralPath $gptIniPath)
|
||||
$versionFound = $false
|
||||
$gptLines = @($gptLines | ForEach-Object {
|
||||
if ($_ -match '^Version=') { $versionFound = $true; "Version=$newVersion" } else { $_ }
|
||||
})
|
||||
if (-not $versionFound) { $gptLines += "Version=$newVersion" }
|
||||
[IO.File]::WriteAllLines($gptIniPath, $gptLines, [Text.Encoding]::ASCII)
|
||||
Set-ADObject -Identity $policy -Replace @{
|
||||
gPCMachineExtensionNames = $extensionValue
|
||||
versionNumber = [int]$newVersion
|
||||
}
|
||||
|
||||
$verifiedGpo = Get-GPO -Name $GpoName -Domain $domainName
|
||||
[pscustomobject]@{
|
||||
GpoName = $verifiedGpo.DisplayName
|
||||
GpoId = $verifiedGpo.Id
|
||||
LaboratoryOuDn = $LaboratoryOuDn
|
||||
MachineVersion = $verifiedGpo.Computer.DSVersion
|
||||
InstallerVersion = '3.26.826.17182'
|
||||
InstallerSha256 = $installerHash
|
||||
StartupScript = Join-Path $startupRoot 'Install-SguFsLogix.cmd'
|
||||
}
|
||||
Reference in New Issue
Block a user