自动更新是很多 winform 应用程序可能都要具有的一个特性, 自动更新在.net 中实现起来可能相对就更容易一点.
简单一点写的话可能就是
wc.DownloadFile(.)
而很多.net 应用程序一般会有一个.config 文件, 如果你的exe是 test.exe的话,可能就有一个test.exe.config
有了这个场景, 我要说的错误就可以重现了:)
假设有一个test.exe.config 放在web server 上面需要更新, 那么对于客户端可能就是不管采用webclient 还是webrequest 甚至通过socket 来获取这个文件,一般情况下都没有问题,也就是说
webclient.DownloadFile("http://xxx/test/test.exe.comfig","c:\test.exe.config") 是ok的.
有些时候问题就出现了.
你会发现download file 的时候, 会返回一个500 错误, 如果把服务端的自定义异常关闭的话,就会有一下一个莫名其妙的错误.
Server Error in '/test' Application.
--------------------------------------------------------------------------------
Specified argument was out of the range of valid values. Parameter name: date
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. Parameter name: date
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[ArgumentOutOfRangeException: Specified argument was out of the range of valid values.
Parameter name: date]
System.Web.HttpCachePolicy.UtcSetLastModified(DateTime utcDate) +242
System.Web.HttpCachePolicy.SetLastModified(DateTime date) +40
System.Web.StaticFileHandler.ProcessRequest(HttpContext context) +1166
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication+IExecutionStep.Execute() +179
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +87
如何重现这个问题:
随便新建一个文件,后缀名改为test.exe.config , 放到 IIS 的一个虚拟目录下面, 然后把你web server 的时间改为比这个文件还要旧,比如改到2004年.然后浏览这个问题,就会出现以上的问题.
如何解决这个问题:
原因就是微软对静态的文件都采取了一个cache 策略,如果一个文件的上次修改日期比当前日期还新的话,他认为是不可思议,就会throw 一个异常. 所以你只要保证你的文件修改时间比当前时间老一点旧可以.
之所以出现这个问题,因为上海的时间比LA快一点, 今天上海的一个同事发布一个文件到美国server 的话, 就会出现这个问题,所以要么你把文件修改一下,要么等上16个小时就可以了:)
后来用reflector 看了一下就是一下代码造成的
{
utcDate = new DateTime(utcDate.Ticks - (utcDate.Ticks % ((long) 10000000)));
if (utcDate > DateTime.UtcNow) //..
{
throw new ArgumentOutOfRangeException("date");
}
if (!this._isLastModifiedSet || (utcDate > this._utcLastModified))
{
this.Dirtied();
this._utcLastModified = utcDate;
this._isLastModifiedSet = true;
}
}
通过这个小问题,有一点需要注意:不同地域之间文件更新的时候,一定要考虑微软常用的chchepolicy