2014-01-06 3 views
5

В моем клиентском приложении .NET я использую поставщик настроек по умолчанию с Scope = User и Roaming = True. Это отлично работает в большинстве сред, независимо от того, клиент или сервер терминалов, за исключением клиента с фермой сервера терминалов Citrix. Всякий раз, когда Properties. Settings.Default.Save() называется следующее исключение:Как работать с LocalFileSettingsProvider, требующий полного доступа/OwnerRights

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 этого файла и явно установить права собственности на текущего пользователя.
  • В случае этого клиента это терпит неудачу, потому что перемещаемый профиль хранится на общем файловом и пользователи имеют только Read и Изменить разрешения, но не Full Control. Вероятно, у них есть полный контроль в NTFS (потому что по умолчанию вы являетесь «Владельцем» всех создаваемых вами файлов, и как владелец вы можете делать что-либо с файлом независимо от того, установлен ли в явном виде «Полный контроль»), но кажется как и его блокировка на уровне SMB.

Такое поведение не имеет никакого смысла для меня: Учитывая, что LocalFileSystemProviderвсегда использует личную папку профиля текущего пользователя (локальный или роуминга), то можно смело предположить, что пользователь является владельцем в любом случае ,

Поскольку WriteFileContext перехватывает исключение, удаляет временный .newcfg файл, а затем rethrows, нет никакого способа, чтобы просто поймать исключение в моем коде и переименовать файл или каким-то образом захватить его содержимое, так как он уже удален, когда исключение ,

Я не мог найти простой способ обойти эту проблему, кроме реализации моего собственного поставщика настроек. Для этого мне кажется, что мне даже придется перестроить такие вещи, как сериализационная часть, поскольку весь материал System.Configuration, используемый для этого, является внутренним. И, конечно же, я не хочу нарушать используемые в настоящее время настройки, поэтому это выглядит как нелепое количество кода, просто для того, чтобы перестроить все, как есть, только с одной строкой, прокомментированной (установка владельца файла).

Любые идеи, что еще я мог попробовать?

Там нет никакого способа клиент меняет что-либо в своих акций файл разрешений ...

+0

Примечание. Это приложение предназначено для .NET 2/3.5 CLR. Таргетинг .NET 4.0/4.5 создает одно и то же исключение, при этом только трассировка стека пропускает несколько строк, поэтому обновление до более новой версии .NET не помогает. – realMarkusSchmidt

+0

@realMarkusScmidt Вы могли найти решение проблемы? В моем случае он отлично работает в случае обычной папки данных приложения, но проблема возникает в случае папки данных приложения, то есть перенаправлено. Я получаю то же исключение. –

ответ

1

я испытал подобную проблему на Citrix - AppData перенаправляется на «Change & Read» сетевой ресурс (не «Full Control »- работает над« Полный контроль »). При первом запуске наше приложение создаст user.config при первом вызове Save(), но выдает UnauthorizedAccessException при любых последующих вызовах Save().

Ответ заключается в том, чтобы удалить файл user.config, если он существует до вызова Save().

В настоящее время мы тестируем это с нашим клиентом - я обновлю свой ответ, когда у меня появятся конкретные результаты.

Обновление: Вам необходимо «прикоснуться» к каждой настройке в параметрах Settings.Default перед вызовом Save(), поскольку временный файл фактически слит с существующим user.config. Вызвав следующий метод перед вызовом Save(), пользователь.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()); 
    } 
} 
+0

Я попытался удалить файл конфигурации перед его сохранением, но это дает мне исключение: «Файл конфигурации был изменен другой программой». –

Смежные вопросы