Click here to Skip to main content
15,879,326 members
Articles / Programming Languages / C# 4.0
Tip/Trick

Allow write/modify access to CommonApplicationData

Rate me:
Please Sign up or sign in to vote.
4.95/5 (14 votes)
22 May 2010CPOL1 min read 114.4K   14   30
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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
CEO Dave Meadowcroft
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionI added a try-catch for sharing old directories Pin
Member 949920326-Jan-21 17:39
Member 949920326-Jan-21 17:39 
QuestionIs it ok to use whitout any admin rights ? Pin
Golard7728-Jan-16 3:49
Golard7728-Jan-16 3:49 
AnswerRe: Is it ok to use whitout any admin rights ? Pin
DaveyM6928-Jan-16 7:29
professionalDaveyM6928-Jan-16 7:29 
AnswerRe: Is it ok to use whitout any admin rights ? Pin
DennisXWu24-Mar-17 10:13
DennisXWu24-Mar-17 10:13 
QuestionExisting folders Pin
Paul Mickelsen29-Aug-15 8:30
Paul Mickelsen29-Aug-15 8:30 
AnswerRe: Existing folders Pin
DennisXWu23-Mar-17 12:54
DennisXWu23-Mar-17 12:54 
QuestionImplementation code? Pin
DeveloperDan27-Aug-15 10:15
DeveloperDan27-Aug-15 10:15 
GeneralMy vote of 5 Pin
DidiKunz1-Jul-13 0:14
DidiKunz1-Jul-13 0:14 
Questionthis flag: PropagationFlags.InheritOnly is not enough Pin
TCDooM2-Aug-11 3:53
TCDooM2-Aug-11 3:53 
AnswerRe: this flag: PropagationFlags.InheritOnly is not enough Pin
DaveyM693-Aug-11 13:02
professionalDaveyM693-Aug-11 13:02 
GeneralRe: this flag: PropagationFlags.InheritOnly is not enough Pin
pcbbc24-Jan-12 2:50
pcbbc24-Jan-12 2:50 
GeneralRe: this flag: PropagationFlags.InheritOnly is not enough Pin
Umpfz12-Feb-13 14:47
Umpfz12-Feb-13 14:47 
GeneralRe: this flag: PropagationFlags.InheritOnly is not enough Pin
DaveyM6913-Feb-13 0:14
professionalDaveyM6913-Feb-13 0:14 
QuestionPlease help Pin
Jipat3-Jun-11 3:35
Jipat3-Jun-11 3:35 
AnswerRe: Please help Pin
DaveyM693-Jun-11 9:36
professionalDaveyM693-Jun-11 9:36 
GeneralRe: Please help Pin
Jipat3-Jun-11 19:49
Jipat3-Jun-11 19:49 
GeneralRe: Please help Pin
DaveyM694-Jun-11 4:27
professionalDaveyM694-Jun-11 4:27 
GeneralRe: Please help Pin
Jipat8-Jun-11 1:26
Jipat8-Jun-11 1:26 
General"Whilst I understand the reasoning for this" Pin
Qwertie26-Nov-10 9:55
Qwertie26-Nov-10 9:55 
GeneralRe: "Whilst I understand the reasoning for this" Pin
DaveyM6927-Nov-10 1:46
professionalDaveyM6927-Nov-10 1:46 
GeneralApplication.CommonAppDataPath Pin
Amir_Saniyan29-Sep-10 22:06
Amir_Saniyan29-Sep-10 22:06 
GeneralRe: Application.CommonAppDataPath Pin
DaveyM6930-Sep-10 11:02
professionalDaveyM6930-Sep-10 11:02 
GeneralDoes not work on non english OS... Pin
eric.ducos1-Mar-10 21:28
eric.ducos1-Mar-10 21:28 
GeneralFixed: Does not work on non english OS... [modified] Pin
DaveyM692-Mar-10 10:27
professionalDaveyM692-Mar-10 10:27 
GeneralRe: Does not work on non english OS... Pin
wout de zeeuw16-Jun-10 2:19
wout de zeeuw16-Jun-10 2:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.