我的一位同事遇到了以下问题(因此某些相关细节可能需要进一步审查):
服务器是 Windows 2008 Server。有一个正在运行的 Windows 服务(exe(.net),也使用 .NET 程序集)。dll 和/或 exe 有一些错误。dll 中添加和删除了一些调试消息。此新版本的 dll 及其重新编译的 exe 通过 ftp 传输到此服务器,服务已停止,现有 dll 和 exe 已重命名,并替换为新版本,然后服务已启动。
我们仍然会看到从 dll 中删除的调试消息。它们在新代码中不存在。
服务器已重新启动。
旧的 dll 是否以某种方式缓存在某处?谢谢。
更新
刚刚发生了以下事情:
- 最近重命名的 assembly.old 已被物理删除(这是唯一的副本)
- 旧的调试消息仍然存在!
- 卸载/重新安装服务(尽管我们认为可以通过重新启动来解决)
- 作品。
因此,了解了之前发生的情况(包括重新启动操作系统)以及现在发生的情况,Windows 以某种方式跟踪了 dll(?),并且当一个副本被重命名时,Windows 会拒绝更新并(在它看来)将 assembly.old 关联为 assembly.dll。而不是放置在其位置上的新 assembly.dll?
因为 assembly.dll 和 assembly.old 位于同一目录中,所以在操作系统重启后 - 继续查看旧的 dll。assembly.dll 并且没有 assembly.old - 有效。
让我困惑的是,你如何控制这个?或者说,这方面的文档在哪里?
其他信息:64 位版本的服务器。虚拟机。
答案1
这可能是由于.NET 定位程序集的方式所致,如下所述:
.NET 运行时如何定位程序集
http://msdn.microsoft.com/en-us/library/yx7xezcf%28v=VS.100%29.aspx
请注意以下几点:
“编译器在构建时将静态引用记录在程序集清单的元数据中。动态引用是通过调用各种方法(例如 System.Reflection.Assembly.Load)动态构建的。”
如果您的引用是静态的,您可以检查正在执行的程序集的元数据以查找清单。可以使用 ILDASM 或其他工具(例如 ILSpy)检查清单。如果它是动态的,则定位过程会很复杂。
我的经验是,如果存在多个 CLR 版本(例如,2.0 和 4.0),结果可能会出乎意料。还有其他几个因素,例如:
- 机器配置和应用程序配置;
- 如果应用程序全部是托管代码,或者有一些非托管代码(COM/Interop);
- 如果执行/调用程序集和被调用的程序集是平台无关的(“任何 CPU”),或者是平台特定的(x86 或 x64)。
还可以同时在一个进程中运行 2.0 和 4.0 CLR 代码(并行执行)。
我认为这应该是在开发环境中可重现的,并且期望消费者了解或处理所有可能的情况是不现实的。
.NET 进程内并行执行
http://msdn.microsoft.com/en-us/library/ee518876%28VS.100%29.aspx
组件:定位、绑定和部署
http://www.codeproject.com/KB/install/assemblydeployment.aspx
当您运行 Microsoft SysInternals 的 Process Explorer、选择服务进程和 .NET Assemblies 选项卡时,它应该会显示所有已加载的各种程序集,以便您可以验证是否加载了正确的文件:
答案2
好吧,您自己回答了这个问题。您将新的 DLL 放到磁盘上,但当您运行某些代码时,它似乎仍在使用旧 DLL。因此,您的内存中一定还残留着旧 DLL 的副本。
尝试一下——创建一个快捷方式,并使用它作为运行的命令:
%windir%\system32\rundll32.exe advapi32.dll,进程空闲任务
随意命名...例如“Memory Cache Flusher”。在程序测试运行期间运行它。