My application stores log files in a location which, depending on admin settings, can get redirected to a folder in the VirtualStore. They sometimes end up in, for example:
The log file is in:
C:\Users\-my username-\AppData\Local\VirtualStore\Program Files (x86)\ *my-application* \logs
C# thinks it is here:
C:\Program Files (x86)\ my-application \logs
This is only a problem in one part of the code - a button which tries to open the log file in notepad. It runs Process.Start( path-where-application-thinks-log-files-are );
If I test this using File.Exists( path-where-application-thinks-log-files-are ); I get true - because c# knows to look in the VirtualStore location. But when I try to launch the file, it fails.
So my question is, is there a way to convert a path into the correct location, from the point of view of the Process.Start() command?
The answer to your question is that you cannot.
File and Registry virtualization is a temporary compatibility hack, present in the current version of Windows so that buggy applications will temporarily continue to work. Microsoft provides no capability to cope with redirected files. Applications that do it are in a buggy state and need to be fixed.
From the Developing for Windows blog:
User Account Control Data Redirection
Today, many applications are still designed to write files to the Program Files, Windows directories, or system root (typically the C drive) folders.
Virtualization is intended only to assist in application compatibility with existing programs. New applications designed for Microsoft Windows 7 should NOT perform write operations to sensitive system areas, nor should they rely on virtualization to provide redress for incorrect application behavior. Always develop applications for use with standard user privileges and don’t count on the application running under administrator privileges. Test your application with standard user privileges and not administrator privileges.
If you are experiencing UAC virtualization with applications developed prior to Windows 7, re-design your applications to write files to the appropriate locations.
The ideal way to solve your problem is to disable File and Registry Virtualization of your application. That way your application will no longer be able to save files to sensitive locations - and will get an Access denied
error.
You do this by adding an entry to your application's assembly manifest, telling Windows that your application is properly written:
AssemblyManifest.xml
:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<assemblyIdentity
version="1.0.0.0"
processorArchitecture="X86"
name="client"
type="win32"
/>
<description>Sugrue Contoso</description>
<!-- Disable file and registry virtualization -->
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
This way any attempts to write a log file to the %ProgramFiles%
subtree will correctly fail.
Correctly written Windows applications do not store data in Program Files
. From Technical requirements for the Windows 7 Client Software Logo Program, page 8-9:
Install to the correct folders by default
Users should have a consistent and secure experience with the default installation location of files, while maintaining the option to install an application to the location they choose. It is also necessary to store application data in the correct location to allow several people to use the same computer without corrupting or overwriting each other's data and settings.
Windows provides specific locations in the file system to store programs and software components, shared application data, and application data specific to a user:
- Applications should be installed to the Program Files folder by default. User data or application data must never be stored in this location because of the security permissions configured for this folder (emphasis added)
- All application data that must be shared among users on the computer should be stored within ProgramData
- All application data exclusive to a specific user and not to be shared with other users of the computer must be stored in Users\<username>\AppData
- Never write directly to the "Windows" directory and or subdirectories. Use the correct methods for installing files, such as fonts or drivers
- In “per-machine” installations, user data must be written at first run and not during the installation. This is because there is no correct user location to store data at time of installation. Attempts by an application to modify default association behaviors at a machine level after installation will be unsuccessful. Instead, defaults must be claimed on a per-user level, which prevents multiple users from overwriting each other's defaults.
In your case, log files should either be stored:
LocalAppData
folder (typically resolves to C:\Users\Sugrue\AppData\Local
)CommonAppData
folder (typically resolves to C:\ProgramData
)The choice is yours. Presumably you want a single log file which multiple users can add to. In which case you want the Common AppData folder. You can retrieve this path using SHGetFolderPath
with the CSIDL_COMMON_APPDATA
, or the newer SHGetKnownFolderPath
:
SHGetFolderPath(0, CSIDL_COMMON_APPDATA, SHGFP_TYPE_CURRENT, out path);
Users are able to write to this folder, because rights to create files and folders are there are granted to Users by default:
You can't.
But at the same time: you shouldn't.
Consider what happens if there is no redirection happening. What happens when you run as a standard user on Windows XP?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With