在停止服务后,我用新版本替换了Windows服务的EXE。 EXE绝对是新版本,Windows资源管理器属性显示新版本。
但是,程序集(加载System.Reflection.Assembly.LoadFile
时)会报告.FullName
,这似乎表明它不是最新版本。
这在我部署到的第一个站点上没有发生,所以现在我的版本报告系统似乎表明该站点未升级。 (版本报告由单独的ASP.NET Web服务管理,该服务在某些目录中发布程序集的所有版本,正是此Web服务调用System.Reflection.Assembly.LoadFile
)。
这里有什么?是否存在某种缓存(Web服务最后会在升级之前检查该程序集?)
代码很基本:
System.IO.DirectoryInfo assemblies = new System.IO.DirectoryInfo(DirectoryName);
foreach (var f in assemblies.GetFiles(Pattern))
{
var a = System.Reflection.Assembly.LoadFile(f.FullName);
l.Add(new VersionManager.Assembly(f.Name, f.LastWriteTime, a.FullName));
}
return l; // l is List<VersionManager.Assembly>
删除EXE并替换它(而不是仅覆盖它)无效。
我写了一个小的控制台应用程序,并在上次查询Web服务约3.5小时后直接在系统上运行它,并且非常惊讶地发现它返回了正确的版本。然后我查询了Web服务,它返回了正确的版本。
二进制或Web服务没有任何改变(尽管它所属的Web应用程序可能已被回收,但Web服务本身并不存储它检索到的有关程序集的信息,它只是在响应中将它们发送出去)
更新 - 2011-12-20:
此问题已重新发生。我部署到一个站点,然后在所有站点上运行我的库存程序,并且站点报告了正确的版本。我部署到另外两个站点,DLL上的属性提供了正确的版本,但通过在另外两个站点上加载System.Reflection报告的版本信息已过期。它似乎在第一次通话后被缓存,并重新用于第二次通话。
澄清
有一个IIS ASP.NET(.NET 2.0)Web服务,它报告系统目录中的组件的DLL版本(不属于Web服务的目录)。其中一个目录包含Windows服务的EXE和配置。当Windows服务停止,EXE被替换并且Web服务被询问时,它有时会报告旧版本。如果暂时没有调用Web服务,则会在下次查询时正确报告替换EXE。如果在替换之前调用了Web服务,则在替换之后它不会报告任何更改,尽管已经替换了EXE并通过Windows资源管理器等报告了正确的版本。
我注意到LoadFile没有伴随任何类型的卸载。即使对程序集的引用超出了范围,我想知道它是否仍然保持加载状态(因此在后续调用中不会刷新,因此仍然会报告过期信息),直到IIS或其他任何内容过期。有没有办法卸载组件?有没有办法获得汇编文件的版本信息而不首先加载它?
答案 0 :(得分:1)
使用System.Reflection.Assembly.LoadFile(FileName)加载程序集,在没有完全卸载AppDomain的情况下无法卸载程序集。
为了检查装配而不加载它,另一种方法是改变:
var a = System.Reflection.Assembly.LoadFile(f.FullName);
到此:
var a = System.Reflection.AssemblyName.GetAssemblyName(f.FullName);
答案 1 :(得分:1)
不应该使用Inspect Appdomain解决问题吗?或安全性是否禁止创建新的domaion?
using System;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// Create a new domain for loading extra Assemblies
AppDomain inspectDomain = AppDomain.CreateDomain("Inspect");
// attach handler to show that no assemblies are loaded in the current domain
AppDomain.CurrentDomain.AssemblyLoad +=new AssemblyLoadEventHandler(CurrentDomain_AssemblyLoad);
// another prove
int startcount = AppDomain.CurrentDomain.GetAssemblies().Length;
// now call the inspection method in the inspectionDomain
inspectDomain.DoCallBack(new CrossAppDomainDelegate(Inspect));
// what is the count on assemblies in the curent domain
int endcount = AppDomain.CurrentDomain.GetAssemblies().Length;
// show it
Console.WriteLine("Appdomain {2} # start: {0} and end {1}",
startcount,
endcount,
AppDomain.CurrentDomain.FriendlyName);
// unload our inspectdomain and therefor the loaded assemblies
AppDomain.Unload(inspectDomain);
// pause so we can see
Console.ReadLine();
}
static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
{
// write a line for a loaded assembly
Console.WriteLine("program domain: {0}", args.LoadedAssembly.FullName);
}
public static void Inspect()
{
Console.WriteLine("Inspecting...");
int startcount = AppDomain.CurrentDomain.GetAssemblies().Length;
var assemblies = new DirectoryInfo(
@"C:\Windows\Microsoft.NET\Framework64\v2.0.50727");
foreach (var f in assemblies.GetFiles("System.Data.*.dll"))
{
var a = System.Reflection.Assembly.LoadFile(f.FullName);
Console.WriteLine("name:{0}, rt:{1}", a.FullName, a.ImageRuntimeVersion);
}
int endcount = AppDomain.CurrentDomain.GetAssemblies().Length;
Console.WriteLine("Appdomain {2} start: {0} and end {1}",
startcount,
endcount,
AppDomain.CurrentDomain.FriendlyName);
Console.WriteLine("Done Inspecting...");
}
}
}