Problem: a Windows Service is designed to run under the Local Service account with minimum privileges on the local computer. Suppose, however, that the service needs to write logs/what have you locally, so we must create a folder for it to write to (usually in its Application/installation folder), and set the appropriate permissions to it. This solution covers also the cases where a permissions-restricted program is installed, but needs access to certain folders/files. Since this is just some quick help on a specific problem, several assumptions have been made:

  • a solution with a Windows Forms/Windows Service application¬† has been developed, and is ready for deployment (at whatever stage)
  • an installer class has been added to that project
  • (in the case of a Windows Service) a ServiceInstaller and ServiceProcessInstaller have been added to the installer class – see more information at MSDN
  • a Visual Studio Setup project has been created in that solution that installs the aforementioned application
  • the goal is to create a folder in the installation folder of the application where that software will be able to at least read and write. See the available FileSystemRights for more options.

It is actually rather easy, given that you know all the details:

  • you will need to be

using System.Security.AccessControl;
using System.IO;

  • then handle the AfterInstall event of the Installer/ServiceInstaller class
  • the Application folder is stored in Context.Parameters[“assemblypath”], combine it with the name of the writable folder (say Logs) to obtain the full path:

string sFolder = Path.Combine(Path.GetDirectoryName(Context.Parameters[“assemblypath”]), “Logs”);

  • the username is hardcoded to the name of the Local Service (change it to the actual user account your application will be running under):

string sUsername = “NT AUTHORITY\\LOCALSERVICE”;

  • the code to alter permissions of a certain folder in C# is

DirectoryInfo myDirectoryInfo = new DirectoryInfo(sFolder);
DirectorySecurity myDirectorySecurity = myDirectoryInfo.GetAccessControl();
myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(sUsername, FileSystemRights.Read | FileSystemRights.Write | FileSystemRights.Modify, AccessControlType.Allow));

This code is a short snippet from the fine article at Redmond Pie, from Mr. Sumair Shaikh. If the permissions need to be inherited and propagated to all child nodes (containers and leaves, which is a fancy expression for subfolders and files), then change the myDirectorySecurity.AddAccessRule call to

myDirectorySecurity.AddAccessRule(new FileSystemAccessRule(sUsername, FileSystemRights.Read | FileSystemRights.Write | FileSystemRights.Modify, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.InheritOnly, AccessControlType.Allow));

See PropagationFlags and InheritanceFlags, and the latter’s Community Content, for more information.

Of course, do not forget to handle the BeforeUninstall event of Installer/ServiceInstaller class to undo all the changes you have made (delete the Logs folder if it is not empty, etc.), if needed.

Comments/suggestions are welcome.