在我的 .NET 客户端应用程序中,我使用 Scope=User 和 Roaming=True 的默认设置提供程序。这在大多数环境中都能正常工作,无论是客户端还是终端服务器,除了具有 Citrix 终端服务器场的客户。每当 属性。 Settings.Default.Save()
被调用,抛出如下异常:
System.UnauthorizedAccessException: Attempted to perform an unauthorized operation.
at System.Security.AccessControl.Win32.SetSecurityInfo(ResourceType type, String name, SafeHandle handle, SecurityInfos securityInformation, SecurityIdentifier owner, SecurityIdentifier group, GenericAcl sacl, GenericAcl dacl)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, SafeHandle handle, AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.NativeObjectSecurity.Persist(String name, AccessControlSections includeSections, Object exceptionContext)
at System.Security.AccessControl.FileSystemSecurity.Persist(String fullPath)
at System.Configuration.Internal.WriteFileContext.DuplicateTemplateAttributes (String source, String destination)
at System.Configuration.Internal.WriteFileContext.DuplicateFileAttributes(String source, String destination)
at System.Configuration.Internal.WriteFileContext.Complete(String filename, Boolean success)
at System.Configuration.Internal.InternalConfigHost.StaticWriteCompleted(String streamName, Boolean success, Object writeContext, Boolean assertPermissions)
at System.Configuration.Internal.DelegatingConfigHost.WriteCompleted(String streamName, Boolean success, Object writeContext, Boolean assertPermissions)
at System.Configuration.ClientSettingsStore.ClientSettingsConfigurationHost.WriteCompleted(String streamName, Boolean success, Object writeContext)
at System.Configuration.UpdateConfigHost.WriteCompleted(String streamName, Boolean success, Object writeContext)
at System.Configuration.MgmtConfigurationRecord.SaveAs(String filename, ConfigurationSaveMode saveMode, Boolean forceUpdateAll)
at System.Configuration.ClientSettingsStore.WriteSettings(String sectionName, Boolean isRoaming, IDictionary newSettings)
at System.Configuration.LocalFileSettingsProvider.SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection values)
at System.Configuration.SettingsBase.SaveCore()
at System.Configuration.SettingsBase.Save()
出现这个异常的原因:
System.Configuration.Internal.WriteFileContext
在用户的漫游配置文件中写入用户设置的新副本 (...newcfg
)。然后,DuplicateTemplateAttributes
尝试修改此文件的 ACL,并将所有权明确设置为当前用户。- 对于此客户,此操作失败,因为漫游配置文件存储在文件共享中,并且用户只有读取 和更改 权限,但没有完全控制。他们可能在 NTFS 中拥有完全控制权(因为默认情况下您是您创建的所有文件的“所有者”,并且作为所有者,无论您是否明确设置了“完全控制权”,您都可以对该文件执行任何操作),但似乎就像它在 SMB 共享级别上被阻止一样。
这种行为对我来说没有任何意义:鉴于 LocalFileSystemProvider
总是 使用当前用户(本地或漫游)的私有(private)配置文件文件夹,我们可以无论如何,安全地假设用户是所有者。
由于 WriteFileContext
捕获异常,删除临时 .newcfg
文件然后重新抛出,所以没有办法简单地在我的代码中捕获异常并重命名文件或以某种方式获取其内容,因为在抛出异常时它已被删除。
除了实现我自己的设置提供程序之外,我找不到任何简单的方法来解决这个问题。为此,似乎我什至不得不重建序列化部分之类的东西,因为用于此的所有 System.Configuration 东西都是内部的。当然,我不想破坏当前使用的设置,所以它看起来像一个荒谬的代码,只是为了重建一切,因为它只是“注释掉一行”(设置文件的所有者)。
还有什么我可以尝试的想法吗?
客户无法更改其文件共享权限中的任何内容...
最佳答案
我在 Citrix 上遇到过类似的问题 - AppData 被重定向到“更改和读取”网络共享(不是“完全控制”- 它适用于“完全控制”)。首次运行时,我们的应用程序将在第一次调用 Save() 时创建 user.config,但会在任何后续调用 Save() 时抛出 UnauthorizedAccessException。
答案似乎是在调用 Save() 之前删除 user.config 文件(如果存在)。
我们目前正在与我们的客户进行测试 - 当我有具体结果时我会更新我的答案。
更新:您需要在调用 Save() 之前“触摸”Settings.Default 中的每个设置,因为临时文件实际上已与现有 user.config 合并。通过在调用 Save() 之前调用以下方法,每次都会正确地重新创建 user.config(不会抛出 UnauthorizedAccessException)。
public static void ClearUserConfigFile()
{
//Touch each setting
foreach (SettingsProperty property in Settings.Default.Properties)
{
if (property.DefaultValue != Settings.Default[property.Name])
Settings.Default[property.Name] = Settings.Default[property.Name];
}
//Delete the user.config file
var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoaming);
var userConfigPath = config.FilePath;
try
{
if (File.Exists(userConfigPath) == true)
File.Delete(userConfigPath);
}
catch (Exception ex)
{
_log.ErrorFormat("Exception thrown while deleting user.config : {0}", ex.ToString());
}
}
关于c# - 如何解决需要完全控制/所有者权限的 LocalFileSettingsProvider,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20946627/