<# This script created for spreading users over multiple file shares with FSLogix Profile Containers With Ref https://james-rankin.com/articles/spreading-users-over-multiple-file-shares-with-fslogix-profile-containers/ Script customized as per Citrix VDI requirement, Azure Subscription will be connected with User Assigned Managed Idenity(UAMI) and UAMI is assigned to Citrix Master Image. Script is added in Task Scheduler of Master Image and Machine catalog is created with "Machine Profile" option so that all cloned VDI's get UAMI property #> # This script count the directories in each share and FSLOgix VHD location is added based on count retrieved. We took directories count as users count can not be measured. # This Script also created to address the Azure File Handle limit which is 10k per share # This script fetches directories count from MULTIPLE AZURE FILE STORAGES AND MULTIPLE SHARES ########### Set TLS 1.2 ########### [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 ########### Connect Using User Assigned Managed Identity (UAMI) ########### Connect-AzAccount -Identity -AccountId ########### Provide Profile Storage Account Details ########### # Provide "Profile Storage Account Name and Storage Resource Group Name" else LEAVE BLANK values $profilestorageaccount1 = "" $profilestorageaccount1RG = "" $profilestorageaccount1shares = @( "profile1", "profile2" ) # Provide "Profile Storageaccount Shares FULL PATH" in above SHARES ORDER ONLY $profilestorageaccount1sharesfullpath = @( "\\.file.core.windows.net\profile1", "\\.file.core.windows.net\profile2" ) # Provide "Profile Storage Account Name and Storage Resource Group Name" else LEAVE BLANK values $profilestorageaccount2 = "" $profilestorageaccount2RG = "" $profilestorageaccount2shares = @( "profile3", "profile4" ) # Provide "Profile Storageaccount Shares FULL PATH" in above SHARES ORDER ONLY $profilestorageaccount2sharesfullpath = @( "\\.file.core.windows.net\profile3", "\\c.file.core.windows.net\profile4" ) # Provide "Profile Storage Account Name and Storage Resource Group Name" else LEAVE BLANK values $profilestorageaccount3 = "" $profilestorageaccount3RG = "" $profilestorageaccount3shares = @( ) # Provide "Profile Storageaccount Shares FULL PATH" in above SHARES ORDER ONLY $profilestorageaccount3sharesfullpath = @( ) # Provide "Profile Storage Account Name and Storage Resource Group Name" else LEAVE BLANK values $profilestorageaccount4 = "" $profilestorageaccount4RG = "" $profilestorageaccount4shares = @( ) # Provide "Profile Storageaccount Shares FULL PATH" in above SHARES ORDER ONLY $profilestorageaccount4sharesfullpath = @( ) # Provide "Profile Storage Account Name and Storage Resource Group Name" else LEAVE BLANK values $profilestorageaccount5 = "" $profilestorageaccount5RG = "" $profilestorageaccount5shares = @( ) # Provide "Profile Storageaccount Shares FULL PATH" in above SHARES ORDER ONLY $profilestorageaccount5sharesfullpath = @( ) ########### Provide Office Storage Account Details ########### # Provide "Office Storage Account Name and Storage Resource Group Name" else LEAVE BLANK values $officestorageaccount1 = "" $officestorageaccount1RG = "" $officestorageaccount1shares = @( "office1", "office2" ) # Provide "Office Storageaccount Shares FULL PATH" in above SHARES ORDER ONLY $officestorageaccount1sharesfullpath = @( "\\.file.core.windows.net\office1", "\\.file.core.windows.net\office2" ) # Provide "Office Storage Account Name and Storage Resource Group Name" else LEAVE BLANK values $officestorageaccount2 = "" $officestorageaccount2RG = "" $officestorageaccount2shares = @( "office3", "office4" ) # Provide "Office Storageaccount Shares FULL PATH" in above SHARES ORDER ONLY $officestorageaccount2sharesfullpath = @( "\\.file.core.windows.net\office3", "\\.file.core.windows.net\office4" ) # Provide "Office Storage Account Name and Storage Resource Group Name" else LEAVE BLANK values $officestorageaccount3 = "" $officestorageaccount3RG = "" $officestorageaccount3shares = @( ) # Provide "Office Storageaccount Shares FULL PATH" in above SHARES ORDER ONLY $officestorageaccount3sharesfullpath = @( ) # Provide "Office Storage Account Name and Storage Resource Group Name" else LEAVE BLANK values $officestorageaccount4 = "" $officestorageaccount4RG = "" $officestorageaccount4shares = @( ) # Provide "Office Storageaccount Shares FULL PATH" in above SHARES ORDER ONLY $officestorageaccount4sharesfullpath = @( ) # Provide "Office Storage Account Name and Storage Resource Group Name" else LEAVE BLANK values $officestorageaccount5 = "" $officestorageaccount5RG = "" $officestorageaccount5shares = @( ) # Provide "Office Storageaccount Shares FULL PATH" in above SHARES ORDER ONLY $officestorageaccount5sharesfullpath = @( ) ########### Fetch the Directories in the Profile Shares ########### $ProfileDirShareCount = @() $profileorderedShares = @() if($profilestorageaccount1shares.Count -gt 0) { $i = 0 $keys = Get-AzStorageAccountKey -ResourceGroupName $profilestorageaccount1RG -AccountName $profilestorageaccount1 $value = $keys[0].Value $context = New-AzStorageContext -StorageAccountName $profilestorageaccount1 -StorageAccountKey $value foreach($sharename in $profilestorageaccount1shares) { $directories = Get-AzStorageFile -ShareName $sharename -Context $context $dircount = $directories.count $shareSpace = New-Object -TypeName psobject $path = $profilestorageaccount1sharesfullpath[$i] $sharespace | Add-Member -membertype NoteProperty -Name Share -value $path $sharespace | Add-Member -membertype NoteProperty -Name freespace -value $dircount $ProfileDirShareCount += $shareSpace $i = $i + 1 } } if($profilestorageaccount2shares.Count -gt 0) { $i = 0 $keys = Get-AzStorageAccountKey -ResourceGroupName $profilestorageaccount2RG -AccountName $profilestorageaccount2 $value = $keys[0].Value $context = New-AzStorageContext -StorageAccountName $profilestorageaccount2 -StorageAccountKey $value foreach($sharename in $profilestorageaccount2shares) { $directories = Get-AzStorageFile -ShareName $sharename -Context $context $dircount = $directories.count $shareSpace = New-Object -TypeName psobject $path = $profilestorageaccount2sharesfullpath[$i] $sharespace | Add-Member -membertype NoteProperty -Name Share -value $path $sharespace | Add-Member -membertype NoteProperty -Name freespace -value $dircount $ProfileDirShareCount += $shareSpace $i = $i + 1 } } if($profilestorageaccount3shares.Count -gt 0) { $i = 0 $keys = Get-AzStorageAccountKey -ResourceGroupName $profilestorageaccount3RG -AccountName $profilestorageaccount3 $value = $keys[0].Value $context = New-AzStorageContext -StorageAccountName $profilestorageaccount3 -StorageAccountKey $value foreach($sharename in $profilestorageaccount3shares) { $directories = Get-AzStorageFile -ShareName $sharename -Context $context $dircount = $directories.count $shareSpace = New-Object -TypeName psobject $path = $profilestorageaccount3sharesfullpath[$i] $sharespace | Add-Member -membertype NoteProperty -Name Share -value $path $sharespace | Add-Member -membertype NoteProperty -Name freespace -value $dircount $ProfileDirShareCount += $shareSpace $i = $i + 1 } } if($profilestorageaccount4shares.Count -gt 0) { $i = 0 $keys = Get-AzStorageAccountKey -ResourceGroupName $profilestorageaccount4RG -AccountName $profilestorageaccount4 $value = $keys[0].Value $context = New-AzStorageContext -StorageAccountName $profilestorageaccount4 -StorageAccountKey $value foreach($sharename in $profilestorageaccount4shares) { $directories = Get-AzStorageFile -ShareName $sharename -Context $context $dircount = $directories.count $shareSpace = New-Object -TypeName psobject $path = $profilestorageaccount4sharesfullpath[$i] $sharespace | Add-Member -membertype NoteProperty -Name Share -value $path $sharespace | Add-Member -membertype NoteProperty -Name freespace -value $dircount $ProfileDirShareCount += $shareSpace $i = $i + 1 } } if($profilestorageaccount5shares.Count -gt 0) { $i = 0 $keys = Get-AzStorageAccountKey -ResourceGroupName $profilestorageaccount5RG -AccountName $profilestorageaccount5 $value = $keys[0].Value $context = New-AzStorageContext -StorageAccountName $profilestorageaccount5 -StorageAccountKey $value foreach($sharename in $profilestorageaccount5shares) { $directories = Get-AzStorageFile -ShareName $sharename -Context $context $dircount = $directories.count $shareSpace = New-Object -TypeName psobject $path = $profilestorageaccount5sharesfullpath[$i] $sharespace | Add-Member -membertype NoteProperty -Name Share -value $path $sharespace | Add-Member -membertype NoteProperty -Name freespace -value $dircount $ProfileDirShareCount += $shareSpace $i = $i + 1 } } $SortedProfileShares = $ProfileDirShareCount | Sort-Object freespace | select share foreach ($item in $SortedProfileShares) { $profileorderedShares += $item.Share.ToString() } ########### Fetch the Directories in the Office Shares ########### $OfficeDirShareCount = @() $officeorderedShares = @() if($officestorageaccount1shares.Count -gt 0) { $i = 0 $keys = Get-AzStorageAccountKey -ResourceGroupName $officestorageaccount1RG -AccountName $officestorageaccount1 $value = $keys[0].Value $context = New-AzStorageContext -StorageAccountName $officestorageaccount1 -StorageAccountKey $value foreach($sharename in $officestorageaccount1shares) { $directories = Get-AzStorageFile -ShareName $sharename -Context $context $dircount = $directories.count $shareSpace = New-Object -TypeName psobject $path = $officestorageaccount1sharesfullpath[$i] $sharespace | Add-Member -membertype NoteProperty -Name Share -value $path $sharespace | Add-Member -membertype NoteProperty -Name freespace -value $dircount $officeDirShareCount += $shareSpace $i = $i + 1 } } if($officestorageaccount2shares.Count -gt 0) { $i = 0 $keys = Get-AzStorageAccountKey -ResourceGroupName $officestorageaccount2RG -AccountName $officestorageaccount2 $value = $keys[0].Value $context = New-AzStorageContext -StorageAccountName $officestorageaccount2 -StorageAccountKey $value foreach($sharename in $officestorageaccount2shares) { $directories = Get-AzStorageFile -ShareName $sharename -Context $context $dircount = $directories.count $shareSpace = New-Object -TypeName psobject $path = $officestorageaccount2sharesfullpath[$i] $sharespace | Add-Member -membertype NoteProperty -Name Share -value $path $sharespace | Add-Member -membertype NoteProperty -Name freespace -value $dircount $officeDirShareCount += $shareSpace $i = $i + 1 } } if($officestorageaccount3shares.Count -gt 0) { $i = 0 $keys = Get-AzStorageAccountKey -ResourceGroupName $officestorageaccount3RG -AccountName $officestorageaccount3 $value = $keys[0].Value $context = New-AzStorageContext -StorageAccountName $officestorageaccount3 -StorageAccountKey $value foreach($sharename in $officestorageaccount3shares) { $directories = Get-AzStorageFile -ShareName $sharename -Context $context $dircount = $directories.count $shareSpace = New-Object -TypeName psobject $path = $officestorageaccount3sharesfullpath[$i] $sharespace | Add-Member -membertype NoteProperty -Name Share -value $path $sharespace | Add-Member -membertype NoteProperty -Name freespace -value $dircount $officeDirShareCount += $shareSpace $i = $i + 1 } } if($officestorageaccount4shares.Count -gt 0) { $i = 0 $keys = Get-AzStorageAccountKey -ResourceGroupName $officestorageaccount4RG -AccountName $officestorageaccount4 $value = $keys[0].Value $context = New-AzStorageContext -StorageAccountName $officestorageaccount4 -StorageAccountKey $value foreach($sharename in $officestorageaccount4shares) { $directories = Get-AzStorageFile -ShareName $sharename -Context $context $dircount = $directories.count $shareSpace = New-Object -TypeName psobject $path = $officestorageaccount4sharesfullpath[$i] $sharespace | Add-Member -membertype NoteProperty -Name Share -value $path $sharespace | Add-Member -membertype NoteProperty -Name freespace -value $dircount $officeDirShareCount += $shareSpace $i = $i + 1 } } if($officestorageaccount5shares.Count -gt 0) { $i = 0 $keys = Get-AzStorageAccountKey -ResourceGroupName $officestorageaccount5RG -AccountName $officestorageaccount5 $value = $keys[0].Value $context = New-AzStorageContext -StorageAccountName $officestorageaccount5 -StorageAccountKey $value foreach($sharename in $officestorageaccount5shares) { $directories = Get-AzStorageFile -ShareName $sharename -Context $context $dircount = $directories.count $shareSpace = New-Object -TypeName psobject $path = $officestorageaccount5sharesfullpath[$i] $sharespace | Add-Member -membertype NoteProperty -Name Share -value $path $sharespace | Add-Member -membertype NoteProperty -Name freespace -value $dircount $officeDirShareCount += $shareSpace $i = $i + 1 } } $SortedOfficeShares = $OfficeDirShareCount | Sort-Object freespace | select share foreach ($item in $SortedOfficeShares) { $officeorderedShares += $item.Share.ToString() } ########### Remove the Existing VHDLocations Available ########### $FSLogixProfilePath="HKLM:\software\FSLogix\Profiles" $FSLogixODFCPath="HKLM:\SOFTWARE\Policies\FSLogix\ODFC" $FSLogixKeyName="VHDLocations" if ((get-item -path $FSLogixProfilePath).GetValue($FSLogixKeyName) -ne $null) { Remove-itemProperty -path $FSLogixProfilePath -Name $FSLogixKeyName -force } else { # do nothing, no key to delete } if ((get-item -path $FSLogixODFCPath).GetValue($FSLogixKeyName) -ne $null) { Remove-itemProperty -path $FSLogixODFCPath -Name $FSLogixKeyName -force } else { # do nothing, no key to delete } ########### Adding New VHDLocation for Profile ########### ### Reason for changing VHDLocation property type to Multi string value is because that FSLogix need to searches the user profile in all shares hence to keep all shares , regkey should be Mutistring New-ItemProperty $FSLogixProfilePath -Name $FSLogixKeyName -Value $profileorderedShares -PropertyType MultiString -Force ########### Adding New VHDLocation for Office ########### New-ItemProperty $FSLogixODFCPath -Name $FSLogixKeyName -Value $officeorderedShares -PropertyType MultiString -Force ########### Write OutPut ########### $folderPath="C:\Temp" $ProfileDirShareCount | Export-csv -Path "$folderPath\Profile_Shareleastlog_$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv" -NoTypeInformation $OfficeDirShareCount | Export-csv -Path "$folderPath\Office_Shareleastlog_$((Get-Date).ToString('MM-dd-yyyy_hh-mm-ss')).csv" -NoTypeInformation