Windows 服务在程序集加载时锁定
我有一个用 C# 编写的 Windows 服务。它还包括用于调试目的的独立控制台模式。它在几乎所有运行它的计算机上都能正常工作,但我们遇到了一种情况,当您尝试启动该服务时,它会锁定,然后由于超时而被终止。但是当在同一台机器上以控制台模式运行它时,它启动正常。
调试很痛苦,因为我实际上无法访问正在发生这种情况的机器,我必须通过人工代理。但经过一系列的反复试验和错误调试,我最终将原因缩小到程序集负载。根据日志文件,当它遇到对特定 dll 中任何数据类型的第一个引用时,它会立即停止。它甚至没有给出例外,它只是锁定。
[编辑] 经过进一步检查,似乎它并没有永久锁定,实际上只需要大约 40 秒即可完成加载库,这足以让 Windows 服务决定终止该进程。
有任何线索如何调试这种情况吗?
这是我可以重现它的最简单的解决方案。 “之前”显示,但“期间”和“之后”不显示。
private static void LoadAssembly()
{
Log("During");
MyNameSpace.MyClass x = new MyNameSpace.MyClass();
}
static void Main(string[] args)
{
try
{
// Leaving out code to handle command line parameters
// ...
//
Log("Before");
LoadAssembly();
Log("After");
if (Environment.UserInteractive)
{
Log("Starting in console mode");
ConnectionManager.Listen();
}
else
{
Log("Starting in service mode");
ServiceBase.Run(new RunAsService());
}
}
catch (Exception ex)
{
Log(ex.ToString());
}
}
I have a Windows Service written in C#. It includes a standalone console mode as well, for debugging purposes. It works fine on almost every computer it's been run on, but we ran into a situation where this service locks up when you try to start it, and then it gets killed because of timeout. But when running it in console mode on the same machine, it starts up fine.
It's a pain to debug because I don't actually have access to the machine this is happening on, I have to go through a human proxy. But after a bunch of trial and error debugging, I finally narrowed the cause down to assembly load. When it hits the first reference to any data type in a specific dll, it stops right there, according to the log file. It's not even giving an exception, it just locks up.
[Edit] After further examination, it appears it's not locking up permanently, it just takes about 40 seconds to actually finish loading the library, which is long enough for Windows services to decide to kill the process.
Any clue how to debug this kind of situation?
Here's about the simplest solution that I can reproduce it with. "Before" shows up, but "During" and "After" do not.
private static void LoadAssembly()
{
Log("During");
MyNameSpace.MyClass x = new MyNameSpace.MyClass();
}
static void Main(string[] args)
{
try
{
// Leaving out code to handle command line parameters
// ...
//
Log("Before");
LoadAssembly();
Log("After");
if (Environment.UserInteractive)
{
Log("Starting in console mode");
ConnectionManager.Listen();
}
else
{
Log("Starting in service mode");
ServiceBase.Run(new RunAsService());
}
}
catch (Exception ex)
{
Log(ex.ToString());
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
该程序集需要 45 秒才能连接,它会尝试连接到 Internet 以在加载程序集之前验证有关该程序集的某些内容,但在该特定计算机上,它被防火墙阻止。尝试启动 30 秒后,Windows 服务管理器放弃并终止该进程。
将程序集的加载移到服务启动之后,使其能够正确启动(尽管在开始响应之前有 45 秒的延迟)。
看起来这与生成出版商证据有关。从这里 http://msdn.microsoft.com/en-us/library/ bb629393.aspx:
将以下内容放入 app.config 文件中可以消除延迟:
The assembly was taking 45 seconds to connect, it tries to connect to the internet to verify something about the assembly before loading it, but on that particular machine it's blocked by the firewall. After 30 seconds of trying to start, Windows service manager gives up and kills the process.
Moving the loading of the assembly until after the service has been started allowed it to start up properly (although with a 45 second delay before it starts responding).
It looks like it was related to generating publisher evidence. From here http://msdn.microsoft.com/en-us/library/bb629393.aspx:
Putting the following in the app.config file got rid of the delay:
您是否在保持加载器锁定的同时在模块加载上执行操作?
请参阅此文章进行调试: http://msdn.microsoft.com/en-我们/library/ms172219.aspx
Are you doing things on module load while holding the loader lock?
See this article for debugging: http://msdn.microsoft.com/en-us/library/ms172219.aspx