.NET 应用程序在启动时挂在 Windows 2012 上

.NET 应用程序在启动时挂在 Windows 2012 上

我们有一位客户为我们提供了一台 Windows 2012 Hyper-V 服务器,该服务器具有 Windows 2012 Multipoint 客户操作系统,我们在其上运行基于 .NET(v3.5)的软件产品。

不幸的是,我们的 Windows 服务无法启动许多机器。它们每台都会写入日志先于其他任何事情,例如:

<DllImport("Kernel32.dll", _
            SetLastError:=True, _
            CharSet:=CharSet.Unicode, _
            entrypoint:="OutputDebugString", _
            CallingConvention:=CallingConvention.StdCall)> _
Public Shared Sub OutputDebugString(ByVal str As String)
End Sub

Protected Overrides Sub OnStart(ByVal args() As String)
    OutputDebugString("Service is starting...")
    m_worker = New Thread(AddressOf serviceThread)
    m_worker.Start()
End Sub
'...

问题是这个调试字符串从未进入 Dbgview,程序也不使用任何 CPU(它始终处于 0% 并且服务最终会超时。

我们有一个开关,可以添加到服务中,以便能够将其作为 WinForms 应用程序运行来测试类似的事情,当我尝试使用此开关运行它时,程序需要大约 2 分钟才能到达第一行并输出这个调试字符串,所以难怪服务没有启动!!

我打开了 Fusion,它可以正常生成融合日志,而且似乎没有任何错误,但我不明白为什么这些 .NET 应用程序需要这么长时间才能到达我们的代码库?

我们还有许多其他客户(尽管没有一个使用 Windows 2012),这种情况只发生在一些机器上。依赖程序集数量不超过十几个,整个应用程序不到 4MB。

有人可以建议如何进一步调查此事吗?

事件查看器似乎为空,只有“服务未及时响应启动或控制请求”......?

客人的规格是4CPU和4GB RAM,硬盘有足够的空间。

更新:奇怪的是,当机器有互联网连接时,问题似乎就消失了??现在我们的软件不需要这个(因为我们假设它是在没有访问权限的网站上运行的),但可能需要进行一些许可检查,或者依赖于我们网络上不存在的服务器的组策略?(他们确实从他们的实验室给了我们一台机器的克隆版)。有什么想法吗?

答案1

这通常是由于 .Net Framework 尝试验证您正在加载的所有程序集上的签名而导致的。Microsoft 一些 知识库博客 帖子关于这个问题,简短的回答是您可以在machine.config应用程序的config文件中禁用它:

<configuration>
    <runtime>
        <generatePublisherEvidence enabled="false"/>
    </runtime>
</configuration>

长话短说shawnfa 很好地解释了

当 CLR 加载具有 Authenticode 签名的程序集时,它将始终尝试验证该签名。这与 Windows 加载器相反,Windows 加载器仅在特定情况下验证文件的签名,例如当文件是 ActiveX 控件时。此验证可能非常耗时,因为它可能需要多次访问网络以下载最新的证书吊销列表,还要确保在通往受信任根的途中有完整的有效证书链。因此,当将 Authenticode 签名应用于程序集时,加载该程序集时出现几秒钟的延迟并不罕见。

如果您处于受限访问网络上,则每次呼叫 CRL 分发点都必须超时,这可能会导致延迟超过 2 分钟。

在调试方面,通常可以通过在调试器中中断代码并查看调用堆栈来解决此类挂起问题。进程探索器应该能够加载符号并表明您正在等待 CRL。

相关内容