4

I am using a web setup project to install my ASP.NET app which needs to write to a folder that exists under the main virtual directory folder. How do I configure the setup project to grant the ASPNET user permissions to that folder?

Dan Nuffer
  • 665
  • 1
  • 6
  • 11

1 Answers1

6

The way to do it is to create a class derived from System.Configuration.Install.Installer. Override the Install() method. The following is an example that changes permissions on a directory and a file, you probably don't want to be so permissive, but it depends on your security context. In order for this to work, the setup project has to run this as a custom action. Add the "Primary Output" from whatever project this class is in. You will also need to pass the directory to the custom action in its properties. The first variable name has to match the code. Like this: /targetdir="[TARGETDIR]\"

[RunInstaller(true)]
public partial class SetPermissions : Installer
{
    private const string STR_targetdir = "targetdir";
    private const string STR_aspnetUser = "ASPNET";

    public SetPermissions()
    {
        InitializeComponent();
    }

    public override void Install(IDictionary stateSaver)
    {
        base.Install(stateSaver);

        Context.LogMessage(
            Context.Parameters
                .Cast<DictionaryEntry>()
                .Select(entry => String.Format("String = {0} Value = {1}", entry.Key, entry.Value))
                .Aggregate(new StringBuilder("From install\n"), (accumulator, next) => accumulator.AppendLine(next))
                .ToString()
        );

        string targetDir = Context.Parameters[STR_targetdir];
        string dbDir = Path.Combine(targetDir, "db");

        AddFullControlPermissionToDir(dbDir, STR_aspnetUser);
        string rimdbSqliteFilename = Path.Combine(dbDir, "db.sqlite");
        AddFullControlPermissionToFile(rimdbSqliteFilename, STR_aspnetUser);
        string logsDir = Path.Combine(targetDir, "logs");
        AddFullControlPermissionToDir(logsDir, STR_aspnetUser);
    }

    private static void AddFullControlPermissionToDir(string dir, string user)
    {
        DirectorySecurity directorySecurity = Directory.GetAccessControl(dir);
        directorySecurity.AddAccessRule(
            new FileSystemAccessRule(
                user,
                FileSystemRights.FullControl,
                InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
                PropagationFlags.None,
                AccessControlType.Allow));
        Directory.SetAccessControl(dir, directorySecurity);
    }

    private static void AddFullControlPermissionToFile(string filename, string user)
    {
        FileSecurity fileSecurity = File.GetAccessControl(filename);
        fileSecurity.AddAccessRule(
            new FileSystemAccessRule(
                user,
                FileSystemRights.FullControl,
                AccessControlType.Allow));
        File.SetAccessControl(filename, fileSecurity);
    }
}
Dan Nuffer
  • 665
  • 1
  • 6
  • 11
  • 3
    Thank you for the complete code example, saved a bunch of time. I learned two things while implementing this action: 1) If you have spaces in TARGETDIR you need to pass it like this: /targetdir="[TARGETDIR]\" Of course it's pretty obvious to try the quotes, but NOT obvious to escape only the last one! ( http://msdn.microsoft.com/en-us/library/2w2fhwzz%28VS.80%29.aspx ) The other thing I learned is that to debug an action it's handy to break and attach the debugger like so: System.Diagnostics.Debugger.Launch(); – scubasteve Nov 17 '10 at 08:27