Наше приложение установщика использует следующий код для проверки разрешений учетной записи службы:
try
{
using (svcIdentity.Impersonate())
{
using (SqlConnection conn = new SqlConnection(builder.ConnectionString)) // <<<
{
conn.Open();
...
Для краткости опущено:
- WindowsIdentity
svcIdentity
получен с помощью Win32 LSALogonUser
функция в advapi32.dll и LOGON32_LOGON_SERVICE
. builder
- это SqlConnectionStringBuilder, который создает строку подключения к локальной базе данных SQL Server.
Таргетинг .Net Framework 4.6.
Приложение работает с повышенными правами (requestedExecutionLevel level='requireAdministrator'
в app.manifest).
Этот код работал безупречно до Windows 10 версии 1803 (обновление апреля 2018 года).С тех пор конструктор SqlConnection (помеченный <<<) вызывает исключение: </p>
The type initializer for 'System.Data.SqlClient.SqlConnection' threw an exception.
Внутреннее исключение обеспечивает более глубокое понимание:
Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
Трассировка стека:
at System.Security.Policy.PEFileEvidenceFactory.GetLocationEvidence(SafePEFileHandle peFile, SecurityZone& zone, StringHandleOnStack retUrl)
at System.Security.Policy.PEFileEvidenceFactory.GenerateLocationEvidence()
at System.Security.Policy.PEFileEvidenceFactory.GenerateEvidence(Type evidenceType)
at System.Security.Policy.AssemblyEvidenceFactory.GenerateEvidence(Type evidenceType)
at System.Security.Policy.Evidence.GetHostEvidenceNoLock(Type type)
at System.Security.Policy.Evidence.GetHostEvidence(Type type, Boolean markDelayEvaluatedEvidenceUsed)
at System.Security.Policy.AppDomainEvidenceFactory.GenerateEvidence(Type evidenceType)
at System.Security.Policy.Evidence.GetHostEvidenceNoLock(Type type)
at System.Security.Policy.Evidence.RawEvidenceEnumerator.MoveNext()
at System.Security.Policy.Evidence.EvidenceEnumerator.MoveNext()
at System.Configuration.ClientConfigPaths.GetEvidenceInfo(AppDomain appDomain, String exePath, String& typeName)
at System.Configuration.ClientConfigPaths.GetTypeAndHashSuffix(AppDomain appDomain, String exePath)
at System.Configuration.ClientConfigPaths..ctor(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigPaths.GetPaths(String exePath, Boolean includeUserConfig)
at System.Configuration.ClientConfigurationHost.RequireCompleteInit(IInternalConfigRecord record)
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.ConfigurationManager.GetSection(String sectionName)
at System.Data.SqlClient.SqlConnection..cctor()
Трассировка стека указывает, что конструктору SqlConnection не удается открыть раздел конфигурации.У нашего app.config
нет раздела строк подключения, а machine.config
и security.config
на тестируемых компьютерах не менялись с 2017 года.
Код работает, когда:
Закомментирование using (svcIdentity.Impersonate)
,
или
при установке точки останова на линии непосредственно над конструктором SqlConnection ({
) и пошаговом выполнении кода (???),
или
при добавлении нашего приложения к разделу реестра, указанному в конце KB945701
Эта статья базы знаний об исправлении для Internet Explorer 9 кажется не связанной, за исключением того, что GetLocationEvidence
в первой строке трассировки стека, кажется, учитывает SecurityZone
, какие приложения перечислены в соответствующем разделе реестракажется, игнорирует.
Теперь мой вопрос:
Может кто-нибудь помочь мне понять, что именно идет не так, и если есть лучший способ исправить это, чем с неясным ключом реестра?Кажется «совпадением», что это изменение реестра работает, и я боюсь, что наш код может снова сломаться, если мы точно не поймем, почему он не работает.
Thx.