假如这个世界上只剩下你一个人,当你正坐在屋子里的时候,这时突然响起了敲门声...

ASPNet_Compiler的编译过程

上一篇 / 下一篇  2008-05-01 17:59:05

查看( 62 ) / 评论( 2 )
最近手头的一个ASP.Net的项目不时会出现编译错误,提示某个控件ascx类不存在,但该控件明明就在同一个网站下。错误有时候会突然出现,而一旦出现错误再多次编译也无法消除。由于公司使用脚本编译,所以就用ProcExp看了一下到底编译时执行了什么:ITPUB个人空间+KH#[9G*aAZ'lX8G#{
aspnet_compiler.exe -d -v / -p <source webroot> <target webroot>ITPUB个人空间1]!h.ZR{| ](B

&q4E4K:} ?9~5Ni K0 主要就是这一条命令。难道是编译器有bug?再细究发现aspnet_compiler.exe又调用了csc.exe(C#编译器):ITPUB个人空间R[e6Y8E9V%d(w%g9a
"C:WINDOWSMicrosoft.NETFrameworkv2.0.50727csc.exe" /noconfig /fullpaths @"C:WINDOWSMicrosoft.NETFrameworkv2.0.50727Temporary ASP.NET Files
z/x3^3nT"C`/P$A0 oot1c85b622f7798d18mz_xtoba.cmdline"
+WTlP g3S:A0 ITPUB个人空间N8P`}C }
到Temporary ASP.NET FilesITPUB个人空间pc q'|]hZ qqk
oot1c85b622f7798d18目录下查看,发现很多.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里):ITPUB个人空间HpN)p7A xRm.|6r*Z
/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)ITPUB个人空间t+UKQ4T2H4Kh a
ITPUB个人空间,q3w ko^2k[:y u
但怎么决定文件的分组呢,哪些文件要放在前面的组,哪里文件要放在后面?我们在.aspx.xxx.compiled或.ascx.xxx.compiled里发现了该文件依赖于哪些文件的信息:ITPUB个人空间t}t0_;{g/KU
<?xml version="1.0" encoding="utf-8"?>ITPUB个人空间7UW!YAeJ x7|)}B I8o
<preserve resultType="3" virtualPath="/Result.aspx" hash="84d987223" filehash="a23fecda9fe4d6d8" flags="110000" assembly="App_Web_wt3qqawy" type="ASP.result_aspx">ITPUB个人空间O(Pu%hDMy t
    <filedeps>
@S8X!c$X0         <filedep name="/controls/Control1.ascx" />
L9_`G R E;P s0         <filedep name="/controls/Control1.ascx.cs" />
'o W"nqAA!I0         <filedep name="/Result.aspx" />
;F(Ur,^&\1Rh0         <filedep name="/Result.aspx.cs" />ITPUB个人空间$h0[;cR`
    </filedeps>ITPUB个人空间 B KIs2~0ha
</preserve>ITPUB个人空间_/eh#o3o

P*G*hq)Dg0 于是猜想编译器就是在内存中维护用这样的依赖关系,并可以产生一个树来决定文件分组先后。但.compiled文件只在编译成功那个页面后才会生成。
n;R-C WZg9V c0 明白了这些,再来找项目的问题:原来Result.aspx.cs里动态创建了Control2:ITPUB个人空间emylC-@(Ua|"L4h
Control2 ctrl = (Control2)page.LoadControl("controls\Control2.ascx");ITPUB个人空间.Y q(N,Em&k;tkvx
page.PlaceHolder.Controls.Add(ctrl);
#yujB)nM k-Y;[W6P0 但在.compiled文件里看不到有这样的依赖关系!所以编译器不知道要把Control2.ascx分在Result.aspx的前一组。这样就会产生有时可以编译通过(刚好分对组了,上面的.compiled文件就是碰巧编译成功时的样子)有时出错的奇怪问题。解决方案也不难,就是在 Result.aspx页面注册一下Control2控件:
-_ n,||(\5Kc GA0 <%@ Register TagPrefix="uc1" TagName="Control2" Src="controlsControl2.ascx" %>ITPUB个人空间:j w!y Y/U)g
即使aspx页面里没有直接引用该控件也要加这一行,让编译器知道该页面引用了控件。而文件依赖关系和.compiled文件正是使用了这个信息,编译器根本不看.cs文件里的引用。

TAG:

cnhzlt的个人空间 cnhzlt 发布于2008-05-01 20:31:24
看看
记录:Rocky月影 rockwl2001 发布于2008-05-07 04:09:09
不错的帖子~
我来说两句

(可选)

日历

« 2008-10-11  
   1234
567891011
12131415161718
19202122232425
262728293031 

数据统计

  • 访问量: 12302
  • 日志数: 119
  • 建立时间: 2008-02-08
  • 更新时间: 2008-10-01

RSS订阅

Open Toolbar