Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

File permissions and config-files. 1

Status
Not open for further replies.

MagiMike

Technical User
Jun 5, 2003
44
0
0
SE
Hi!
I'm making a program that takes uses some values from a config-file in the program's folder. The program is also able to change the settings in the file.
But when I run it under a restricted user Windows XP won't let the program write to the file.

Is there a good workaround for this? Being able to change it's config-file is very important for the program.
I tried to use the register but a restricted user isn't allowed to change the values.
 
Add the user to the Permissions on the folder so they can write to it during the installation.
 
The problem is that the config-file will change not only during the installation but during each execution also since it also works as a log-file. Forgot to mention that. :/
 
you're logging to your config file? The app.config file?

That's almost as bad as logging to the registry :)

You will want to either
1. Write to a log file (text or xml)
2. Write the the System Event Viewer under your own application space
 
Ok, you got me there. Tried to make it simpler by not introducing another file in my example but the example only got more stupid... :)

If we take your alternative 1, I'd like to use the same log-file for all users. Where can I put the file so that all restricted users can log to it(in other words, read/write permissions, no execution-permission required)?
Putting the logfile in the folder for the program does not work.
 
depending on the OS and the restrictions given, you should be able to write the the user's local directory or you will have to point to a folder that has read/write access for the restricted user.

 
Which common places (shared by all users) can a restricted user in windows xp use?
 
Should include anything under their Documents And Settings folder. (MyDocuments, LocalSettings, etc)

Chip H.


____________________________________________________________________
If you want to get the best response to a question, please read FAQ222-2244 first
 
I'll probably have to use the All users-folder.
Is it available under Win2k also?
 
You probably want to put the file in the "All Users" appication data directory.

You can caluclate this by using the following:

using System;
using System.IO;

...

string filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"CompanyName\ProductName\ConfigFile.config");

Note that this directory location can be moved so you should always use Environment.GetFolderPath rather than hard code it.
 
Yes, the All users-directory would have been the solution.
However, then I discovered that in Win2000 a restricted user does not have permission to write to that folder and its underlying folders. :(

So to simplify the problem:
I need to find a place where all restricted users can read and write to the same file. No execution of the file is needed.
This place must be available under both WinXP and Win2000.
 
It doesn't even have to be a file, just a place to store data.
 
... in Win2000 a restricted user does not have permission to write to that folder"

That's a bit dumb. I wonder why MS did that? After all what is the point of this directory if people can't write to it?

Looks like you are going to have to use the strategy JurkMonkey suggested of setting permissions at install time.
 
Is there a way to do this using a C#-program? Or else, how can I set filepermissions in a setup-project?
 
It is possible but a little tricky.

I am assuming you are using a standard VS setup project. What you need to do is:

1. Add an Installer Class to your exe project.
2. Add the code below to the installer class (remember to change the company and product names).
3. Build the project.
4. Add the primary output of the exe project to the installer project.
5. Go to the Custom Actions editor for the setup project.
6. Right click on the Custom Actions node in the tree and add the primary output you added in step 4.

The code for your Installer class needs to look like this:

Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;

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

namespace NameSpace
{
    [RunInstaller(true)]
    public partial class CreateDir : Installer
    {
        public CreateDir()
        {
            InitializeComponent();
        }

        public override void Install(System.Collections.IDictionary stateSaver)
        {
            CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Company"));
            CreateDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Company\Product"));
            base.Install(stateSaver);
        }

        public override void Uninstall(System.Collections.IDictionary savedState)
        {
            DeleteDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Company\Product"), true);
            DeleteDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Company"), false);
            base.Uninstall(savedState);
        }

        public override void Rollback(System.Collections.IDictionary savedState)
        {
            DeleteDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Company\Product"), true);
            DeleteDirectory(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), @"Company"), false);
            base.Rollback(savedState);
        }

        private void CreateDirectory(string dirPath)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(dirPath);
            FileSystemAccessRule rule = new FileSystemAccessRule("Everyone", FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.None, AccessControlType.Allow);
            if (!dirInfo.Exists)
            {
                DirectorySecurity security = new DirectorySecurity();
                security.SetAccessRule(rule);
                dirInfo.Create(security);
            }
            else
            {
                DirectorySecurity security = dirInfo.GetAccessControl();
                security.AddAccessRule(rule);
                dirInfo.SetAccessControl(security);
            }
        }

        private void DeleteDirectory(string dirPath, bool recursive)
        {
            DirectoryInfo dirInfo = new DirectoryInfo(dirPath);

            if (recursive)
            {
                dirInfo.Delete(true);
            }
            else if (dirInfo.GetFileSystemInfos().Length == 0)
            {
                dirInfo.Delete();
            }
        }
    }
}
 
An extremely nice example! Thank you very much. :)

Too bad my company is still using .Net 1.1 that doesn't contain System.Security.AccessControl :(
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top