Почему использование ConfigurationManager.GetSection вызывает "SecurityException: Request failed", но ConfigurationManager.OpenExeConfiguration нет?

У меня есть кое-что любопытное, что я надеюсь, что эксперт .Net может мне помочь.

У меня есть пользовательский раздел конфигурации и его ухватить Я делаю это:

var s = (TestConfigurationSection)ConfigurationManager
    .GetSection("testSection");

Я запускаю это на своей машине разработки (Windows 7, 64 бит, Windows полностью обновлен), и он отлично работает.

Я беру exe с этим кодом и помещаю его в каталог внутри c:\users\public на машине Windows Server 2008 R2, откройте командную строку как администратор, запустите его, и я получаю:

System.Configuration.ConfigurationErrorsException: Произошла ошибка при создании обработчика раздела конфигурации для testSection: запрос не выполнен. (C:\Users\Public\configtest\AppConfigTestConsoleApplication.exe.Config строка 10) --- > System.Security.SecurityException: запрос не выполнен.

Теперь я изменил этот код, чтобы сделать это:

var config = ConfigurationManager.OpenExeConfiguration(
    ConfigurationUserLevel.None);
var s = (TestConfigurationSection) config
    .GetSection("testSection");

и он отлично работает на обеих машинах.

Итак, я умеренно счастлив (насколько мне нравится приложение), но этот маленький Гремлин в моей голове смущен, поэтому я спрашиваю здесь:

Почему это так?


Шаги по воспроизведению

Создайте новый проект приложения Console Console Console в Visual Studio 2010 и замените содержимое Program.cs на следующее:

using System;
using System.Configuration;

namespace AppConfigTestConsoleApplication
{
    public class TestConfigurationSection : ConfigurationSection
    {
        [ConfigurationProperty("someSetting")]
        public int SomeSetting
        {
            get { return (int) this["someSetting"]; }
            set { this["someSetting"] = value; }
        }
    }

    internal class Program
    {
        private static void Main()
        {
            try
            {
                var s = (TestConfigurationSection) ConfigurationManager
                    .GetSection("testSection");
                Console.WriteLine("First Method worked: " + s.SomeSetting);
            }
            catch (Exception ex)
            {
                Console.WriteLine("First method failed");
                Console.WriteLine(ex.ToString());

                if (ex.InnerException != null)
                {
                    var eex = ex.InnerException as SecurityException;
                    Console.WriteLine("Action: '{0}'", eex.Action.ToString());
                    Console.WriteLine("Demanded: '{0}'", eex.Demanded.ToString());
                    Console.WriteLine("RefusedSet: '{0}'", eex.RefusedSet);
                    Console.WriteLine("GrantedSet: '{0}'", eex.GrantedSet);
                }

                try
                {
                    var config = ConfigurationManager.OpenExeConfiguration(
                        ConfigurationUserLevel.None);

                    var s = (TestConfigurationSection) config
                        .GetSection("testSection");

                    Console.WriteLine("Second Method worked: " 
                        + s.SomeSetting);
                }
                catch (Exception x)
                {
                    Console.WriteLine("Even the second method failed!");
                    Console.WriteLine(ex.ToString());
                }
            }
        }
    }
}

Затем добавьте файл конфигурации приложения и замените его следующим текстом:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>  
    <section
      name="testSection"
      type="AppConfigTestConsoleApplication.TestConfigurationSection, AppConfigTestConsoleApplication"
      requirePermission="false"
      allowDefinition="Everywhere" />  
  </configSections>
  <testSection someSetting="10"></testSection>
</configuration>

Скомпилируйте и запустите, и это результат, который я получил:

C:\Users\Public\configtest>AppConfigTestConsoleApplication.exe
First method failed
System.Configuration.ConfigurationErrorsException: An error occurred creating the configuration section handler for testSection: Request failed. (C:\Users\Public\configtest\AppConfigTestConsoleApplication.exe.Config line 10) ---> System.Security.SecurityException: Request failed.
   at System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, RuntimeMethodHandleInternal method, RuntimeType parent, UInt32 invocationFlags)
   at System.RuntimeMethodHandle.PerformSecurityCheck(Object obj, IRuntimeMethodInfo method, RuntimeType parent, UInt32 invocationFlags)
   at System.Reflection.RuntimeConstructorInfo.Invoke(BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at System.Reflection.ConstructorInfo.Invoke(Object[] parameters)
   at System.Configuration.TypeUtil.InvokeCtorWithReflectionPermission(ConstructorInfo ctor)
   at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.CreateSectionImpl(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
   at System.Configuration.RuntimeConfigurationRecord.RuntimeConfigurationFactory.CreateSectionWithRestrictedPermissions(RuntimeConfigurationRecord configRecord, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
   at System.Configuration.RuntimeConfigurationRecord.CreateSection(Boolean inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader)
   at System.Configuration.BaseConfigurationRecord.CallCreateSection(Boolean inputIsTrusted, FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentConfig, ConfigXmlReader reader, String filename, Int32 line)
   --- End of inner exception stack trace ---
   at System.Configuration.BaseConfigurationRecord.EvaluateOne(String[] keys, SectionInput input, Boolean isTrusted, FactoryRecord factoryRecord, SectionRecordsectionRecord, Object parentResult)
   at System.Configuration.BaseConfigurationRecord.Evaluate(FactoryRecord factoryRecord, SectionRecord sectionRecord, Object parentResult, Boolean getLkg, Boolean getRuntimeObject, Object& result, Object& resultRuntimeObject)
   at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
   at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
   at System.Configuration.BaseConfigurationRecord.GetSectionRecursive(String configKey, Boolean getLkg, Boolean checkPermission, Boolean getRuntimeObject, Boolean requestIsHere, Object& result, Object& resultRuntimeObject)
   at System.Configuration.BaseConfigurationRecord.GetSection(String configKey)
   at System.Configuration.ClientConfigurationSystem.System.Configuration.Internal.IInternalConfigSystem.GetSection(String sectionName)
   at System.Configuration.ConfigurationManager.GetSection(String sectionName)
   at AppConfigTestConsoleApplication.Program.Main()
Action: 'Demand'
Demanded: '<PermissionSet class="System.Security.PermissionSet"
version="1"
Unrestricted="true"/>
'
RefusedSet: ''
GrantedSet: ''
Second Method worked: 10

Монитор процессов

Я запустил Process Monitor и установил фильтр следующим образом:

Process Monitor Filter

И это оставило 508 событий, все из которых:

  • ИМЯ НЕ НАЙДЕНА
  • НЕТ БОЛЬШЕ ЗАЯВЛЕНИЙ
  • ПУТЬ НЕ НАЙДЕНА
  • ФАЙЛ ЗАБЛОКИРОВАН С ТОЛЬКО ЧИТАТЕЛЯМИ.
  • НЕТ ТАКОГО ФАЙЛА (только один раз для C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\93e7df09dacd5fef442cc22d28efec83\mscorlib.ni.dll и C:\Users\Public\configtest\AppConfigTestConsoleApplication.exe.config)
  • ОБНОВЛЕНИЕ БУФЕРА (для HKCU\Панель управления\Рабочий стол \MuiCached\MachinePreferredUILanguages ​​, HKCU\Программное обеспечение\Microsoft\Windows\CurrentVersion\Explorer\Папки для пользователей\Кэш

Есть ли у кого-нибудь какие-либо советы по поводу того, какой фильтр установить, чтобы добраться до основной причины?

Ответ 1

У меня было такое же поведение, когда сборка была "заблокирована" (на вкладке свойств файла). Файлы были отправлены по электронной почте через zip администратору. Когда он сэкономил приложение, бит блока был добавлен... так же, как при загрузке файла из Интернета. После того как мы очистили блок, он работал нормально.

Ответ 2

ConfigurationManager.GetSection(String):

извлекает файл конфигурации, полученный путем слияния файла конфигурации приложения, файла конфигурации локального пользователя и файла конфигурации роуминга.


ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel):

Параметр userLevel определяет местоположение открытого файла конфигурации, указывая, нет ли у него пользовательского уровня (файл конфигурации находится в том же каталоге, что и приложение)

Итак, они открывают разные файлы. Посмотрите, используя ProcessMonitor, чтобы узнать, к каким файлам обращаются, и почему возникает исключение и в каком файле.

Ответ 3

Я знаю, что это старый поток, но недавно я столкнулся с этой проблемой при работе с клиентом и думал, что опубликую другое предложение. В моем случае проблема заключалась в использовании нестатического метода ConfigurationManager, который может вызвать SecurityException в определенных конкретных условиях (таргетинг на платформу .NET Framework 4 и установка на сетевой диск, а в этом случае также отключается Windows Update). Ниже приведена более подробная информация об этой проблеме и исправление от Microsoft:

https://support.microsoft.com/en-us/help/2580188/fix-system.security.securityexception-occurs-when-a-.net-framework-4-based-application-that-calls-a-static-method-in-the-system.configuration.configurationmanager-class-runs-on-a-network-share