In what conditions are local files seen or written by an App-V application?
For some applications I have sequenced, App-V seems to do just what is needed to make the application work correctly. In other cases, however, I have found that a few files that ought to reside on the local filesystem are virtualized. This is a problem because those files don't survive a "repair" of the virtualized application.
I thought that setting a VFS folder to merge mode would allow the application to write to the local file system. However, a simple test revealed that this does not seem to be the case. Obviously, there must be rules dictating which files are read from and written to the local file system as opposed to the VFS.
In what conditions is the local filesystem read from or written to by an App-V application?
Solution 1:
TL;DR
Files that exist on the local filesystem can be seen by a virtualized application when the corresponding VFS folder is "merge" mode or the corresponding folder is not mentioned in the VFS. But, the same files cannot be seen when the corresponding VFS folder is in "override" mode.
A virtualized application only writes to the local filesystem when both of the following are true:
- the folder where the file is written is not mentioned in the VFS, and
- the folder where the file is written exists on the local filesystem
I wasn't able to find authoritative documentation to answer this question. The closest information I found was Kalle Saunamäki's 2011 blog post about App-V 4.6. It turns out that not only is that post only peripherally on-point, but App-V 5.x behavior also seems to have changed in at least one case (i.e. App-V 5.x doesn't seem to create missing merged-mode VFS folders on the local filesystem anymore, whereas Kalle seems to have witnessed 4.6 doing so).
Empirical Test
My crude experimentation just resulted in confusing results so I decided to run some more formal tests to get the bottom of this.
Setup
The test involved creating files at each of the following stages:
- A: Before Sequencing
- B: During Sequencing from inside the Sequencer
- C: Before Publishing
- D: After Publishing from a Virtual Process Inside the App
There are three possible cases for how the VFS applies to a folder at end of sequencing:
- override mode
- merge mode
- not mentioned
At the publishing stage, any given folder could either be created or not in each of the local and virtual filesystems. That's four possibilites.
The three ways the VFS applies combined with the four publishing possibilities results in 12 cases that I tested. I used some scripts to automate this and (hopefully) avoid mistakes. Those scripts are at the end of this post.
Results
The VFS as seen from the sequencer UI is as follows:
I checked for the existence of each of the files written by the scripts from both inside and outside the published app's bubble. The results are in this table:
Analysis
Based on the table, it looks like following statements hold:
- All files created by the running, virtualized application can be seen by that application. This is no surprise since this is absolutely required for the application to function.
- Files that exist on the local filesystem cannot be seen by a virtualized application when the corresponding VFS folder is "override" mode.
- Files that exist on the local filesystem can be seen by a virtualized application when the corresponding VFS folder is "merge" mode or the corresponding folder is not mentioned in the VFS.
- The only case where a virtualized application writes to the local filesystem occurs when both of the following are true:
- the folder where the file is written is not mentioned in the VFS, and
- the folder where the file is written exists on the local filesystem
Scripts
A-before-sequencing.ps1
$splat = @{
Cases = 4..11
FolderName = 'ExistsBeforeSequencing'
FileName = 'ExistsBeforeSequencing'
Mode = 'Create'
}
.\Alter-Folders.ps1 @splat
B-during-sequencing.ps1
$splats = @(
@{
Cases = 0..3
FolderName = 'CreatedDuringSequencing'
FileName = 'CreatedDuringSequencing'
Mode = 'Create'
},
@{
Cases = 4..7
FolderName = 'ExistsBeforeSequencing'
FileName = 'CreatedDuringSequencing'
Mode = 'Create'
}
)
$splats |
% { .\Alter-Folders.ps1 @_ }
C-before-publishing.ps1
$splats = @(
@{
Cases = 0..3
FolderName = 'CreatedDuringSequencing'
Mode = 'Remove'
}
@{
Cases = 4..11
FolderName = 'ExistsBeforeSequencing'
Mode = 'Remove'
}
@{
Cases = 1,3
FolderName = 'CreatedDuringSequencing'
FileName = 'CreatedBeforePublishing'
Mode = 'Create'
}
@{
Cases = 5,7,9,11
FolderName = 'ExistsBeforeSequencing'
FileName = 'CreatedBeforePublishing'
Mode = 'Create'
}
)
$splats |
% { .\Alter-Folders.ps1 @_ }
D-app-running.ps1
$splats = @(
@{
Cases = 2,3
FolderName = 'CreatedDuringSequencing'
FileName = 'CreatedByRunningApp'
Mode = 'Create'
}
@{
Cases = 6,7,10,11
FolderName = 'ExistsBeforeSequencing'
FileName = 'CreatedByRunningApp'
Mode = 'Create'
}
)
$splats |
% { .\Alter-Folders.ps1 @_ }
Alter-Folders.ps1
[CmdletBinding()]
param
(
[parameter(Mandatory=$true)]
[int32[]]
$cases,
[parameter(Mandatory=$true)]
[string]
$FolderName,
[string]
$FileName,
[parameter(Mandatory=$true)]
[string]
[ValidateSet('create','remove')]
$mode
)
$path = $env:ProgramData
if ( 'create' -eq $mode )
{
$cases |
% {
New-Item "$path\$FolderName$_" -ItemType Directory | Out-Null
New-Item "$path\$FolderName$_\$FolderName$_-1" -ItemType Directory | Out-Null
$filePath = "$path\$FolderName$_\$FolderName$_-1\$FileName$_-1.txt"
$filePath | Out-File $filePath
}
}
if ( 'remove' -eq $mode )
{
$cases |
% {
Remove-Item "$path\$FolderName$_" -Recurse -Force
}
}