Microsoft FSLogix Profile Container

Nach dem Aufkauf von FSLogix hier ein kleines How-To zum Einrichten der FSLogix Profile Container zur Nutzung in einer Microsoft Remotedesktop-Sammlung oder auch in einem Citrix Virtual Apps and Desktop Deployment.

Welche Betriebssysteme werden supported?

  • Desktop: ab Windows 7 (32- / 64-Bit)
  • Server: ab 2008 R2 (32- / 64-Bit)

Wer darf die Profile Container bzw. die FSLogix Suite nutzen?

  • Microsoft 365 E3/E5
  • Microsoft 365 A3/A5/ Student Use Benefits
  • Microsoft 365 F1
  • Microsoft 365 Business
  • Windows 10 Enterprise E3/E5
  • Windows 10 Education A3/A5
  • Windows 10 VDA per user
  • Remote Desktop Services (RDS) Client Access License (CAL)*
  • Remote Desktop Services (RDS) Subscriber Access License (SAL)

* Die RDS (User / Device) CAL dürfte für die On-Prem-Freunde von Interesse sein, um die Container in einer lokal gehosteten (RDSH / CVAD / Horizon) Umgebung zu nutzen.

Wo finde ich die FSLogix Apps? -> https://aka.ms/fslogix_download

Hier noch ein Hinweis: Ich versuche hier so viel wie möglich bzw. das meiste zu automatisieren / zu scripten. Das liegt zum Einen daran, dass ich diesen Task vermutlich des Öfteren wiederholen muss und zum Anderen plane ich ein „kleines“ Deployment-Script. 😉 Für die Freunde der GUI wäre evtl. das folgende Hersteller Video ein Ansatz: http://blog.fslogix.com/deployment-guide-video-for-fslogix-profile-containers-and-office-365-containers

An dieser Stelle fange ich damit an, eine entsprechende Freigabe zur Ablage der späteren Profile Container zu erstellen. Wenn möglich würde ich an dieser Stelle auf das ReFS Dateisystem setzen! Das kann man sich in der GUI zusammenklicken („Benutzer (S-1-5-32-545)“; Nur diesen Ordner; Ändern / „Ersteller Besitzer (S-1-3-0)“; Unterordner und Dateien; Ändern / Optional: „Administratoren (S-1-5-32-544)“; Dieser Ordner, Unterordner und Dateien; Vollzugriff) oder auch flott per PowerShell erledigen:

$FSLogixStore = "D:\FSLogixStore"
$FSLogixShare = "FSLogixStore"
$FslogixHost = "jans-dc01"
$FSLogixSetup = "\\" + $FslogixHost + "\Install\FSLogix_Apps_2.9.7117.27413"
$FSLogixO365Group = "grp_O365_Container"
$FSLogixProfileGroup = "grp_Profile_Container"
$FSLogixPolicy = "C_FSLogix_Config"

$IcaclsPath = "C:\Windows\System32\icacls.exe"

Enable-NetFirewallRule -Name FPS-SMB-In-TCP, FPS-SMB-Out-TCP

if(!(Test-Path $FSLogixStore)){
    New-Item -Path $FSLogixStore -ItemType Directory | Out-Null
} else{
    Write-Host "ACHTUNG: Berechtigungen für ""$FSLogixStore"" wird zurückgesetzt!" -ForegroundColor Red
}
Start-Process -FilePath $IcaclsPath -ArgumentList $($FSLogixStore + " /inheritance:d /T /C /Q") -Wait
Start-Process -FilePath $IcaclsPath -ArgumentList $($FSLogixStore + " /remove:g *S-1-3-0 /remove:g *S-1-5-18 /remove:g *S-1-5-32-545 /grant:r *S-1-5-32-544:(OI)(CI)(F) /grant:r *S-1-5-32-545:(M) /grant:r *S-1-3-0:(OI)(CI)(IO)(M) /T /C /Q") -Wait
if(!(Get-SmbShare | ? Name -eq $FSLogixShare)){
    New-SmbShare -Name $FSLogixShare -Path $FSLogixStore -FullAccess *S-1-5-11 -CachingMode None -Description "FSLogix Profildaten" | Out-Null
} else{
    Write-Host "ACHTUNG: Der Freigabe ""$FSLogixShare"" wird ""Authentifizerte Benutzer - Vollzugriff"" hinzugefügt!" -ForegroundColor Red
    Grant-SmbShareAccess -Name $FSLogixShare -AccountName *S-1-5-11 -AccessRight Full -Confirm:$false
}

Als weitere Vorbereitung ist es hilfreich entsprechende Gruppen und ein Gruppenrichtlinien-Objekt zur Nutzung der Profile Container vorzubereiten. Ebenfalls werden das ADMX / ADML File in den PolicyDefintions Ordner kopiert. Anbei ein PowerShell Script zum Erstellen der, in meinem Fall zwei, benötigten Gruppen („grp_O365_Container“ / „grp_Profile_Container“) sowie dem GPO („C_FSLogix_Config“) samt Konfiguration:

$FSLogixStore = "D:\FSLogixStore"
$FSLogixShare = "FSLogixStore"
$FslogixHost = "jans-dc01"
$FSLogixSetup = "\\" + $FslogixHost + "\Install\FSLogix_Apps_2.9.7117.27413"
$FSLogixO365Group = "grp_O365_Container"
$FSLogixProfileGroup = "grp_Profile_Container"
$FSLogixPolicy = "C_FSLogix_Config"

if(!(Test-Path \\$env:UserDNSDomain\sysvol\$env:UserDNSDomain\Policies\)){
    Copy-Item C:\Windows\PolicyDefinitions \\$env:UserDNSDomain\sysvol\$env:UserDNSDomain\Policies\ -Recurse
}
Copy-Item $($FSLogixSetup + "\fslogix.adml") \\$env:UserDNSDomain\sysvol\$env:UserDNSDomain\Policies\PolicyDefinitions\en-US\
Copy-Item $($FSLogixSetup + "\fslogix.adml") \\$env:UserDNSDomain\sysvol\$env:UserDNSDomain\Policies\PolicyDefinitions\de-DE\
Copy-Item $($FSLogixSetup + "\fslogix.admx") \\$env:UserDNSDomain\sysvol\$env:UserDNSDomain\Policies\PolicyDefinitions\

$GroupOU = Get-ADOrganizationalUnit -Filter * | Select-Object Name, DistinguishedName | Out-GridView -Title "In welcher OU sollen die beiden Gruppen angelegt werden?" -PassThru
$GroupOU = Get-ADOrganizationalUnit $GroupOU.DistinguishedName
$RDSHOU = Get-ADOrganizationalUnit -Filter * | Select-Object Name, DistinguishedName | Out-GridView -Title "Wo befinden sich die Session-Hosts / Desktops?" -PassThru
$RDSHOU = Get-ADOrganizationalUnit $RDSHOU.DistinguishedName

New-ADGroup -Name $FSLogixO365Group -DisplayName $FSLogixO365Group -Description "FSLogix Office 365 Container User" -Path $GroupOU.DistinguishedName -GroupCategory Security -GroupScope DomainLocal
New-ADGroup -Name $FSLogixProfileGroup -DisplayName $FSLogixProfileroup -Description "FSLogix Profile Container User" -Path $GroupOU.DistinguishedName -GroupCategory Security -GroupScope DomainLocal

$GPOObject = New-GPO $FSLogixPolicy | New-GPLink -Target $RDSHOU.DistinguishedName -LinkEnabled Yes

# Profile Container
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\FSLogix\Profiles" -ValueName "Enabled" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\FSLogix\Profiles" -ValueName "IsDynamic" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\FSLogix\Profiles" -ValueName "SizeInMBs" -Value 5000 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\FSLogix\Profiles" -ValueName "RoamSearch" -Value 2 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\FSLogix\Profiles" -ValueName "VHDLocations" -Value $("\\" + $FslogixHost + "\" + $FSLogixShare) -Type String | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\FSLogix\Profiles" -ValueName "VolumeType" -Value "VHDX" -Type String | Out-Null

# Office Container
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "Enabled" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "IsDynamic" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "SizeInMBs" -Value 5000 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "IncludeSkype" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "IncludeTeams" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "IncludeOneNote" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "IncludeOutlook" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "IncludeOfficeActivation" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "IncludeOneDrive" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "IncludeSharepoint" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "IncludeOfficeFileCache" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "IncludeOutlookPersonalization" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "IncludeOneNote_UWP" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "OutlookCachedMode" -Value 1 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "RoamSearch" -Value 2 -Type DWord | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "VHDLocations" -Value $("\\" + $FslogixHost + "\" + $FSLogixShare) -Type String | Out-Null
Set-GPRegistryValue -Name $FSLogixPolicy -Key "HKLM\Software\Policies\FSLogix\ODFC" -ValueName "VolumeType" -Value "VHDX" -Type String | Out-Null

# Group Policy Preferences Gruppen
New-Item $("\\" + $env:USERDNSDOMAIN + "\SYSVOL\" + $env:USERDNSDOMAIN + "\Policies\{" + $GPOObject.GpoId + "}\Machine\Preferences\Groups\Groups.xml") -ItemType File -Force | Out-Null
"<?xml version=""1.0"" encoding=""utf-8""?>" | Out-File $("\\" + $env:USERDNSDOMAIN + "\SYSVOL\" + $env:USERDNSDOMAIN + "\Policies\{" + $GPOObject.GpoId + "}\Machine\Preferences\Groups\Groups.xml") -Encoding utf8
"<Groups clsid=""{3125E937-EB16-4b4c-9934-544FC6D24D26}""><Group clsid=""{6D4A79E4-529C-4481-ABD0-F5BD7EA93BA7}"" name=""FSLogix ODFC Include List"" image=""2"" changed=""$(Get-Date -Format "yyyy-MM-dd HH:mm:ss")"" uid=""{7D296515-BA25-452D-85A5-B1DB2580B2D5}""><Properties action=""U"" newName="""" description=""Members of this group are on the include list for Outlook Data Folder Containers"" deleteAllUsers=""1"" deleteAllGroups=""1"" removeAccounts=""0"" groupSid="""" groupName=""FSLogix ODFC Include List""><Members><Member name=""%DomainName%\$FSLogixO365Group"" action=""ADD"" sid=""""/></Members></Properties></Group>" | Out-File $("\\" + $env:USERDNSDOMAIN + "\SYSVOL\" + $env:USERDNSDOMAIN + "\Policies\{" + $GPOObject.GpoId + "}\Machine\Preferences\Groups\Groups.xml") -Encoding utf8 -Append
"	<Group clsid=""{6D4A79E4-529C-4481-ABD0-F5BD7EA93BA7}"" name=""FSLogix Profile Include List"" image=""2"" changed=""$(Get-Date -Format "yyyy-MM-dd HH:mm:ss")"" uid=""{6C2B4A05-A5F4-43E3-8F12-1C80538C2C6A}""><Properties action=""U"" newName="""" description=""Members of this group are on the include list for dynamic profiles"" deleteAllUsers=""1"" deleteAllGroups=""1"" removeAccounts=""0"" groupSid="""" groupName=""FSLogix Profile Include List""><Members><Member name=""%DomainName%\$FSLogixProfileGroup"" action=""ADD"" sid=""""/></Members></Properties></Group>" | Out-File $("\\" + $env:USERDNSDOMAIN + "\SYSVOL\" + $env:USERDNSDOMAIN + "\Policies\{" + $GPOObject.GpoId + "}\Machine\Preferences\Groups\Groups.xml") -Encoding utf8 -Append
"</Groups>" | Out-File $("\\" + $env:USERDNSDOMAIN + "\SYSVOL\" + $env:USERDNSDOMAIN + "\Policies\{" + $GPOObject.GpoId + "}\Machine\Preferences\Groups\Groups.xml") -Encoding utf8 -Append

Kommen wir als nächstes zur Installation der FSLogix Suite auf dem / den Session-Hosts / Desktops bzw. im „Golden-Image“. Erneut bleibt die unspektakuläre Möglichkeit zum Klicken in der GUI (langweilig!) oder per PowerShell Script.

$FSLogixStore = "D:\FSLogixStore"
$FSLogixShare = "FSLogixStore"
$FslogixHost = "jans-dc01"
$FSLogixSetup = "\\" + $FslogixHost + "\Install\FSLogix_Apps_2.9.7117.27413"
$FSLogixO365Group = "grp_O365_Container"
$FSLogixProfileGroup = "grp_Profile_Container"
$FSLogixPolicy = "C_FSLogix_Config"

if(Test-Path $($FSLogixSetup + "\x64\Release\FSLogixAppsSetup.exe")){
    Start-Process -FilePath $($FSLogixSetup + "\x64\Release\FSLogixAppsSetup.exe") -ArgumentList $("/install /quiet /norestart /log " + $FSLogixSetup + "\FSLogix_Log.txt") -Wait
}

Nach einem ggfs. benötigten Reboot finden sich auf dem Host die folgenden Gruppen zur späteren Steuerung der Container wieder:

  • FSLogix ODFC Exclude List
  • FSLogix ODFC Include List (Standardmäßig ist hier „Jeder“ / „Everyone“ bzw. „S-1-1-0“ Mitglied)
  • FSLogix Profile Exclude List
  • FSLogix Profile Include List (Standardmäßig ist hier „Jeder“ / „Everyone“ bzw. „S-1-1-0“ Mitglied)

Sollte die Richtlinie wie oben in meinem Beispiel verwendet worden sein, befindet sich „\Jeder“ nicht mehr in den beiden Gruppen, sondern die, ebenfalls oben erstellten, Gruppen darin. Wenn bis hierher nichts vollkommen daneben gegangen ist, sollte eine Testanmeldung möglich sein. Bei der Anmeldung sollten dann auch die entsprechenden Container erstellt werden – Yay 🙂 !

Beteilige dich an der Unterhaltung

5 Kommentare

  1. Super Scripte!
    Läuft alles bis auf das Entfernen der Gruppe „.\Jeder“ in den lokalen Gruppen. Server ist 2016. Die „groups.xml“ wird im richtigen Policy-Verzeichnis erstellt. Woran kann das liegen?

    1. Hi,
      hast du mal in das GPO geguckt und geprüft, ob da auch alles i.O. ist? Bzw. werden die neuen Gruppen Mitglied und nur „.\Jeder“ wird nicht entfernt?
      Generell würde ich hier aber Punkt 4 aus https://jans.cloud/2019/08/gruppenrichtlinien-mit-powershell-bearbeiten/ berücksichtigen und mir ein passendes GPO erstellen, dann sichern, in die Zielumgebung(en) importieren und anschließend bearbeiten. Den GPP Teil kann ich ja dank Variablen eh schon dynamisch halten.
      Viele Grüße
      Jan

      1. Die GPO an sich wird richtig befüllt; auch unter Computerkonfiguration => Einstellungen => Systemsteuerungseinstellungen => Benutzer und Gruppen steht alles richtig drin; wenn ich dort via GPEditor die Gruppen händisch entferne und neu hinzufüge funktioniert die GPO auch. Dabei ist mir aufgefallen, dass in der Groups.xml die SID der Gruppe nicht gefüllt ist, wenn diese über das Script erstellt wird.

        1. Das die SID fehlt ist soweit korrekt, da die SID nur aufgelöst wird wenn du über die „…“ hinzufügst. In dem Eingabefeld kannst du z.B. „F3“ drücken und verschiedene Variablen sehen und nutzen bzw. einfach reinschreiben. In dem Fall wird die SID eben nicht aufgelöst. Findet sich auf dem Client bzw. dem RDSH / dem VDA etwas im Eventlog?

Schreib einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.