ASPNet_Compiler的編譯過程

銀河使者發表於2008-05-01
最近手頭的一個ASP.Net的專案不時會出現編譯錯誤,提示某個控制元件ascx類不存在,但該控制元件明明就在同一個網站下。錯誤有時候會突然出現,而一旦出現錯誤再多次編譯也無法消除。由於公司使用指令碼編譯,所以就用ProcExp看了一下到底編譯時執行了什麼:
aspnet_compiler.exe -d -v / -p

主要就是這一條命令。難道是編譯器有bug?再細究發現aspnet_compiler.exe又呼叫了csc.exe(C#編譯器):
"C:WINDOWSMicrosoft.NETFrameworkv2.0.50727csc.exe" /noconfig /fullpaths @"C:WINDOWSMicrosoft.NETFrameworkv2.0.50727Temporary ASP.NET Files
oot1c85b622f7798d18mz_xtoba.cmdline"

到Temporary ASP.NET Files
oot1c85b622f7798d18目錄下檢視,發現很多.cmdline, .err, .out, .compiled等檔案,還有很多.cs檔案!原來那些網頁或AppCode下的.cs檔案在這裡被重組並分組了:App_Code.n.cs; App_Web_.n.cs; (n=0~...)。如果網頁比較多的話,就會有多組App_Web_.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裡發現了該檔案依賴於哪些檔案的資訊:


   
        
        
        
        
   



於是猜想編譯器就是在記憶體中維護用這樣的依賴關係,並可以產生一個樹來決定檔案分組先後。但.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控制元件:

即使aspx頁面裡沒有直接引用該控制元件也要加這一行,讓編譯器知道該頁面引用了控制元件。而檔案依賴關係和.compiled檔案正是使用了這個資訊,編譯器根本不看.cs檔案裡的引用。

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12921506/viewspace-259936/,如需轉載,請註明出處,否則將追究法律責任。

<source>

相關文章