【问题标题】:Safe Storage Locations for Any User, C#, Windows任何用户、C#、Windows 的安全存储位置
【发布时间】:2010-09-13 21:28:57
【问题描述】:

我的公司有一个应用程序,它必须以全局方式存储设置,以便具有多种访问类型的员工可以运行该程序。

我们的大多数员工都使用公共帐户访问该计划,这意味着他们不必登录 - 有一个名为 Public 的登录 ID,任何人都可以使用。您可以猜到,公共帐户受到严格限制!

因此,我似乎找不到让我的应用程序将数据写入 PC 的方法。错误始终是相同的未授权访问异常。

我尝试过使用以下路径,但都失败了:

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

我不想使用独立存储,因为我不想为每个登录到我们工厂的多台 PC 之一的个人配置应用程序。

有没有办法说,“嘿,我的应用程序是管理员。给我访问权限!” ???

我们目前仅限于 .NET Framework 3.5。

编辑

异常消息:

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

【问题讨论】:

  • 您应该能够写入 CommonApplicationData。你能告诉我们你的代码吗?
  • 你尝试写在Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)目录还是C:\ProgSuite\Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)目录下(最后写错了)。如果“公共”用户无权访问在他的个人资料中 (!!!) 的Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),那么您必须与您公司的管理员讨论您的要求。您应该找到有关“公共”用户具有写入权限的目录的更多信息。
  • 我假设您正在尝试写入目录Path.Combine(Environment.GetFolderPath(SpecialFolder.CommonApplicationData), "ProgramSuite")?我没有尝试直接写入 CommonApplicationData,只写入其中的子目录。
  • 您是否有另一个进程或句柄打开了该文件的读写?

标签: c# windows path


【解决方案1】:

我知道您说过您不想使用 IsolatedStorage,因为您不希望每个用户都必须拥有自己的设置。

但是您是否使用 MachineStore 研究过独立存储?如果我理解正确(我可能是错的,这不是第一次),这应该由访问您的应用程序的所有用户共享。

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

或者,您可以更改应用程序的配置文件的权限以允许所有人访问。这可以由特权用户在您的应用首次运行时完成。

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

【讨论】:

    【解决方案2】:

    我使用 CommonApplicationData,但有一个警告似乎可以正常工作。我发现如果管理员在 CommonApplicationData 路径中创建子目录,那么其他“非管理员”用户无法删除该目录。在创建 CommonApplicationData 中包含的子目录时,您可能需要将 FileSystemAccessRule 添加到 DirectoryInfo 对象。 create 方法有一个重载,允许您指定此类型的对象。

    编辑:使用代码 sn-p。

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

    【讨论】:

    • 老鼠!不,这段代码也给了我错误。不过,我希望它会起作用。
    • 鉴于您的堆栈跟踪,我想知道是否还有其他东西可以处理存储在 CommonApplicationData 中的日志文件,您使用什么进行日志记录?
    • 这是一个自定义函数,它接受异常并传入引发异常的文件/例程——这样我就可以追查问题的根源!
    • 好吧,根据查看您的堆栈跟踪,我怀疑您锁定了文件,因为另一个操作已经打开了文件并正在写入。
    • +1。我确实锁定了文件,并且正在进行线程处理。这可能是一种可能性。不过,我不确定为什么只有公共帐户会遇到这种情况。
    【解决方案3】:

    您应该能够写入权限设置为允许所有人的任何文件夹。您可以在安装程序中设置这些权限,甚至可以手动设置。

    【讨论】:

    • 如果该文件夹尚不存在,我的应用程序将在尝试创建它时抛出异常。
    • 所以当您尝试在此位置创建目录时,您是以“用户”身份运行的吗?您应该能够在那里创建目录。将自己置于 .NET 之外,您的公司环境中是否存在不允许这样做的东西?您可以检查是否可以通过资源管理器手动创建一个。
    • 我在哪里可以找到一个很好的技术来做到这一点?我已经知道如何进入安装程序类。我只需要知道如何编辑/设置文件夹的权限。如果这是从安装程序完成的,我认为我将能够使用当前的用户 ID(假设他/她是超级用户或管理员)。我看过一些例子,但它们都非常不同。
    【解决方案4】:

    好的,这是我的两分钱,希望对您有所帮助。

    如果您可以在程序中对某些管理员级别的凭据进行硬编码,则可以对需要访问文件夹的那部分代码使用模拟。看看这里:

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

    不过,就我个人而言,我更倾向于存储在 ApplicationData 中。

    【讨论】:

    • 好主意!但是,我们的网络管理员声称 Sorbanes-Oxley 法案阻止他使用静态密码创建管理员帐户。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-01-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-07
    • 2018-03-26
    • 1970-01-01
    相关资源
    最近更新 更多