tags:

views:

91

answers:

4

I've got an application for our company that has to store settings in a global fashion so that employees with a multitude of access types can run the program.

Most of our employees access the program using a Public account, which means they don't have to log on - there is a login ID called Public that anyone can use. The Public account, as you can guess, is severely limited!

As a result, I can't seem to find a way to get my application to write data to the PC. The error is always the same Unauthorized Access Exception.

I have tried using the following paths, that all fail:

  • C:\ProgSuite\
  • Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
  • Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData)

I do not want to use Isolated Storage, because I do not want to have to configure the application for each individual that logs in onto one of the many PCs in our plant.

Is there a way to say, "Hey, my Application is an administrator. Give me access!" ???

We are currently limited to .NET Framework 3.5.

Edit:

Exception Message:

System.UnauthorizedAccessException: Access to the path 'C:\Documents and Settings\All Users\Application Data\Aaon Coil Products, Inc\AcpConfig.log' is denied.
   at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)
   at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy)
   at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share)
   at Suite.MdiForm.SaveFormSettings()
   at Suite.MdiForm.MdiForm_Closing(Object sender, FormClosingEventArgs e)
   at System.Windows.Forms.Form.OnFormClosing(FormClosingEventArgs e)
   at System.Windows.Forms.Form.WmClose(Message& m)
   at System.Windows.Forms.Form.WndProc(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)


************** Loaded Assemblies **************
mscorlib
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3603 (GDR.050727-3600)
    CodeBase: file:///c:/WINDOWS/Microsoft.NET/Framework/v2.0.50727/mscorlib.dll
----------------------------------------
Suite
    Assembly Version: 2.2.8.28978
    Win32 Version: 2.2.8
    CodeBase: file:///C:/Program%20Files/Aaon%20Coil%20Products,%20Inc/ACP%20Software%20Suite/Suite.exe
----------------------------------------
System.Windows.Forms
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Windows.Forms/2.0.0.0__b77a5c561934e089/System.Windows.Forms.dll
----------------------------------------
System
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System/2.0.0.0__b77a5c561934e089/System.dll
----------------------------------------
System.Drawing
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
----------------------------------------
System.Core
    Assembly Version: 3.5.0.0
    Win32 Version: 3.5.30729.1 built by: SP
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Core/3.5.0.0__b77a5c561934e089/System.Core.dll
----------------------------------------
System.Management
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Management/2.0.0.0__b03f5f7f11d50a3a/System.Management.dll
----------------------------------------
System.Data
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_32/System.Data/2.0.0.0__b77a5c561934e089/System.Data.dll
----------------------------------------
System.Xml
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3082 (QFE.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Xml/2.0.0.0__b77a5c561934e089/System.Xml.dll
----------------------------------------
System.DirectoryServices
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.DirectoryServices/2.0.0.0__b03f5f7f11d50a3a/System.DirectoryServices.dll
----------------------------------------
System.Configuration
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_MSIL/System.Configuration/2.0.0.0__b03f5f7f11d50a3a/System.Configuration.dll
----------------------------------------
System.Transactions
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_32/System.Transactions/2.0.0.0__b77a5c561934e089/System.Transactions.dll
----------------------------------------
System.EnterpriseServices
    Assembly Version: 2.0.0.0
    Win32 Version: 2.0.50727.3053 (netfxsp.050727-3000)
    CodeBase: file:///C:/WINDOWS/assembly/GAC_32/System.EnterpriseServices/2.0.0.0__b03f5f7f11d50a3a/System.EnterpriseServices.dll
----------------------------------------
AcpSuiteFormHeader
    Assembly Version: 1.0.0.0
    Win32 Version: 1.0.0
    CodeBase: file:///C:/Program%20Files/Aaon%20Coil%20Products,%20Inc/ACP%20Software%20Suite/AcpSuiteFormHeader.DLL
----------------------------------------
+1  A: 

You should be able to write to any folder whose permissions are set to allow Everybody. You can set those permissions inside your installer, or even by hand.

egrunin
If the folder does not exist yet, my application will throw the exception whenever it tries to create it.
jp2code
So you are running as a 'User' when you attempt to create a directory in this location? You should be able to create directories there. Take yourself outside of .NET, is there something inside your corporate environment that disallows this? You might check if you can create one manually through explorer.
Wil P
@egrunin: Where could I find a good technique for doing this? I already know how to get into the Installer class. I just need to know how to edit/set permissions on a folder. If this is done from an installer, I take it I would be able to use the current User ID (assuming he/she is Super User or Admin). I've seen a few examples, but they are all very different.
jp2code
+1  A: 

I use CommonApplicationData and it seems to work fine with one caveat. I found that if an admin creates the subdirectory within the CommonApplicationData path then other users who are 'non-admin' cannot delete that directory. You may need to add a FileSystemAccessRule to the DirectoryInfo object when you create the sub directory contained within CommonApplicationData. There is an overload to the create method that allows you to specify an object of this type.

Edit: with code snippet.

public static void CreateWithEveryoneFullControlIfAdmin(this DirectoryInfo source)
{
    if (IsAdmin())
    {
        DirectorySecurity directorySecurity = Directory.GetAccessControl(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
        FileSystemAccessRule accessRule
            = new FileSystemAccessRule(@"BUILTIN\Users", FileSystemRights.FullControl,
                InheritanceFlags.ObjectInherit | InheritanceFlags.ContainerInherit,
                PropagationFlags.None,
                AccessControlType.Allow);

        bool modified = false;
        directorySecurity.ModifyAccessRule(AccessControlModification.Add,
            accessRule,
            out modified);

        if (modified)
        {
            source.Create(directorySecurity);
        }
        else
        {
            source.Create();
        }
    }
    else
    {
        source.Create();
    }
}

public static bool IsAdmin()
{
    WindowsIdentity identity = WindowsIdentity.GetCurrent();
    WindowsPrincipal principal = new WindowsPrincipal(identity);
    return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
Wil P
Rats! Nope, this code gave me the error too. I was hoping it would work, though.
jp2code
Given your stack trace I wonder if something else has a handle to log file stored in CommonApplicationData, what are you using for logging?
Wil P
It is a custom function that accepts the exception and passes in the file/routine that threw the exception - so I can trace down where the problem came from!
jp2code
Well, based on reviewing you stack trace I'd be suspicious that you have a lock on the file because another operation already has the file open and is writing to it.
Wil P
+1. I do lock the file, and there is threading going on. That could be a possibility. I'm not sure why the Public account would be the only one experiencing this, though.
jp2code
+2  A: 

I know you said you don't want to use IsolatedStorage because you don't want each user to have to have their own setup.

But have you looked at IsolatedStorage using the MachineStore? If I understand correctly (and I could be wrong, wouldn't be the first time) this should be shared by all users accessing your application.

using(IsolatedStorageFile store = IsolatedStorageFile.GetMachineStoreForApplication())
{
    // check if file exists or not
    try
    {
        using(IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(STG_FILE_NAME, FileMode.OpenOrCreate, store)) {
            StreamWriter sw = new StreamWriter(isfs);
            foreach(string key in m_values.Keys) {
                sw.WriteLine(key + "::" + m_values[key]);
            } // foreach
            sw.Flush();
        } // using
    } catch(IOException) {
        // generally because file is locked by another process...do nothing
    }
} // using

Alternatively, you could change your application's config file's permissions to allow everyone access. This could be done by a privileged user the first time your app is run.

http://www.techtalkz.com/c-c-sharp/153732-saving-files-so-any-user-can-access-them.html

FileInfo fileInfo = new FileInfo(path);
FileSecurity fileSecurity = fileInfo.GetAccessControl();
fileSecurity.AddAccessRule(new FileSystemAccessRule(
    "Users",
    FileSystemRights.FullControl,
    AccessControlType.Allow) );

fileInfo.SetAccessControl(fileSecurity);
Zippit
+1  A: 

OK, here is my two cents hope it helps you.

If you can hard-code some admin level credentials in your program, you may use impersonation for that part of the code that needs access to folders. Have a look here:

http://www.codeproject.com/KB/cs/cpimpersonation1.aspx

Personally, however, I would favour storing in ApplicationData.

Aliostad
Great Idea! However, our Network Administrator claims Sorbanes-Oxley act prevents him from creating an Admin account with a static password.
jp2code