ASPNet_Compiler的编译过程

最近手头的一个ASP.Net的项目不时会出现编译错误,提示某个控件ascx类不存在,但该控件明明就在同一个网站下。错误有时候会突然出现,而一旦出现错误再多次编译也无法消除。由于公司使用脚本编译,而不是用msbuild或Visual Studio直接编译。事实上用Visual Studio编译从来没有出过错。用ProcExp看了一下build时编译时到底执行了什么:

aspnet_compiler . exe -d -v  /  -p  < source webroot >   < target webroot >

主要就是这一条命令。难道是编译器有bug?再细究发现aspnet_compiler.exe又调用了csc.exe(C#编译器):

" C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\csc.exe "   / noconfig  / fullpaths @ " C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\root\1c85b622\f7798d18\mz_xtoba.cmdline "

到Temporary ASP.NET Files\root\1c85b622\f7798d18目录下查看,发现很多.cmdline, .err, .out, .compiled等文件,还有很多.cs文件!原来那些网页或AppCode下的.cs文件在这里被重组并分组了:App_Code.n.cs; App_Web_<xxx>.n.cs; (n=0~...)。如果网页比较多的话,就会有多组App_Web_<xxx>.n.cs。编译器会一组一组地编译n个cs文件,然后下一组的cs编译会引用上一组编译生成的DLL(在.cmdline里):

/ t :library   / utf8output  / R: " System.Web.Services.dll "   / R: " App_global.asax.dll "   / R: " App_Web_rydiwb8f.dll "     / out: " App_Web_bl8pd2er.dll "  App_Web_bl8pd2er . 9 . cs App_Web_bl8pd2er . 0 . cs   (已省略一些路径和参数。这里面App_Web_bl8pd2er.dll就引用了上一组cs生成的App_Web_rydiwb8f.dll)

但怎么决定文件的分组呢,哪些文件要放在前面的组,哪里文件要放在后面?我们在.aspx.xxx.compiled或.ascx.xxx.compiled里发现了该文件依赖于哪些文件的信息:

<? xml version="1.0" encoding="utf-8" ?>
< preserve  resultType ="3"  virtualPath ="/Result.aspx"  hash ="84d987223"  filehash ="a23fecda9fe4d6d8"  flags ="110000"  assembly ="App_Web_wt3qqawy"  type ="ASP.result_aspx" >
    
< filedeps >
        
< filedep  name ="/controls/Control1.ascx"   />
        
< filedep  name ="/controls/Control1.ascx.cs"   />
        
< filedep  name ="/Result.aspx"   />
        
< filedep  name ="/Result.aspx.cs"   />
    
</ filedeps >
</ preserve >

于是猜想编译器就是在内存中维护用这样的依赖关系,并可以产生一个树来决定文件分组先后。但.compiled文件只在编译成功那个页面后才会生成。
明白了这些,再来找项目的问题:原来Result.aspx.cs里动态创建了Control2:

Control2 ctrl  =  (Control2)page.LoadControl( " controls\\Control2.ascx " );
page.PlaceHolder.Controls.Add(ctrl);
但在.compiled文件里看不到有这样的依赖关系!所以编译器不知道要把Control2.ascx分在Result.aspx的前一组。这样就会产生有时可以编译通过(刚好分对组了,上面的.compiled文件就是碰巧编译成功时的样子)有时出错的奇怪问题。解决方案也不难,就是在Result.aspx页面注册一下Control2控件:
<% @ Register TagPrefix = " uc1 "  TagName = " Control2 "  Src = " controls\Control2.ascx "   %>
即使aspx页面里没有直接引用该控件也要加这一行,让编译器知道该页面引用了控件。而文件依赖关系和.compiled文件正是使用了这个信息,编译器根本不看.cs文件里的引用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值