开发者

Safe Storage Locations for Any User, C#, Windows

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 Versio开发者_StackOverflow中文版n: 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
----------------------------------------


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);


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);
}


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜