Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Allow write/modify access to CommonApplicationData

0.00/5 (No votes)
22 May 2010 1  
Now your application can update it's saved data regrdless of the account it is running under.
This tip was prompted by a discussion here[^] yesterday in the C# forum.

When you need to store data common to all users of an application locally, Microsoft recommend using System.Environment.SpecialFolder.CommonApplicationData. In addition they also suggest creating a sub folder here with your CompanyName and a sub folder in that of ApplicationName.

The issue with this is the folders and files you create only have read/execute permissions for other users other than the creator. This means that they cannot be appended to or replaced by another user without UAC elevation.

Whilst I understand the reasoning for this, in reality it creates a problem for a shared dynamic data store.

The class below addresses this by setting read/write permissions to all users on the CompanyName folder and optionally setting read/write permissions of the ApplicationName folder on creation and sub folders/files inherit these permissions.

Note: The permissions are only set on the ApplicationName folder creation. If it already exists the permissions will not be altered.

This has only been tested on Windows 7 to date, but should work fine in Vista and XP (if required?). I will test these OSes when time allows and update this accordingly.

Make sure you wrap any calls to this class in suitable try/catch blocks as there is no exception handling.
C#
using System;
using System.IO;
using System.Security.AccessControl;
using System.Security.Principal;

/// <summary>
/// Simplifies the creation of folders in the CommonApplicationData folder
/// and setting of permissions for all users.
/// </summary>
public class CommonApplicationData
{
    private string applicationFolder;
    private string companyFolder;
    private static readonly string directory = 
        Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);

    /// <summary>
    /// Creates a new instance of this class creating the specified company and application folders
    /// if they don't already exist and optionally allows write/modify to all users.
    /// </summary>
    /// <param name="companyFolder">The name of the company's folder (normally the company name).</param>
    /// <param name="applicationFolder">The name of the application's folder (normally the application name).</param>
    /// <remarks>If the application folder already exists then permissions if requested are NOT altered.</remarks>
    public CommonApplicationData(string companyFolder, string applicationFolder)
        : this(companyFolder, applicationFolder, false)
    { }
    /// <summary>
    /// Creates a new instance of this class creating the specified company and application folders
    /// if they don't already exist and optionally allows write/modify to all users.
    /// </summary>
    /// <param name="companyFolder">The name of the company's folder (normally the company name).</param>
    /// <param name="applicationFolder">The name of the application's folder (normally the application name).</param>
    /// <param name="allUsers">true to allow write/modify to all users; otherwise, false.</param>
    /// <remarks>If the application folder already exists then permissions if requested are NOT altered.</remarks>
    public CommonApplicationData(string companyFolder, string applicationFolder, bool allUsers)
    { 
        this.applicationFolder = applicationFolder;
        this.companyFolder = companyFolder;
        CreateFolders(allUsers);
    }

    /// <summary>
    /// Gets the path of the application's data folder.
    /// </summary>
    public string ApplicationFolderPath 
    { 
        get { return Path.Combine(CompanyFolderPath, applicationFolder); }
    }
    /// <summary>
    /// Gets the path of the company's data folder.
    /// </summary>
    public string CompanyFolderPath 
    { 
        get { return Path.Combine(directory, companyFolder); }
    }

    private void CreateFolders(bool allUsers) 
    {
        DirectoryInfo directoryInfo;
        DirectorySecurity directorySecurity;
        AccessRule rule;
        SecurityIdentifier securityIdentifier = new SecurityIdentifier
            (WellKnownSidType.BuiltinUsersSid, null);
        if (!Directory.Exists(CompanyFolderPath))
        {
            directoryInfo = Directory.CreateDirectory(CompanyFolderPath);
            bool modified;
            directorySecurity = directoryInfo.GetAccessControl();
            rule = new FileSystemAccessRule(
                    securityIdentifier,
                    FileSystemRights.Write |
                    FileSystemRights.ReadAndExecute |
                    FileSystemRights.Modify,
                    AccessControlType.Allow);
            directorySecurity.ModifyAccessRule(AccessControlModification.Add, rule, out modified);
            directoryInfo.SetAccessControl(directorySecurity);
        }
        if (!Directory.Exists(ApplicationFolderPath))
        {
            directoryInfo = Directory.CreateDirectory(ApplicationFolderPath);
            if (allUsers)
            {
                bool modified;
                directorySecurity = directoryInfo.GetAccessControl();
                rule = new FileSystemAccessRule(
                    securityIdentifier,
                    FileSystemRights.Write |
                    FileSystemRights.ReadAndExecute |
                    FileSystemRights.Modify,
                    InheritanceFlags.ContainerInherit |
                    InheritanceFlags.ObjectInherit,
                    PropagationFlags.InheritOnly,
                    AccessControlType.Allow);
                directorySecurity.ModifyAccessRule(AccessControlModification.Add, rule, out modified);
                directoryInfo.SetAccessControl(directorySecurity);
            }
        }
    }
    /// <summary>
    /// Returns the path of the application's data folder.
    /// </summary>
    /// <returns>The path of the application's data folder.</returns>
    public override string ToString() 
    { 
        return ApplicationFolderPath;
    }
}

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here