ASPNet_Compiler的编译过程

http://www.cnblogs.com/wonderow/archive/2008/05/01/1178294.html
最近手头的一个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文件里的引用。
========

关于ASP.NET预编译

http://www.cnblogs.com/dudu/archive/2011/02/07/aspnet_compiler_precompilation.html
为什么要用预编译?

博客园博客程序中.aspx和.ascx文件总共加起来有3000多个(博客模板中有大量的.ascx文件)。如果使用动态编译,每次只要更新bin文件夹中的任何一个dll文件,动态编译至少需要5分钟(访问量越高,所需的编译时间越长),而在动态编译期间网站访问速度极慢,几乎就是无法正常访问。这样,每次更新程序成为了一种痛苦,只能安排在深夜或一大早。

面对这样的情况,只能选择预编译。
预编译的原理是什么?
请阅读Artech写的深入剖析ASP.NET的编译原理之二:预编译(Precompilation)。
如何进行预编译?
用aspnet_compiler命令,命令示例:

aspnet_compiler -v \ -p G:\SourceWebSite G:\TargetWebsite -fixednames

参数说明:
-v \  要编译的虚拟路径,这里表示根路径。
-p G:\SourceWebSite 要编译的源Web项目所在文件夹。
G:\TargetWebsite 编译目标文件夹。
-fixednames 每个.aspx与.ascx文件都编译生成单独的dll文件,并使用固定文件名。

编译情况分析
1. 源文件夹中的所有.aspx, .ascx及App_Code中的.cs文件都会被编译。

2. 编译中遇到任何一个错误,会立即停止编译,并清空目标文件夹中已生成的文件;解决了引起编译错误的问题后,只能从头重新进行编译。出现编译警告,只提示,不影响正常编译。

3. 编译完成后,aspnet_compiler会将.aspx, .ascx, .cs之外的所有文件原封不动地复制至目标文件。(如果编译只是为了更新网站程序,这个操作显得多余。aspnet_compiler没有提供取消这个操作的参数)

4. 3000多个.aspx,.ascx文件,使用-fixednames编译,耗时30分钟左右;不使用-fixednames编译,只要6分钟。-fixednames编译本来是为了更新方便(每次编译生成的文件名相同,更新生产环境中的dll时直接覆盖就行),没想到这么慢。不用-fixednames编译,每次更新时,要先删除原来的文件,再复制。在生产环境中,这个操作会短暂影响网站的正常访问。

5. 预编译不会生成任何.ascx文件,也就是编译目标文件夹中没有任何.ascx文件。如果存在通过System.IO.File.Exists判断.ascx文件是否存在的代码,将不能按正常逻辑执行。解决方法是将.ascx文件复制到目标文件夹。

为什么不用“可更新的预编译(Updatable Pre-compilation)”

Updatable Pre-compilation只编译App_Code中的文件以及.aspx,.ascx的code behind文件,我们的Web项目类型是Web Application,code behind已经编译了,App_Code中也没有代码,相当于已经处于这种编译状态,但还是需要至少5分钟的动态编译时间。

这种编译方式只是减少了编译.cs文件的工作量,但每个.aspx,.ascx文件还是要动态编译,不能避免动态编译的性能问题。

Updatable Pre-compilation适用于App_Code中有大量代码(更新其中的文件会引起该文件夹中的所有文件重新编译),又不想用Non-updatable Pre-compilation的情况。

结论

面对这么多的.aspx,.ascx文件,只能选择预编译。-fixednames编译实在太慢,只能放弃。更新时只能先删除,再更新。虽然有些不足,但总比动态编译好。

当然,真正的解决之道是干掉模板中的那些.ascx文件。ASP.NET MVC会是救星吗?
========

用aspnet_compiler发布网站

http://www.educity.cn/develop/493536.html

  在 2.0模型中,vs2005已经完全脱离了编译而成为了一个彻底的ide.算是一个不小的改动。其中更是取消了有关Web Application的概念,使得习惯了vs2003的人刚开始的时候会有一些摸不着头脑。下面简单说一下我在使用过程中自己总结的,算是一点经验。

  新建web工程并且位置是文件系统的时候,vs2005只是帮你建好了一个sln文件,这个东西只是指引msbuild 如何进行编译的,过程是:ide 调用 msbuild ,msbuild解析sln文件,msbuild调用aspnet_compiler.exe进行网站的编译。所以aspnet_compiler.exe只是负责进行网站的编译的。

  预编译的概念在framework 1.1 里面就存在了,vs2003中的预编译指的是将页面对应的cs/vb文件与resx文件编译后统一集成到一个dll中放到bin目录下,将aspx文件直接拷贝过去。这样做会留下隐患,因为aspx文件就直接暴露在最后的发行包中,如果完全是codeb-behind模型还好,只能改改界面,如果采用了页面上的来生成页面,源代码就暴露了。针对这些问题,vs2005采用了一种新的模式。

  请参看ASP.NET 编译工具 (Aspnet_compiler.exe) 这篇文章了解对各种文件的处理方式。

  IDE发布:

  vs2005中选择 生成-〉发布网站,在对话框中的操作将映射到aspnet_compiler.exe的参数中,可更新的发布对应 -u,其他选项类似,请参考上面的文章了解。

  注意:发布时将忽略nfig中的debug?问骋簧晌薜魇孕畔⒌奈募?

  手工编译:

  简单说来,如果是无更新发布模式编译,appcode下面的class编译成dll放在bin下,页面内容清空位置不变作占位用,同时页面被编译成一个随机名称的dll,增加一个同piled文件到bin目录下,内容大概如下:

  <?xml version="1.0" encoding="utf-8"?>

  <preserve resultType="3" virtualPath="/Forum/AdminList.aspx" hash="6772609c3" filehash="49154463f1d6738c" flags="110000" assembly="App_Web_hmrycg3w" type="ASP.forum_adminlist_aspx">

  <filedeps>

  <filedep name="/Controls/footer.ascx" />

  <filedep name="/Controls/header.ascx" />

  <filedep name="/Forum/AdminList.aspx" />

  <filedep name="/Forum/AdminList.aspx.cs" />

  <filedep name="/Forum/menu.ascx" />

  <filedep name="/Forum/menu.ascx.cs" />

  </filedeps>

  </preserve>

  里面只是列出了页面上的customcontrol,这里已经完成了和masterfile的映射。这样最大限度的保护了页面的敏感信息,发布过的网站中只能看见一堆文件名了。可更新的发布模式与vs2003类似,页面就直接拷贝过来不予编译了。

  讲了一堆原理,下面说一下aspnet_compiler.exe的调用方法,这是我使用的例子

  我的开发目录是这样的

  Project/

  library/

  devroot/

  pubroot/

  proj.sln

  使用的命令如下:

  aspnet_compiler -v / -p .\devroot -f .\pubroot

  分析:

  -v / 指明了iis的虚拟目录

  -p .\devroot 表示代码实际位置

  .\pubroot 指明了要发布的位置

  -f 表示强制改写目标位置

  你还可以用-u来进行传统意义上的预编译,-d来插入编译符号。
========

使用aspnet_compiler.exe预编译网站

http://www.ixueyi.com/jingyan/103518.html

第一步:切换到aspnet_compiler.exe所在目录
在“命令提示符”下,切换到所在目录“c:\windows\microsoft\framework\v2.0.50727”。
第二步:运行aspnet_compiler.exe预编译
Aspnet_Compiler -v test c:\tmp\test
-v是虚拟目录参数,test为虚拟目录名称,而c:\tmp\test是指先行编译后的程序文件的目的位置。
第三步:使用预编译后的网站
将预编译后的test目录Copy到正式网页服务器,部署网站。
但要注意:aspnet_compiler.exe不会对静态文件如:Web.config、文本文件和图片文件等进行编译,所以像数据库连接字符串请用 aspnet_regiis.exe工具来进行加密。
网站预编译后,以后也不会触发重新动态编译,故请不要事后再加入新的.aspx文件,那样不会有任何作用。
也可通过ClientBuildManager类进行编译
string vdir = "/MyDataSource"; //虚拟目录名称
string srcLocation = "c:\\Inetpub\\wwwroot\\VS2005IDE"; //来源位置
string tarLocation = "c:\\tmp\\VS2005IDE"; //目标位置
System.Web.Compilation.ClientBuildManager cbm = new System.Web.Compilation.ClientBuildManager (vdir,srcLocation,tarLocation);
cbm.PrecompileApplication(); //预编译
========

ASPNet_Compiler学习总结相关推荐

  1. java入门 慕路径,Java入门基础知识总结学习教程大全【必看经典】

    类型的表达式,是循环条件,表达式3是党执行了一遍循环之后,修改控制循环的变量值. ??? for语句的执行过程是这样的:首先计算表达式1,完成必要的初始化工作:然后判断表达式2的值,如果表达式的值为t ...

  2. Java EE学习心得

    –Java EE学习心得   1.    称为编程专家的秘诀是: 思考-----编程--------思考------编程--.. 编程不能一步到位,不能一上来就编,必须先思考如何写,怎样写?然后再编程 ...

  3. FastAI 2019课程学习笔记 lesson 2:自行获取数据并创建分类器

    文章目录 数据获取 google_images_download 的安装和使用 挂载google 个人硬盘到Google colab中 删除不能打开文件 创建ImageDataBunch 训练模型 解 ...

  4. FastAI 课程学习笔记 lesson 1:宠物图片分类

    文章目录 代码解析 神奇的"%" 导入fastAI 库 下载解压数据集 untar_data 获取帮助文档 help() ? ?? doc 设置路径 get_image_files ...

  5. 深度学习学习指南-工具篇

    colab Colab是由Google提供的云计算服务,通过它可以让开发者很方便的使用google的免费资源(CPU.GPU.TPU)来训练自己的模型. 学习经验总结 如何使用命令行? 通过!+cmd ...

  6. Redis学习之路(一)--下载安装redis

    redis学习之路--下载安装redis windows安装redis 1.下载redis 2.安装 3.查看是否安装成功 windows安装redis 1.下载redis 网址:https://gi ...

  7. python内置库之学习configparser库(一)

    python内置库之学习configparser库(一) 1.引言 ini文件简介 [节] 键=值 注:节不能重复出现 2.自己封装了一个增删改查的类,可以参考一下 import configpars ...

  8. 前端Vue学习之路(二)-Vue-router路由

    Vue学习之路 (二) Vue-router(基础版) 一.增加静态路由 二.动态路由+路由嵌套+404页面 三. 编程式导航 四.命名路由 五.命名视图 六.重定向和起别名 1.重定向 2.起别名 ...

  9. 前端Vue学习之路(一)-初识Vue

    Vue学习之路 (一) 1.引言 2.更换npm国内镜像源 3.用npm下载Vue 4.Vue全家桶 5.使用命令创建项目 5.推荐插件 6.推荐网站 7.学习扩展 1.引言 先安装node.js环境 ...

最新文章

  1. 数字转换为字符的L受哪个参数影响
  2. 每日程序C语言47-找到年龄最大的人并输出
  3. Android闹钟 AlarmManager的使用
  4. 毕业了去哪里工作,一位毕业多年北漂人的经验感悟
  5. QML笔记-2种方式实现心脏跳动
  6. 富士康立讯精密可能仍在苹果汽车代工商候选名单中
  7. HoudahSpot 6.2 for Mac文件搜索软件
  8. Atitit.css 规范 bem 项目中 CSS 的组织和管理
  9. saas,pass介绍
  10. 互联网晚报 | 7月27日 星期三 | 微信安装包11年膨胀575倍;阿里申请香港纽约双重主要上市;苹果应用商店被曝大量色情应用...
  11. 简易cad导出pdf程序源码
  12. 增长研究:电子烟巨头JUUL未公开的增长启示
  13. 郑大计算机课程表,郑州大学研究生课程表.doc
  14. 【BZOJ5470】[FJOI2018]所罗门王的宝藏()
  15. 1.Twitter开发者之如何申请一个twitter开发者账号
  16. C# 判断圆与矩形的冲突
  17. 全球尺度的高分辨率遥感产品
  18. Leetcode 307.区域检索-数组可修改
  19. 微软官方给出无法安装WIN10更新的终极解决办法:覆盖安装
  20. Spark架构原理和生态系统

热门文章

  1. 在redhat9中交叉编译nano-X nxlib和fltk
  2. 151. 翻转字符串里的单词
  3. 软件设计原则——合成复用原则
  4. Create an Apex class that returns contacts based on incoming parameters
  5. javascript (function(){})()
  6. 百度网盘文件分享演示,如何查看已经分享的文件
  7. c#-----让richtextbox或者TextBox不可编辑
  8. opencv中的imread不支持中文路径的解决办法
  9. [YTU]_2911(我想放假)
  10. Pycharm安装PyQT5调用QTDesigner