WindowsIdentity.Impersonate 在 2018 年 4 月 (1803) 更新后抛出“灾难性故障(来自 HRESULT 的异常:0x8000FFFF (E_UNEXPECTED))”

fli*_*lip 5 impersonation windows-10 .net-4.6

我们的安装程序应用程序使用以下代码来验证服务帐户权限:

try
{
    using (svcIdentity.Impersonate())
    {
        using (SqlConnection conn = new SqlConnection(builder.ConnectionString))  // <<<
        {
            conn.Open();
            ...
Run Code Online (Sandbox Code Playgroud)

为简洁起见省略:

  • 所述svcIdentity的WindowsIdentity通过使用Win32 LSA获得LogonUser在ADVAPI32.DLL功能和LOGON32_LOGON_SERVICE
  • builder 是一个 SqlConnectionStringBuilder,它构建到本地 SQL Server 数据库的连接字符串。

针对 .Net Framework 4.6。

该应用程序运行提升(requestedExecutionLevel level='requireAdministrator'在 app.manifest 中)。

此代码在 Windows 10 版本 1803(2018 年 4 月更新)之前运行完美无缺。从那以后,SqlConnection 构造函数(标记为<<<)抛出异常:

The type initializer for 'System.Data.SqlClient.SqlConnection' threw an exception.
Run Code Online (Sandbox Code Playgroud)

内部异常提供了更多洞察力:

Catastrophic failure (Exception from HRESULT: 0x8000FFFF (E_UNEXPECTED))
Run Code Online (Sandbox Code Playgroud)

堆栈跟踪:

   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()
Run Code Online (Sandbox Code Playgroud)

堆栈跟踪表明 SqlConnection 构造函数无法打开配置节。我们app.config没有连接字符串部分,machine.config并且security.config在经过测试的计算机上自 2017 年以来没有改变。

该代码在以下情况下有效:

  • 注释掉using (svcIdentity.Impersonate)

    或者

  • 在 SqlConnection 构造函数 ( {)正上方的行上设置断点并逐步执行代码 (???) 时,

    或者

  • 将我们的应用程序添加到KB945701末尾提到的注册表项时

那篇关于 Internet Explorer 9 修复程序的知识库文章似乎无关,只是GetLocationEvidence在堆栈跟踪的第一行似乎考虑SecurityZone到了相应注册表项中列出的应用程序似乎忽略了。

现在我的问题:

任何人都可以帮助我了解到底出了什么问题,以及是否有比使用晦涩的注册表项更好的方法来解决这个问题?这个注册表更改有效似乎是一个“巧合”,如果我们不完全理解它失败的原因,我担心我们的代码可能会再次中断。

谢谢。