Warning: Undefined variable $file in /customers/a/e/3/tunecom.be/httpd.www/stg_ba12f/wp-content/plugins/fix-my-feed-rss-repair/rss-feed-fixr.php on line 14
Warning: Cannot modify header information - headers already sent by (output started at /customers/a/e/3/tunecom.be/httpd.www/stg_ba12f/wp-content/plugins/fix-my-feed-rss-repair/rss-feed-fixr.php:14) in /customers/a/e/3/tunecom.be/httpd.www/stg_ba12f/wp-content/plugins/onecom-vcache/vcaching.php on line 549
Warning: Cannot modify header information - headers already sent by (output started at /customers/a/e/3/tunecom.be/httpd.www/stg_ba12f/wp-content/plugins/fix-my-feed-rss-repair/rss-feed-fixr.php:14) in /customers/a/e/3/tunecom.be/httpd.www/stg_ba12f/wp-content/plugins/onecom-vcache/vcaching.php on line 557
Warning: Cannot modify header information - headers already sent by (output started at /customers/a/e/3/tunecom.be/httpd.www/stg_ba12f/wp-content/plugins/fix-my-feed-rss-repair/rss-feed-fixr.php:14) in /customers/a/e/3/tunecom.be/httpd.www/stg_ba12f/wp-includes/feed-rss2.php on line 8
The post How to retrieve lingering FSLogix profiles on Windows Virtual Desktop, mounted from an Azure File share appeared first on Tunecom.
]]>In some very particular cases it happens that when a user logs off its session from a WVD (Windows Virtual Desktop) host, the corresponding FSLogix profile is not dismounted from the host.
When the user tries to login again to the environment, this results in the following error.
Status : 0x0000000B : Cannot open virtual disk
Reason : 0x00000000 : The container is attached
Error code : 0x00000020 : The process cannot access the file because it is being used by another process
During normal behavior of the login and log off process to Windows Virtual Desktop in combination with an FSLogix profile, the profile is mounted from the underlying storage provider and correctly dismounted upon successful log off of the Windows Virtual Desktop host.
The root cause of why the profile container is not dismounted from the host is hard to find, in most cases, an update of the FSLogix components is required, please make sure to read through the latest FSLogix release notes.
During the days that we had our profile shares/data hosted on a traditional IaaS fileserver, we would just open up an MMC console and look for any open files or sessions.
Since our profiles are now being hosted on an Azure File share, this process is slightly different. I’ve written a small PowerShell script for you to use and/or alter to your needs.
The input variables are pretty straightforward :
Note: The script is currently “designed” to query only one storage account/file share, and only one host pool per run. You could of course alter this to check all host pools and related storage accounts.
The script loops through your active Windows Virtual Desktop sessions and active storage handles.
It then checks each storage handle, whether or not it has a corresponding active WVD session. If not you are presented with the virtual machine name where the FSLogix container is mounted.
Save this PowerShell script as “Clean-LingeringFSLogixProfiles.ps1” Read through the blog post to retrieve the InVM script. The scripts can be download from my GitRepo as well.
<# .SYNOPSIS Dismount lingering FSLogix VHD(X) profiles. .DESCRIPTION Dismount lingering FSLogix VHD(X) profiles. .PARAMETER Mode Provide the execution mode of the script. Alerting : Generates an alert whenever a lingering FSLogix VHDX profile is found React : Tries to dismount the lingering FSLogix Profile on the host where it is attached .PARAMETER ProfileStorageAccount Provide the storage account where the FSLogix profiles are located .PARAMETER ProfileStorageAccount Provide the fileshare where the FSLogix profiles are located .PARAMETER StorageAccountResourceGroupName Provide the resource group name of your storage account .PARAMETER OverrideErrorActionPreference Provide the ErrorActionPreference setting, as descibed in about_preference_variables. (https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-7#erroractionpreference). When running locally we should use "Break" mode, which breaks in to the debugger when an error is thrown. .EXAMPLE PS C:\> .\Clean-LingeringFSLogixProfiles.ps1 -Mode "Alerting" -ProfileStorageAccount "storageaccountname" -ProfileShare "profileshare" -StorageAccountResourceGroupName "resourcegroupname" #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [ValidateSet('alerting', 'react')] [string] $Mode, [Parameter(Mandatory = $true)] [string] $ProfileStorageAccount, [Parameter(Mandatory = $true)] [string] $ProfileShare, [Parameter(Mandatory = $true)] [string] $StorageAccountResourceGroupName, [Parameter(Mandatory = $false)] [string] $OverrideErrorActionPreference = "Break" ) $ErrorActionPreference = $OverrideErrorActionPreference # The following cmd retrieves your storage account details and puts it in a context variable $context = Get-AzStorageAccount -ResourceGroupName $StorageAccountResourceGroupName -Name $ProfileStorageAccount #region retrieve details per hostpool # Retrieves the hostpools => Alter the script here to check for additional host pools $hostpools = get-azwvdhostpool foreach ($hostpool in $hostpools) { $wvdrg = Get-AzResource -ResourceId $hostpools.Id # This is tricky, so if you only need 1 host pool remove the foreach loop completely and comment the line below $hostpools = $hostpool #region gather all open files & sessions $OpenFiles = Get-AzStorageFileHandle -Context $Context.Context -ShareName $ProfileShare -Recursive $UserSessions = Get-AzWvdUserSession -HostPoolName $hostpools.Name -ResourceGroupName $wvdrg.ResourceGroupName | Select-Object ActiveDirectoryUserName, ApplicationType, SessionState, UserPrincipalName, name #endregion #region fill Open Files array $pathusers = @() foreach ($openfile in $OpenFiles) { If ($openfile.path) { #Write-host $openfile.Path $FilePath = $openfile.Path.Split("/")[0] $pathusers += $FilePath } } $pathusers = $pathusers | Select-Object -Unique #endregion #region fill Open Sessions array $sessionusers = @() foreach ($usersession in $UserSessions) { If ($usersession) { #Write-host $usersession $Username = $UserSession.ActiveDirectoryUserName.Split("\")[1] $sessionusers += $Username } } $sessionusers = $sessionusers | Select-Object -Unique #endregion #region loop through every open file and find a corresponding user session foreach ($pathuser in $pathusers) { If ($sessionusers -contains $pathuser) { Write-host -ForegroundColor green "Active session user: " $pathuser } else { If ($mode -eq "alerting") { $OpenFilesDetails = Get-AzStorageFileHandle -Context $Context.Context -ShareName $ProfileShare -Recursive | Where-Object { $_.Path -like "*$($pathuser)*" } # the following retrieves the virtual machine name of the lingering VHDX file $IPNic = ((Get-AzNetworkInterface | Where-Object { $_.IpConfigurations.PrivateIpAddress -eq $($OpenFilesDetails.ClientIp.IPAddressToString[0]) }).virtualmachine).Id $vmname = ($IPNic -split '/') | Select-Object -Last 1 $VM = Get-AzVm -Name $vmname Write-host -ForegroundColor red "Inactive session user: $pathuser has a FSLogix mounted on the following virtual machine $vmname" } Else { $OpenFilesDetails = Get-AzStorageFileHandle -Context $Context.Context -ShareName $ProfileShare -Recursive | Where-Object { $_.Path -like "*$($pathuser)*" } # the following retrieves the virtual machine name of the lingering VHDX file $IPNic = ((Get-AzNetworkInterface | Where-Object { $_.IpConfigurations.PrivateIpAddress -eq $($OpenFilesDetails.ClientIp.IPAddressToString[0]) }).virtualmachine).Id $vmname = ($IPNic -split '/') | Select-Object -Last 1 $VM = Get-AzVm -Name $vmname Write-host -ForegroundColor red "Inactive session user: $pathuser has a FSLogix mounted on the following virtual machine $vmname" # double check whether or not you want to dismount the profile $YesNo = Read-Host "Are you sure you want to dismount the user profile off $pathuser on the following server $vmname: Yes/No" If ($YesNo -eq "Yes") { $domainupn = Read-Host "Please enter your domain admin username:" $domainpwd = Read-Host "Please enter your domain admin password:" $runDismount = Invoke-AzVMRunCommand -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name -CommandId 'RunPowerShellScript' -ScriptPath "scripts\AzVMRunCommands\Clean-InVMLingeringFSLogixProfiles.ps1" -Parameter @{"Upn" = "$domainupn"; "Pass" = "$domainpwd";"pathuser" = $pathuser } If ($runDismount.Status -Ne "Succeeded") { Write-Error "Run failed" } else { Write-Host "FSLogix profile has been dismounted for $($pathuser) on $($vmname)" } } else { # Exit script Write-Host "We are now exiting the script, you've entered the wrong option: Yes/No is required" Exit } } } } #endregion } #endregion
Before launching the script above, make sure to save the script that needs to be run within the virtual machine.
Save the PowerShell script below as “InVMLingeringFSLogixProfiles.ps1” and alter the script path in the script above. The scripts can be download from my GitRepo as well.
param ( [Parameter(Mandatory = $true)] [string] $pathuser, [Parameter(Mandatory = $true)] [string] $upn, [Parameter(Mandatory = $true)] [string] $pass, [Parameter(Mandatory = $false)] [string] $OverrideErrorActionPreference = "Break" ) #This script is run within the virtual machine $ziptargetfolder = "c:\troubleshooting\" $innerscriptlocation = $ziptargetfolder + "Dismount-VHD.ps1" If (!(Test-Path $ziptargetfolder)) { mkdir $ziptargetfolder } @" `$ProfileNamingConvention = "Profile-" + "$pathuser" `$Volume = Get-Volume | Where-Object { `$_.filesystemlabel -eq `$ProfileNamingConvention } | % { Get-DiskImage -DevicePath `$(`$_.Path -replace "\\`$") } Dismount-DiskImage -ImagePath `$Volume.ImagePath "@ | Out-File -FilePath $innerscriptlocation $taskName = "Dismount-FSLogixProfile" $Action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Unrestricted -File $innerscriptlocation" -WorkingDirectory $ziptargetfolder $Settings = New-ScheduledTaskSettingsSet -Compatibility Win8 $TaskPath = "\CustomTasks" Register-ScheduledTask -TaskName $taskName -User $upn -Password $pass -RunLevel Highest -Action $Action -Settings $Settings Start-ScheduledTask -TaskName $taskName -TaskPath $TaskPath while ((Get-ScheduledTask -TaskName $taskName).State -ne 'Ready') { Start-Sleep -Seconds 2 } Unregister-ScheduledTask -TaskName $taskName -Confirm:$False Remove-Item -Path $innerscriptlocation -Recurse -Force
The scripts are provided as-is, please be very careful and test run the scripts on a “test” environment or an environment that allows you to perform some quick checks and tests. Dismounting VHD(X) files can cause unwanted effects when performed against an Active user.
Thank you for reading through this blog post, I hope I have been able to assist in troubleshooting FSLogix profile mounting issues.
If you encounter any new insights, feel free to drop me a comment or contact me via mail or other social media channels
The post How to retrieve lingering FSLogix profiles on Windows Virtual Desktop, mounted from an Azure File share appeared first on Tunecom.
]]>