<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss'><id>tag:blogger.com,1999:blog-6939442</id><updated>2009-11-21T10:41:21.271+08:00</updated><title type='text'>天天的家</title><subtitle type='html'>普通平凡的人，网管，编程，司机，生活中的各种角色</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><link rel='next' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default?start-index=26&amp;max-results=25'/><author><name>天天</name><email>noreply@blogger.com</email></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>103</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6939442.post-7762514909722376462</id><published>2009-02-05T14:59:00.001+08:00</published><updated>2009-02-05T14:59:43.902+08:00</updated><title type='text'>改写FULL OUTER JOIN(转)</title><content type='html'>说起数据库的表JOIN，一直是SQL语句开发中最为关注的重点，特别是在OLAP的DW领域。&lt;br /&gt;关注JOIN主要关注JOIN的性能，一般来说数据库都会支持为不同场合不同的代价实现MERGE、HASH以及NESTED-LOOP等JOIN的实现方式。这个非常重要，但这个不是本文主题，以后我想好好的阐述这方面的内在以及优化，不过可能需要根据数据库的不同而分开描述，在此不必熬述。&lt;br /&gt;今天要想说的是JOIN的类型。根据需求，一般来说JOIN有如下几种：&lt;br /&gt;INNER JOIN、&lt;br /&gt;LEFT OUTER JOIN、&lt;br /&gt;RIGHT OUTER JOIN、&lt;br /&gt;FULL OUTER JOIN、&lt;br /&gt;CROSS JOIN。&lt;br /&gt;首先第一种直译为内关联，需要匹配条件完全匹配，这个是最普通的关联，一般来说用的都是这个。对于优化来说，基本上是无法改写的。&lt;br /&gt;第二是做文字直译为左外关联，一般也会说是左关联，如果是常用ORALCE的同志，你们看到的A.COLUMN1= B.COLUMN2(+)描述的就是左关联，当然这个不是标准SQL，是ORACLE PL/SQL自己的语法。它的含义是以左表为主表，匹配条件当右表没有匹配值时会以数据库的NULL值代替，这个实现的功能为主从表的关联。当两表之间存在外键约束但非主键约束时（亦即非强制依赖约束）时，应采用这种关联方式。&lt;br /&gt;第三种直译当然是右关联，说白了，就是右表为主表，其他和左关联同，他的存在和左关联是同一价值，在非必须的情况，右关联尽量用左关联替代。因为右关联会让你的SQL读起来很难受，我们接受的先入为主，先左后右的表达方式，而且很多数据库对复杂关联时，据说对右关联的优化能力较差。&lt;br /&gt;第四种直译为全关联。就是左右两表都是主表，非主从关系，这个时候匹配条件中存在左表有右表无，也同时存在右表有左表无的情况。这个时候你需要进行的就是全关联了。当然这个性能是比较差的，但当我们的需求的确如此的时候，我们也是必须去面对，本文想说的就是替代这种全关联的一种脚本改写，这种写法会对性能上有一定提升，当然是在某些情况和场合下。&lt;br /&gt;第五种是交叉关联，也就是所谓的笛卡尔积。当你的关联不写条件就会出现这种情况，比如你要画方格呵呵，通过横、纵左表描述整个围棋棋盘的时候，你得到的数据行是你的左右两表行数的乘积。当然这种情况一般情况是不需要的，因为关联不用条件基本上意义不大，而且这种是比较恐怖，积数的数据扩充，一般你会受不了的，你受得了你的机器也受不了，当你发现你一个应该可以很快完成关联却怎么也出不来的时候，你要检查你的匹配条件是不是没有写或者错了产生笛卡尔积了。经常有人写条件A.COLUMN1 = A.COLUMN1来作A、B两表的关联条件，这个条件是无效的，是CROSS JOIN。值得注意哦，这种脚本如果出现了，要判编码者死刑的呵呵。&lt;br /&gt;引申了不少，进入主题，来说改写FULL OUTER JOIN。首先我要申明的是我的改写是基于两表或者多表数据量差不多情况下，且为统计所用时，而且表越多，越能显示这种改写的优势。针对不同等量级的表之间的FULL OUTER JOIN，使用这种方式可能会让你的SQL变得晦涩而且性能没有得到很大提高，那就不值得了。&lt;br /&gt;我使用的SQL为“UNION ALL + GROUP BY”的组合。如果我把这个SQL称之为精妙的时候，请同志们不要笑话我的自我满足呵呵。&lt;br /&gt;我们来举例说明，在OLAP系统中，做报表经常会出现这样的一组需要你完成的指标：本期指标、上期指标、去年同期指标。我们今天就来用此例来说明，说明这一改写的精妙。&lt;br /&gt;一般来说，我们会已经形成了如下列明细表格，表一：&lt;br /&gt;月份        分公司        商品        销售额&lt;br /&gt;200504        南京分公司        IBM笔记本        1,002,000&lt;br /&gt;200504        合肥分公司        IBM笔记本        888,887&lt;br /&gt;200504        南京分公司        HP笔记本        1,399,250&lt;br /&gt;200504        合肥分公司        HP笔记本        1,010,222&lt;br /&gt;……        ……        ……        ……&lt;br /&gt;……        ……        ……        ……&lt;br /&gt;200606        南京分公司        DELL笔记本        1,999,250&lt;br /&gt;200606        合肥分公司        DELL笔记本        2,010,222&lt;br /&gt;但我们最终想要的表格如下的表二：&lt;br /&gt;制表月份：200606&lt;br /&gt;分公司        商品        销售额&lt;br /&gt;                本月        上月        上年同期&lt;br /&gt;南京分公司        IBM笔记本                      &lt;br /&gt;南京分公司        HP笔记本                      &lt;br /&gt;南京分公司        DELL笔记本                      &lt;br /&gt;……        ……        ……        ……        ……&lt;br /&gt;合肥分公司        神州笔记本                      &lt;br /&gt;可能在想，很简单啊，把表一中的数据跟月份条件分成三个子查询或者导出表（当月指标表、上月指标表、上年同期指标表），然后来进行一次关联就好了啊。&lt;br /&gt;对，这个想法，完全正确。重要的是你选择什么样的关联方式呢？&lt;br /&gt;当然先说一下关联条件，当时每个表的【分公司】以及【商品】了。&lt;br /&gt;内关联，可能会对，但大部分情况是不对的，比如〖南京分公司〗这个月份销售了〖IBM笔记本〗，但也可能去年这个时候没有销售该笔记本呢，那内关联就会损失〖南京分公司〗销售〖IBM笔记本〗的信息，因为你是内关联，需要完全匹配。&lt;br /&gt;那简单选择外关联吧，左关联或者有关联，那问题又来了，到底选择那个表为主表呢？今年某个公司销售了某个产品，可能去年同期没有销售，今年没有销售某个产品，可能去年又销售了。无法确定主表，外关联也不能满足需求。&lt;br /&gt;当然交叉关联更加是不可以选择，那就只能选择全关联了。一般来说，这种需求即需要进行全关联，但两个表关联会简单，三个表呢？三个表你必须先将两个表关联后生成导出表或者子查询再和第三个表关联，否则你的关联条件可能又会让你的数据不满足你的需求，这个时候你在想？怎么会呢？我这样写：&lt;br /&gt;FROM 当月指标表 A&lt;br /&gt;FULL OUTER JOIN 上月指标表 B&lt;br /&gt;ON B.分公司 = A.分公司　AND B.商品 =  A.商品&lt;br /&gt;FULL OUTER JOIN 上年同期指标表C&lt;br /&gt;ON C.分公司 = A.分公司　AND C.商品 =  A.商品&lt;br /&gt;细看了，这个结果是是B和A外关联，C和A外关联。所以如果有组条件（比如〖上海分公司〗＋〖联想笔记本〗）A表没有，而B表和C表都有，这样的结果是是什么呢？会出现这组条件会有两条记录，第一条：A表指标空、B表指标有、C表指标空，第二条：A表指标空、B表指标空、C表指标有。显然这个也不是我们需要的结果，我们要的结果应该是：A表指标空、B表指标有、C表指标有。所以你如果需要使用全关联，你需要做的事情是要先将两表做全关联然后作为子查询或者导出表再和另外一个表关联。这是三个表的情况，当你要做N个表关联的时候，你就要作N－1个子查询，做N－1次全关联。&lt;br /&gt;听起来就能了解这个效率很有问题。也是麻烦至极的。&lt;br /&gt;所以遇到这个情况，我们不能这么去干，那是莽夫所为，也是愚公所为。愚公精神值得赞扬，但还是需要智叟来解决问题的。现在看智叟的。&lt;br /&gt;从上面的尝试的过程中我们来分析，我们对于三个表，如果是两两关联出来的结果出现场重复记录，如上所属的〖上海分公司〗＋〖联想笔记本〗。这个时候你会想，将结果GROUP BY一下不就可以得到正确的结果了吗？答对了，完全正确，对最终结果做一次GROUP BY绝对可以将重复记录合并。这样当然能解决刚才的问题。&lt;br /&gt;也显然，你会发现当出现这种情况后，GROUP BY基本上再所难免了，当然GROUP BY也是个耗时耗力的操作。那我在想，是否可以不需要前面的FULL OUTER JOIN。而直接GROUP BY呢？答案是显然的，是可以的。这个就是我改写FULL OUTER JOIN的方案：UNION ALL + GROUP BY。&lt;br /&gt;我的做法是将三个导出表的数据项进行扩充成最后需要的表结构，对于未有的只采取默认为0（当然现在说的是数据统计，0可以解决问题，对于其他可以采取其他特殊默认值进行替代，比如空等）。就上理来说，对于本期导出表来说，上期指标填０，上年同期指标也填0；针对上期的导出表，将销售指标赋值给上期指标，本期指标以及上年同期指标均为0；同样去年同期导出表的本期和上期为0，将销售指标赋值给上年同期指标。通过如下格式的SQL即可完成。&lt;br /&gt;SELECT 分公司, 商品, 指标 AS 本期指标, 0 AS 上期指标, 0 AS　上年同期指标&lt;br /&gt;FROM 销售指标表　WHERE 月份＝本期月份；&lt;br /&gt;SELECT 分公司, 商品, 0 AS 本期指标, 指标 AS 上期指标, 0 AS　上年同期指标&lt;br /&gt;FROM 销售指标表　WHERE 月份＝上期月份；&lt;br /&gt;SELECT 分公司, 商品, 0 AS 本期指标, 0 AS 上期指标,  AS　上年同期指标&lt;br /&gt;FROM 销售指标表　WHERE 月份＝本期月份。&lt;br /&gt;现在大家看出来我要干什么了吧？然后将这三个子查询UNION ALL起来合并成一个大的数据集，然后在根据【分公司】、【商品】进行GROUP BY，对其他指标进行SUM即可搞定了。&lt;br /&gt;最终的SQL是：&lt;br /&gt;SELECT 分公司, 商品, SUM(本期指标), SUM(上期指标), SUM(上年同期指标)&lt;br /&gt;FROM&lt;br /&gt;(&lt;br /&gt;SELECT 分公司, 商品, 指标 AS 本期指标, 0 AS 上期指标, 0 AS上年同期指标&lt;br /&gt;FROM 销售指标表　WHERE 月份＝本期月份&lt;br /&gt;UNION ALL&lt;br /&gt;SELECT 分公司, 商品, 0 AS 本期指标, 指标 AS 上期指标, 0 AS上年同期指标&lt;br /&gt;FROM 销售指标表　WHERE 月份＝上期月份&lt;br /&gt;UNION ALL&lt;br /&gt;SELECT 分公司, 商品, 0 AS 本期指标, 0 AS 上期指标, 指标 AS上年同期指标&lt;br /&gt;FROM 销售指标表　WHERE 月份＝本期月份&lt;br /&gt;)&lt;br /&gt;GROUP BY 分公司, 商品&lt;br /&gt;搞定，经典的精妙的SQL出现了，赶快去做个例子去尝试一下吧，你会感觉到精妙的。&lt;br /&gt;这样解决了丢失数据的问题，也解决了重复记录的问题。&lt;br /&gt;效率的问题也解决了，因为所有的操作就GROUP BY是个比较耗时耗力的操作，没有了关联，UNION ALL只是将记录合并，速度很快，而且UNION ALL各部分是互相不干扰的，在多处理器可并行处理的数据库系统中，UNION ALL一般都会被优化为并行处理，即各个部分并行查询将结果集合并而已。所以效率绝对大幅提高。&lt;br /&gt;还有，这样的SQL很好扩种，而且结构清晰，将来对更多的表以及更多的信息扩充起来都要清晰、简单以及明朗的多。&lt;br /&gt;当然我也提过，这种情况针对各个子查询的数据量相当的时候会是非常有效的。至于他的有效性，它的可推广的范围，你可能怀疑，这里只解决了指标计算的问题，通过SUM实现了。你想啊，分组函数还有很多啊，比如MAX、MIN、AVG、COUNT等，这些都可以解决很多问题的，在结合分组GROUP BY可以使用OLAP函数的PARITION BY代替，实际上这个组合可以解决很多关联的问题，针对关联的优化，这种改造不妨是个优秀的选择。结合实际的需求情况，你们可以发现他可以解决很多很多的关联问题。&lt;br /&gt;除了这种统计表格之外，我曾在数据仓库中通过这个SQL组合实现了慢速变化存储（注、慢速变化即为将仓库中按时间存储的数据根据全集连续且无交叉的有效时间短来存储）的批量处理。所以，SQL精妙无穷，本文抛砖引玉，有待大家共同发掘。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-7762514909722376462?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/7762514909722376462/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=7762514909722376462' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/7762514909722376462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/7762514909722376462'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2009/02/full-outer-join.html' title='改写FULL OUTER JOIN(转)'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-4612504400554074181</id><published>2008-10-17T20:52:00.001+08:00</published><updated>2008-10-17T20:52:47.166+08:00</updated><title type='text'>单机环境下vmware与本机操作系统共享adsl网络设置</title><content type='html'>单机环境，ADSL拨号上网，安装VMware后，客户机如何与宿主机共享上网？朋友老问这个问题，其实已经不是什么新问题了。为了方便大家还有新手，今天有功夫就写下来，希望方便大家参考。为了具有针对性，我就拿自己的机器做为参照对象。&lt;p&gt;Product：VMware WorkStation(英文版)&lt;br&gt;Version：6.0.0 build-45731&lt;br&gt;硬件配置：三星Q70-AV01笔记本、Intel Core2 Duo(Merom) T7300(2.0G)、DDR2 &lt;br&gt;667(2G)&lt;br&gt;宿主机系统：Microsoft Windows XP Professional Service Pack 2 (原版)&lt;br&gt;客户机系统：Fedora 7 Linux&lt;br&gt;上网方式：北京网通ADSL(512K)、无路由器、Modem也无路由功能。利用XP自带的PPPoE宽带拨号软件新建名为&amp;quot;ADSL&amp;quot;的连接拨号上网。&lt;p&gt;网络适配器及其配置：&lt;br&gt;VMware Network Adapter VMnet8:&lt;br&gt;IP Address. . . . . . . . . . . . : &lt;a href="http://192.168.168.1"&gt;192.168.168.1&lt;/a&gt;&lt;br&gt;Subnet Mask . . . . . . . . . . . : &lt;a href="http://255.255.255.0"&gt;255.255.255.0&lt;/a&gt;&lt;p&gt;VMware Network Adapter VMnet1:&lt;br&gt;IP Address. . . . . . . . . . . . : &lt;a href="http://192.168.58.1"&gt;192.168.58.1&lt;/a&gt;&lt;br&gt;Subnet Mask . . . . . . . . . . . : &lt;a href="http://255.255.255.0"&gt;255.255.255.0&lt;/a&gt;&lt;p&gt;本地连接(物理网卡)：(自动获取IP地址和DNS)&lt;br&gt;ADSL(PPPoE) ：(由XP新建网络连接向导获得)&lt;p&gt;以下仅介绍Bridged和NAT两种共享上网方式：&lt;br&gt;准备工作(必须)：为客户机Fedora 7 Linux系统安装VMware Tools&lt;p&gt;一、Bridged方式共享上网&lt;p&gt;1、关闭管理工具--服务中的VMware DHCP Service和VMware NAT Service两个服务&lt;br&gt;2、先断开ADSL连接，控制面板--网络连接--ADSL属性--高级-勾选&amp;quot;Internet连接共享&amp;quot;，下拉列表中然后选择&amp;quot;本地连接&amp;quot;。确定，不 要管提示。系统会自动把&amp;quot;本地连接&amp;quot;设置为 &lt;br&gt;&lt;a href="http://192.168.0.1"&gt;192.168.0.1&lt;/a&gt;,子网掩码设置为&lt;a href="http://255.255.255.0"&gt;255.255.255.0&lt;/a&gt;. 以后&lt;a href="http://192.168.0.1"&gt;192.168.0.1&lt;/a&gt;这个IP地址就是Fedora &lt;br&gt;7 Linu的默认网关地址和DNS地址了。&lt;br&gt;3、连接ADSL并拨号，启动Fedora 7 Linux，设置IP和DNS&lt;br&gt;IP设置为192.168.0.X （X就是2到254之间的数都可以）&lt;br&gt;子网掩码&lt;a href="http://255.255.255.0"&gt;255.255.255.0&lt;/a&gt;&lt;br&gt;网关192.268.0.1&lt;br&gt;DNS：192.168.0，1&lt;br&gt;之后重启Fedora 7 Linu或重新激活网络就可以上网了(注意：Linux网络必须激活才能使用，好多人改了配置都不激活，肯定上不了网，时刻检查一下网络是否处于激活状态，而且必须设置为计算机启动时候就激活设备)&lt;p&gt;二、NAT方式共享上网&lt;p&gt;1、开启管理工具--服务中的VMware DHCP Service和VMware NAT Service两个服务&lt;br&gt;2、取消ADSL连接的Internet连接共享。&lt;br&gt;3、连接ADSL并拨号，启动Fedora 7 Linux，设置IP和DNS&lt;br&gt;IP设置为192.168.58.X （X就是128到254之间的数都可以）&lt;br&gt;子网掩码&lt;a href="http://255.255.255.0"&gt;255.255.255.0&lt;/a&gt;&lt;br&gt;网关192.268.58.2&lt;br&gt;DNS：&lt;a href="http://192.168.58.2"&gt;192.168.58.2&lt;/a&gt;&lt;br&gt;之后重启Fedora 7 Linu或重新激活网络就可以上网了.&lt;p&gt;提示：或者更简单的办法就是，开启管理工具--服务中的VMware DHCP Service和VMware &lt;br&gt;NAT Service两个服务后，直接把客户机中的网络设置为DHCP获取IP方式，即可上网&lt;br&gt;这里需要注意的是VMware对于VMnet8采用如下规则(就以本机的&lt;a href="http://192.168.58.0"&gt;192.168.58.0&lt;/a&gt;网段为例)： &lt;p&gt;&lt;br&gt;第一个地址(&lt;a href="http://192.168.58.1"&gt;192.168.58.1&lt;/a&gt;):静态地址，分配给了宿主机Xp的VMware Network Adapter &lt;br&gt;VMnet8适配器使用。&lt;br&gt;第二个地址(&lt;a href="http://192.168.58.2"&gt;192.168.58.2&lt;/a&gt;):静态地址，分配给了NAT设备使用。&lt;br&gt;(&lt;a href="http://192.168.58.3"&gt;192.168.58.3&lt;/a&gt;到&lt;a href="http://192.168.58.127"&gt;192.168.58.127&lt;/a&gt;)静态地址，保留。&lt;br&gt;(&lt;a href="http://192.168.58.128"&gt;192.168.58.128&lt;/a&gt;到&lt;a href="http://192.168.58.254"&gt;192.168.58.254&lt;/a&gt;)：DHCP作用域地址范围，分配给虚拟机使用。&lt;br&gt;最后一个地址(&lt;a href="http://192.168.58.255"&gt;192.168.58.255&lt;/a&gt;)广播地址。&lt;br&gt;VMware默认安装后的规则都是如此。&lt;p&gt;单机ADSL拨号环境，不是路由器或是局域网环境，ADSL的Internet连接共享这步是选择Bridged方式共享上网的关键&lt;p&gt;如果你还想宿主机和客户机之间能相互Ping通和共享，就先把&amp;quot;文件和打印机共享&amp;quot;添加到Windows防火墙例外，然后把管理工具--服务中的Server、Computer Browser、两个服务打开。&lt;p&gt;关于GuestOS共享主机文件&lt;br&gt;选择你的Guest OS&lt;br&gt;点击Edit virtual machine settings---&amp;gt;Options--&amp;gt;Shared Folders&lt;p&gt;选择Always enables,然后点 Add 选择你要共享的主机磁盘或文件夹&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-4612504400554074181?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/4612504400554074181/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=4612504400554074181' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/4612504400554074181'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/4612504400554074181'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/10/vmwareadsl.html' title='单机环境下vmware与本机操作系统共享adsl网络设置'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-7750992736262602091</id><published>2008-10-17T14:35:00.001+08:00</published><updated>2008-10-17T14:35:29.073+08:00</updated><title type='text'>FreeBSD下USB打印机的安装经验谈</title><content type='html'>使用的是HP DeskJet 3420，所以我只能说安装这台打印机的经验了。供你们参考吧！&lt;br&gt;1、编译内核&lt;br&gt;在安装打印机前先检查内核看看内核中是否支持USB端口。&lt;br&gt;如果没有就加入如下：&lt;br&gt;#USB Stuff&lt;br&gt;device usb&lt;br&gt;device uhci&lt;br&gt;device ulpt&lt;br&gt;如果你无法确认是uhci还是ohci你可以使用dmesg命令查看：&lt;br&gt;#dmesg | less&lt;br&gt;或者直接输入下面：&lt;br&gt;#dmesg | grep uhub&lt;p&gt;2、编辑rc.conf&lt;p&gt;内核编译结束后编辑/etc/rc.conf，&lt;br&gt;添加如下内容： usbd_enable=&amp;quot;YES&amp;quot;&lt;p&gt;3、重新启动计算机，以启用新内核。&lt;p&gt; 4、查验设备节点&lt;p&gt;这时你到 /dev下看看是否存在ulpt0这个文件，&lt;br&gt;如果没有就需要用如下方式创建他：&lt;br&gt;#cd /dev #/dev/MAKEDEV ulpt0&lt;p&gt;5、安装打印机软件和驱动。&lt;br&gt;我安装了如下软件：&lt;br&gt;/usr/ports/print/Ghostscript-gnu&lt;br&gt;/usr/ports/print/hpijs&lt;br&gt;/usr/ports/print/apsfilter&lt;br&gt;/usr/ports/print/cups&lt;br&gt;/usr/ports/print/foomatic-db&lt;br&gt;下面的这个我没装： /usr/ports/print/foomatic-db-engine&lt;br&gt;但我还是建议你在安装cups之前安装上他们。&lt;br&gt;我直接下载了foomatic-rip和foomatic-gswrapper到/usr/local/bin目录(你也可以到&lt;a href="http://www.Linuxprinting.org"&gt;http://www.Linuxprinting.org&lt;/a&gt;上下载 foomatic-filters的packages到本地进行安装)： #cd /usr/local/bin #fetch &lt;br&gt;&lt;a href="http://www.linuxprinting.org/foomatic-rip#fetch"&gt;http://www.linuxprinting.org/foomatic-rip&lt;br&gt;#fetch&lt;/a&gt; &lt;a href="http://www.linuxprinting/foomatic-gswrapper"&gt;http://www.linuxprinting/foomatic-gswrapper&lt;/a&gt;&lt;br&gt;然后运行如下命令：&lt;br&gt; #chmod 755 foomatic-rip foomatic-gswrapper&lt;br&gt;#ln -s /usr/local/bin/foomatic-rip &lt;br&gt;/usr/local/libexec/cups/filter/foomatic-rip&lt;br&gt; 好了该准备我的打印机驱动了，&lt;br&gt;我的打印机是HP Deskjet 3420。驱动可以在如下网址搜索到(这里有很多品牌打印机驱动的哦！)：&lt;br&gt;&lt;a href="http://www.linuxprinting.org/printer_list.cgi"&gt;http://www.linuxprinting.org/printer_list.cgi&lt;/a&gt; 驱动是PPD文件，&lt;br&gt;将PPD文件下载到/usr/local/share/cups/model，&lt;br&gt;然后对其设置权限：&lt;br&gt;chown root:wheel HP-DeskJet_3420-hpijs.ppd&lt;br&gt;chmod 644 HP-DeskJet_3420-hpijs.ppd&lt;p&gt;6、准备工作结束，&lt;p&gt;现在开始配置打印机。 打开浏览器在地址栏输入：&lt;br&gt;&lt;a href="http://localhost:631"&gt;http://localhost:631&lt;/a&gt;&lt;br&gt;或者 &lt;a href="http://localhost:631/admin"&gt;http://localhost:631/admin&lt;/a&gt;&lt;br&gt; 如果你是用的前者进入，那么你进入页面中的如下链接&amp;quot;Do Administration &lt;br&gt; Tasks&amp;quot;，这时你需要输入管理员名称(User Name)和密码(PassWord)。如果你用后者进入则会直接要求输入管理员名称(User Name)和密码(Password)。&lt;br&gt;我的：&lt;a href="http://127.0.0.1:631"&gt;http://127.0.0.1:631&lt;/a&gt; 或者 &lt;a href="http://127.0.0.1:631/admin"&gt;http://127.0.0.1:631/admin&lt;/a&gt;&lt;br&gt;我用的后者。管理员名称(User Name)用你机器的超级管理员root ，密码(Password)当然就是root的密码了！&lt;br&gt;第一次使用CUPS当然要点击 Add Printer 了。&lt;br&gt;之后出现一个表单，表单的含义如下(以我的HP Deskjet 3420为例)：&lt;br&gt; Name:3420 (你喜欢怎么叫你的打印机呢？)&lt;br&gt;Location:Local printer (就这么填就行了！)&lt;br&gt;Description:hp DeskJet3420 (描述一下你的打印机)&lt;br&gt;然后点Continue按钮，现在的这个界面是打印机联接端口的选择。&lt;br&gt;我的选择的是： USB Printer #1&lt;br&gt;然后点Continue按钮，现在的这个界面是选择打印机厂商的界面，&lt;br&gt;我的当然选择：HP了。&lt;br&gt;然后点Continue按钮，好了仔细寻找和你打印机匹配的驱动吧。&lt;br&gt;我选择HP DeskJet 3420 Foomatic/hpijs (recommended) (en)。&lt;br&gt;然后点Continue按钮结束配置。&lt;p&gt;7、启动CUPS 先su到超级管理员，&lt;br&gt;之后执行如下操作：&lt;br&gt;#/usr/local/etc/rc.d/cups.sh start OK，&lt;br&gt;现在你用如下命令测试一下：&lt;br&gt;#lp &amp;lt;文件名(可以自己编辑一个小文本文件)&amp;gt;&lt;p&gt; 8、OpenOffice的打印机配置&lt;p&gt;使用如下命令： $openoffice-1.1-spadmin&lt;br&gt;在弹出窗口中点击&amp;quot;新增打印机&amp;quot;。&lt;br&gt;在新窗口中选中&amp;quot;配置一个打印机&amp;quot;。&lt;br&gt;点击&amp;quot;继续&amp;quot;后在新窗口中看看已有的驱动中是不是有和你打印机匹配的。&lt;br&gt; 如果有就选中然后点击继续。如果没有，点击&amp;quot;输入&amp;quot;按钮。&lt;br&gt;在新弹出的窗口中在如下目录中搜寻打印机驱动：&lt;br&gt;/usr/local/etc/cups/ppd/ 应该找到了吧，&lt;br&gt;一路&amp;quot;确定&amp;quot;、&amp;quot;继续&amp;quot;就OK了。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-7750992736262602091?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/7750992736262602091/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=7750992736262602091' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/7750992736262602091'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/7750992736262602091'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/10/freebsdusb.html' title='FreeBSD下USB打印机的安装经验谈'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-5104308117239020955</id><published>2008-10-17T11:30:00.001+08:00</published><updated>2008-10-17T11:30:52.847+08:00</updated><title type='text'> Freebsd7.0 release 安装 diablo-jdk1.6.0</title><content type='html'>.最小化安装freebsd.&lt;br&gt;2.到&lt;a href="http://www.freebsdfoundation.org/downloads/java.shtml"&gt;http://www.freebsdfoundation.org/downloads/java.shtml&lt;/a&gt; 下载&lt;p&gt;Diablo Caffe JDK 1.6.0-7 FreeBSD 7.x/i386 End-User 61M &lt;br&gt;diablo-jdk-freebsd7.i386.1.6.0.07.02.tbz&lt;br&gt;3.敲pkg_add diablo* 后发现少了几个东西，xtrans-1.0.4,xproto-7.0.10_1,xextproto-7.0.2,javavmwrapper-2.3.2,需要安装相应的包，在dist1那张盘里面有，&lt;a href="http://javavmwrapper-2.3.xn--2ftp-qm9f345f2qc212d.freebsd.org"&gt;javavmwrapper-2.3.2我直接到ftp.freebsd.org&lt;/a&gt;上面下。&lt;p&gt;4.安装完上面那几个后，就可以直接安装了，pkg_add diablo*。中间会有提示，敲YES.&lt;br&gt;5.设置JAVA环境：&lt;br&gt;  我用的root用户，因此需要修改.cshrc文件。&lt;br&gt;  vi~/.cshrc&lt;br&gt;  在set path = (/sbin /bin /usr/sbin /usr/bin /usr/games /usr/local/sbin &lt;br&gt;/usr/local/bin $HOME/bin)这一行前面加 上：&lt;br&gt;  setenv JAVA_HOME /usr/local/diablo-jdk1.6.0&lt;br&gt;  setenv CLASSPATH .:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar&lt;br&gt;  然后在set path这一行的那些路径最后面加上jdk的bin路径/usr/local/diablo-jdk1.6.0/bin，就是下面这样：&lt;br&gt;  set path = (/sbin /bin /usr/sbin /usr/bin /usr/games /usr/local/sbin &lt;br&gt;/usr/local/bin $HOME/bin /usr/local   /diablo-jdk1.6.0/bin)&lt;p&gt;退出再登陆一下就ok了。&lt;p&gt;6.重新登录后，敲java -version，看看版本信息。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-5104308117239020955?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/5104308117239020955/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=5104308117239020955' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5104308117239020955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5104308117239020955'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/10/freebsd70-release-diablo-jdk160.html' title=' Freebsd7.0 release 安装 diablo-jdk1.6.0'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-3220123303953679202</id><published>2008-10-14T09:08:00.001+08:00</published><updated>2008-10-14T09:08:26.380+08:00</updated><title type='text'>PostgreSQL分类汇总方法</title><content type='html'>我们知道MySQL中有分类汇总函数GROUP_CONCAT来实现将组内相关值的连接，但是在PostgreSQL没有此类的函数，但是我们可以使用以下两种方法来方便的达到我们的目的:&lt;p&gt;我们首先创建一个测试表，并插入一些测试数据:&lt;p&gt;create table test(id int,name varchar(100));&lt;p&gt;insert into test values(1,&amp;#39;aa&amp;#39;);&lt;br&gt;insert into test values(1,&amp;#39;bb&amp;#39;);&lt;br&gt;insert into test values(2,&amp;#39;cc&amp;#39;);&lt;br&gt;insert into test values(3,&amp;#39;dd&amp;#39;);&lt;br&gt;insert into test values(2,&amp;#39;ff&amp;#39;);&lt;p&gt;1.使用数组函数两组内的列表转换成数组&lt;p&gt;select id,array_to_string(&lt;br&gt;            array(select name from test where id=&lt;a href="http://a.id"&gt;a.id&lt;/a&gt;),&amp;#39;,&amp;#39;)&lt;br&gt;from test a&lt;br&gt;group by id;&lt;p&gt;--结果&lt;p&gt;  3 | dd&lt;br&gt;  2 | cc,ff&lt;br&gt;  1 | aa,bb&lt;p&gt;是不是看起来非常的简单呢，呵呵，非常的cool!&lt;p&gt;2.使用自定义的聚集函数&lt;p&gt;PostgreSQL除了提供给我们的一些预定义函数之外，还有创建聚集函数的DDL语句，非常的灵活！&lt;p&gt;--首先创建一个状态传递函数：实现将统计结果传递连接&lt;p&gt;create function pg_concat( text, text ) returns text as &amp;#39;&lt;br&gt;begin&lt;br&gt;    if $1 isnull then&lt;br&gt;        return $2;&lt;br&gt;    else&lt;br&gt;       return $1 || $2;&lt;br&gt;    end if;&lt;br&gt;end;&amp;#39; language &amp;#39;plpgsql&amp;#39;;&lt;p&gt;--创建一个最终的结果函数：实现将最后一个连接符号清除&lt;p&gt;create function pg_concat_fin(text) returns text as &amp;#39;&lt;br&gt;begin&lt;br&gt;    return substr($1,1,length($1)-1);&lt;br&gt;end;&amp;#39; language &amp;#39;plpgsql&amp;#39;;&lt;p&gt;--创建聚集函数，入口参数basetype:text,状态传递函数：pg_concat,状态变量类型:text,结果函数finalfunc:pg_concat_fin&lt;br&gt;create aggregate pg_concat (&lt;br&gt;    basetype = text,&lt;br&gt;    sfunc = pg_concat,&lt;br&gt;    stype = text,&lt;br&gt;    finalfunc = pg_concat_fin);&lt;p&gt;--使用聚集函数进行统计:&lt;p&gt;select id,pg_concat(name||&amp;#39;,&amp;#39;)&lt;br&gt;from test&lt;br&gt;group by id;&lt;p&gt;--结果&lt;br&gt;  3 | dd&lt;br&gt;  2 | cc,ff&lt;br&gt;  1 | aa,bb&lt;p&gt;和第一种方法得到的结果是一样的，非常的方便。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-3220123303953679202?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/3220123303953679202/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=3220123303953679202' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3220123303953679202'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3220123303953679202'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/10/postgresql_14.html' title='PostgreSQL分类汇总方法'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-5003676541354983966</id><published>2008-10-14T09:07:00.001+08:00</published><updated>2008-10-14T09:07:48.052+08:00</updated><title type='text'> PostgreSQL的许多小技巧</title><content type='html'>1.使用空间索引进行快速间隔数据类型的搜索.&lt;p&gt;间隔搜索有时候很慢，大部分原因是索引优化器不使用索引，并且在开始列和结束列比较独立。一个解决方案是使用空间索引，它可以把两个独立的值当做一个值来使用。&lt;p&gt;postgres=# EXPLAIN ANALYZE SELECT * FROM testip WHERE 19999999 BETWEEN &lt;br&gt;startip AND endip;&lt;p&gt;QUERY PLAN ----------------------------------------------------------------  &lt;br&gt;Seq Scan on testip (cost=0.00..19902.00 rows=200814 width=12) (actual &lt;br&gt;time=3.457..434.218 rows=1 loops=1) Filter: ((19999999 &amp;gt;= startip) AND &lt;br&gt;(19999999 &amp;lt;= endip)) Total runtime: 434.299 ms (3 rows) Time: 435,865 ms&lt;p&gt;结论：根据以上的执行计划，可以知道上边的查询使用的是序列扫描，花费的时间是：435,865 &lt;br&gt;ms&lt;p&gt;postgres=# CREATE INDEX ggg ON testip USING gist &lt;br&gt;((box(point(startip,startip),point(endip,endip))) box_ops);&lt;p&gt;使用如下的查询：&lt;br&gt;EXPLAIN ANALYZE SELECT * FROM testip WHERE &lt;br&gt;box(point(startip,startip),point(endip,endip)) @&amp;gt; box(point &lt;br&gt;(19999999,19999999), point(19999999,19999999));&lt;p&gt;结论：执行计划使用的是Bitmap Index Scan on ggg,花费的时间是：2,805 ms。可见相比以前的查询，使用空间索引的查询效率大大的提高了。&lt;p&gt;2.16进制到10进制的转换&lt;p&gt;我们已经有了系统函数将10进制转换成16进制：to_hex(11)  result: b 下边的函数实现将16进制的数转换成10进制。非常的简单：&lt;p&gt;create or replace function to_dec(text)&lt;br&gt;returns integer as $$&lt;br&gt;declare r int;&lt;br&gt;begin&lt;br&gt;    execute E&amp;#39;select x\&amp;#39;&amp;#39;||$1|| E&amp;#39;\&amp;#39;::integer&amp;#39; into r;&lt;br&gt;    return r;&lt;br&gt;end&lt;br&gt;$$ language plpgsql;&lt;p&gt;--测试&lt;br&gt;select to_dec(&amp;#39;ff&amp;#39;);&lt;p&gt;--结果&lt;br&gt;255&lt;p&gt;3.ALTER TABLE ALTER COLUMN USING 语法&lt;p&gt;在PostgreSQl里边，我们不能将varchar类型直接转换到bool，但是我们可以使用Using语法加判断后进行转换。&lt;p&gt;CREATE TABLE foo(a varchar);&lt;p&gt;INSERT INTO foo VALUES (&amp;#39;ano&amp;#39;);&lt;p&gt;--更改数据类型，会报错误信息&lt;br&gt;ALTER TABLE foo ALTER COLUMN a TYPE boolean ;&lt;br&gt;ERROR:  column &amp;quot;a&amp;quot; cannot be cast to type &amp;quot;pg_catalog.bool&amp;quot;&lt;p&gt;--使用Using语法更改数据类型&lt;br&gt;ALTER TABLE foo&lt;br&gt;ALTER COLUMN a TYPE boolean&lt;br&gt;      USING CASE a&lt;br&gt;      WHEN &amp;#39;ano&amp;#39; THEN true&lt;br&gt;      ELSE false END;&lt;p&gt;--更改成功&lt;br&gt;SELECT * FROM foo;&lt;p&gt;4.Quote_ident 的使用&lt;p&gt;使用双引号是一种防止SQL注入的方法，quote_ident 可以检查参数，如果参数中包含任何非法的字符，它会在参数两边加上&amp;quot;&amp;quot;&lt;br&gt;非常简单和有效，但是问题是&lt;a href="http://schema.name"&gt;schema.name&lt;/a&gt;，因为中间有点分割。问题如下：&lt;p&gt;select quote_ident(&amp;#39;public.foo&amp;#39;);&lt;p&gt;他不能在schema和name两边加上双引号。&lt;p&gt;我们可以通过使用函数来按点分割上边的对象名称，在每个单独的对象上使用quote_ident来完成我们的目的:&lt;p&gt;--对数组进行表转换，针对每一列来使用quote_ident&lt;br&gt;CREATE OR REPLACE FUNCTION quote_array(text[])&lt;br&gt;RETURNS text AS $$&lt;br&gt;SELECT array_to_string(array(SELECT quote_ident($1[i])&lt;br&gt;                                FROM generate_series(1, array_upper($1,1)) &lt;br&gt;g(i)),&lt;br&gt;                       &amp;#39;.&amp;#39;)&lt;br&gt;$$ LANGUAGE SQL IMMUTABLE;&lt;p&gt;--创建函数按点进行拆分字符串&lt;br&gt;CREATE OR REPLACE FUNCTION quote_schema_ident(text)&lt;br&gt;RETURNS text AS $$&lt;br&gt;SELECT quote_array(string_to_array($1,&amp;#39;.&amp;#39;))&lt;br&gt;$$ LANGUAGE SQL IMMUTABLE;&lt;p&gt;--测试&lt;br&gt;select quote_schema_ident(&amp;#39;public.foo tab&amp;#39;);&lt;p&gt;&lt;br&gt;5.我们已经习惯使用PostgreSQL的exception来捕捉错误，但是错误信息一直不知道如何取得，SQLERRM变量可以给我们详细的信息&lt;br&gt;以下是一个具体的示例：&lt;p&gt;CREATE OR REPLACE FUNCTION fn_log_error(p_function varchar, p_location int, &lt;br&gt;p_error varchar)&lt;br&gt;RETURNS void AS $$&lt;br&gt;DECLARE&lt;br&gt;  v_sql varchar;&lt;br&gt;  v_return varchar;&lt;br&gt;  v_error varchar;&lt;br&gt;BEGIN&lt;br&gt;  --连接数据库&lt;br&gt;  PERFORM dblink_connect(&amp;#39;connection_name&amp;#39;, &amp;#39;dbname=...&amp;#39;);&lt;p&gt;  --拼凑插入的字符串&lt;br&gt;  v_sql := &amp;#39;INSERT INTO error_log (function_name, location, error_message, &lt;br&gt;error_time) &amp;#39;&lt;br&gt;           || &amp;#39;VALUES (&amp;#39;&amp;#39;&amp;#39; || p_function_name || &amp;#39;&amp;#39;&amp;#39;, &amp;#39;&lt;br&gt;           || p_location || &amp;#39;, &amp;#39;&amp;#39;&amp;#39; || p_error || &amp;#39;&amp;#39;&amp;#39;, clock_timestamp())&amp;#39;;&lt;br&gt;  --远程执行&lt;br&gt;  SELECT INTO v_return *&lt;br&gt;     FROM dblink_exec(&amp;#39;connection_name&amp;#39;, v_sql, false);&lt;p&gt;  --获取远程的错误信息&lt;br&gt;  SELECT INTO v_error *&lt;br&gt;     FROM dblink_error_message(&amp;#39;connection_name&amp;#39;);&lt;br&gt;  --如果出现错误则抛出异常&lt;br&gt;  IF position(&amp;#39;ERROR&amp;#39; in v_error) &amp;gt; 0 OR position(&amp;#39;WARNING&amp;#39; in v_error) &amp;gt; 0 &lt;br&gt;THEN&lt;br&gt;    RAISE EXCEPTION &amp;#39;%&amp;#39;, v_error;&lt;br&gt;  END IF;&lt;p&gt;  PERFORM dblink_disconnect(&amp;#39;connection_name&amp;#39;);&lt;br&gt;EXCEPTION&lt;br&gt;  WHEN others THEN&lt;br&gt;    --使用SQLERRM 来显示错误信息&lt;br&gt;    PERFORM dblink_disconnect(&amp;#39;connection_name&amp;#39;);&lt;br&gt;    RAISE EXCEPTION &amp;#39;(%)&amp;#39;, SQLERRM;&lt;br&gt;END;&lt;br&gt;$$ LANGUAGE plpgsql SECURITY DEFINER;&lt;p&gt;SQLERRM是一个非常有用的变量，可以详细记录错误的具体信息，帮助我们分析执行中发现的错误。&lt;p&gt;6.循环优化技巧&lt;p&gt;plpgsql对于非SQL操作效率不是特别高。Plpgsql 不喜欢字符或者字符数组的累计操作，当我们也不能用Perl，因此我们只能用SQL&lt;p&gt;--使用循环，结果会比较慢的函数&lt;p&gt;CREATE OR REPLACE FUNCTION SlowList(int) -- slow function, usable for N &amp;lt;= &lt;br&gt;100&lt;br&gt;RETURNS varchar AS $$&lt;br&gt;DECLARE s varchar = &amp;#39;&amp;#39;;&lt;br&gt;BEGIN&lt;br&gt;  FOR i IN 1..$1 LOOP&lt;br&gt;    s := &amp;#39;&amp;lt;item&amp;gt;&amp;#39; || i || &amp;#39;&amp;lt;/item&amp;gt;&amp;#39;;  -- slow is s := s || ..&lt;br&gt;  END LOOP;&lt;br&gt;  RETURN s;&lt;br&gt;END; $$ LANGUAGE plpgsql IMMUTABLE;&lt;p&gt;--使用SQL，结果会比较快的函数&lt;p&gt;CREATE OR REPLACE FUNCTON FastList(int) -- fast function&lt;br&gt;RETURNS varchar AS $$&lt;br&gt;BEGIN&lt;br&gt;  RETURN array_to_string(ARRAY(SELECT &amp;#39;&amp;lt;item&amp;gt;&amp;#39; || i || &amp;#39;&amp;lt;/item&amp;gt;&amp;#39;&lt;br&gt;                                  FROM generate_series(1, $1) g(i)),&lt;br&gt;                         &amp;#39;&amp;#39;);&lt;br&gt;END; $$ LANGUAGE plpgsql IMMUTABLE;&lt;p&gt;--结果:在循环100以下的时候差别并不是很大，当循环更多的时候，差距就非常明显，都来试试吧！&lt;p&gt;7.查询一组之中的头n条记录&lt;p&gt;我们一般的做法是使用子查询如下：&lt;p&gt;SELECT * FROM people WHERE id IN (&lt;br&gt;     SELECT id FROM people s&lt;br&gt;       WHERE people.category = s.category&lt;br&gt;       ORDER BY age LIMIT 2)&lt;br&gt;ORDER BY category, age;&lt;p&gt;使用连接我们也可以达到同样的效果如下：&lt;p&gt;SELECT s1.*&lt;br&gt;   FROM people s1&lt;br&gt;        LEFT JOIN&lt;br&gt;        people s2&lt;br&gt;        ON s1.category = s2.category AND s1.age &amp;lt; s2.age&lt;br&gt;  GROUP BY &lt;a href="http://s1.id"&gt;s1.id&lt;/a&gt;, s1.category&lt;br&gt;  HAVING COUNT(&lt;a href="http://s2.id"&gt;s2.id&lt;/a&gt;) &amp;lt;= 1&lt;br&gt;  ORDER BY s1.category, COUNT(&lt;a href="http://s2.id"&gt;s2.id&lt;/a&gt;);&lt;p&gt;说明:这个SQL语句的含义是找到同一类比自己的age大的记录，最后判断比自己大的记录的个数，如果是0，那么应该排名第一，&lt;br&gt;如果是1，那么排名第二(HAVING COUNT(&lt;a href="http://s2.id"&gt;s2.id&lt;/a&gt;) &amp;lt;= 1)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-5003676541354983966?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/5003676541354983966/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=5003676541354983966' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5003676541354983966'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5003676541354983966'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/10/postgresql.html' title=' PostgreSQL的许多小技巧'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-5926060938579894613</id><published>2008-10-14T09:05:00.001+08:00</published><updated>2008-10-14T09:05:28.462+08:00</updated><title type='text'> slony1-1.2.10配置简介</title><content type='html'>PostgreSQL支持许多复制机制,但是个人觉得slony应该是一个不错的选择,因为slony支持异步,单向,级联的将数据从一个源头复制到多个订阅者手中.&lt;p&gt;异步的意思是一个订阅者的数据不一定是最新的,订阅者可以离线,而并不影响数据源的复制.而当订阅者再次连线后,它可以接收到所有的数据.当然,如果订阅者离线了很长的时间,那么它所要接收的数据将对网络和数据源产生很大的负担.&lt;p&gt;单向意味着你只能在数据源对表进行更改,并将结果复制到订阅者,而不能在订阅者来对表进行更改.&lt;p&gt;级连意味着一个订阅者也可以作为数据的源头来进行数据的发布,从而分担了主数据源的负担.&lt;p&gt;下边我们就开始配置slony, 我是在FreeBSD下配置的,并且已经分别在两台机器上安装好了PostgreSQL 8.2.4和slonyI-1.2.10,注意这里的版本是非常重要的,因为我在以前装 &lt;br&gt;slony1-1.2.9来进行配置的时候会报版本错误.所以还是推荐大家使用最新的版本.&lt;p&gt;在配置之前我们还需要把设置两台PostgreSQL的配置文件pg_hba.conf ,添加如下可以让对方使用用户,密码的访问方式.&lt;p&gt;host    all         all         &lt;a href="http://10.218.143.17/32"&gt;10.218.143.17/32&lt;/a&gt;      password&lt;p&gt;host    all         all         &lt;a href="http://10.218.143.35/32"&gt;10.218.143.35/32&lt;/a&gt;      password&lt;p&gt;下边我们就开始配置slony,配置slony的过程就是通过slonik来输入配置的命令,我们把slonik的配置命令都写成脚本的形式来执行,方便复用.&lt;p&gt;第一个脚本:&lt;a href="http://preamble.sk"&gt;preamble.sk&lt;/a&gt;&lt;p&gt;define CLUSTER  test;&lt;br&gt;define dc35 1;&lt;br&gt;define dc17 2;&lt;br&gt;define fqn fully qualified name;&lt;br&gt;define SUCCESS 0;&lt;br&gt;define FAILURES 1;&lt;p&gt;cluster name = @CLUSTER;&lt;br&gt;node @dc35 admin conninfo = &amp;#39;dbname=portal host=&lt;a href="http://10.218.143.35"&gt;10.218.143.35&lt;/a&gt; user=pgsql &lt;br&gt;password=pgsql&amp;#39;;&lt;br&gt;node @dc17 admin conninfo = &amp;#39;dbname=portal host=&lt;a href="http://10.218.143.17"&gt;10.218.143.17&lt;/a&gt; user=pgsql &lt;br&gt;password=pgsql&amp;#39;;&lt;p&gt;脚本很简单,就是定义一些常量,集群的名称和节点的信息.注意以后的脚本都要包含这个脚本来引用这些常量.&lt;p&gt;第二个脚本:initCluster.sk&lt;p&gt;#!/usr/local/bin/slonik&lt;p&gt;include &amp;lt;&lt;a href="http://preamble.sk"&gt;preamble.sk&lt;/a&gt;&amp;gt;;&lt;p&gt;#初始话集群和主节点&lt;p&gt;init cluster (id=@dc35,comment=&amp;#39;primary node&amp;#39;);&lt;p&gt;#保存节点信息&lt;p&gt;store node&lt;br&gt;(&lt;br&gt;        id = @dc17,&lt;br&gt;        comment = &amp;#39;secondary node - dc17&amp;#39;&lt;br&gt;);&lt;p&gt;#配置连接信息,就是告诉订阅服务器如何来访问数据源的服务器&lt;p&gt;store path&lt;br&gt;(&lt;br&gt;        server = @dc35,&lt;br&gt;        client = @dc17,&lt;br&gt;        conninfo =&amp;#39;dbname=portal host=&lt;a href="http://10.218.143.35"&gt;10.218.143.35&lt;/a&gt; user=pgsql &lt;br&gt;password=pgsql&amp;#39;&lt;br&gt;);&lt;p&gt;store path&lt;br&gt;(&lt;br&gt;        server = @dc17,&lt;br&gt;        client = @dc35,&lt;br&gt;        conninfo =&amp;#39;dbname=portal host=&lt;a href="http://10.218.143.17"&gt;10.218.143.17&lt;/a&gt; user=pgsql &lt;br&gt;password=pgsql&amp;#39;&lt;br&gt;);&lt;p&gt;第三个文件:buildSet.sk&lt;p&gt;#!/usr/local/bin/slonik&lt;p&gt;include&amp;lt;&lt;a href="http://preamble.sk"&gt;preamble.sk&lt;/a&gt;&amp;gt;;&lt;p&gt;#创建复制集,复制集是slony最小的复制单位.&lt;p&gt;create set (id=1,origin=@dc35,comment=&amp;#39;dc35&amp;#39;);&lt;p&gt;#向复制集中添加表&lt;p&gt;set add table (set id=1,origin=@dc35,id=1,fully qualified &lt;br&gt;name=&amp;#39;public.f_slony&amp;#39;);&lt;p&gt;第四个文件:subscribeSet.sk&lt;p&gt;#!/usr/local/bin/slonik&lt;p&gt;include&amp;lt;&lt;a href="http://preamble.sk"&gt;preamble.sk&lt;/a&gt;&amp;gt;;&lt;p&gt;#创建订阅,设置数据源和数据目标.&lt;p&gt;subscribe set (id=1,provider=@dc35,receiver=@dc17,forward=yes);&lt;p&gt;执行完以上4个文件后,slony的整体结构我们基本上已经配置好了.接下来就要启动slon进程来开始复制的工作了,首先我们要写一个配置文件,让slon进行来连接哪个数据库.&lt;p&gt;文件:dc17.slon&lt;p&gt;cluster_name=&amp;#39;test&amp;#39;&lt;br&gt;conn_info=&amp;#39;dbname=portal host=&lt;a href="http://10.218.143.17"&gt;10.218.143.17&lt;/a&gt; user=pgsql password=pgsql&amp;#39;&lt;p&gt;文件:dc35.slon&lt;p&gt;cluster_name=&amp;#39;test&amp;#39;&lt;br&gt;conn_info=&amp;#39;dbname=portal host=&lt;a href="http://10.210.143.35"&gt;10.210.143.35&lt;/a&gt; user=pgsql password=pgsql&amp;#39;&lt;p&gt;启动slon进程:&lt;p&gt;slon -f dc35.slon &amp;gt;dc35.log &amp;amp;&lt;p&gt;slon -f dc17.slon &amp;gt;dc17.log &amp;amp;&lt;p&gt;启动之后观察进程的log信息,如果没有什么错误提示,那就基本上配置成功了,接下来我们就可以测试.我的测试表是f_slony,我们可以对f_slony进行删除修改操作,然后观察订阅的结果.默认slon的扫描频率是2s,我们可以设置这个时间间隔.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-5926060938579894613?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/5926060938579894613/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=5926060938579894613' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5926060938579894613'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5926060938579894613'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/10/slony1-1210.html' title=' slony1-1.2.10配置简介'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-8173655336024501351</id><published>2008-10-08T12:43:00.001+08:00</published><updated>2008-10-08T12:43:41.946+08:00</updated><title type='text'>技术两则</title><content type='html'>1、计算机加入域的时候，提示限制已经满，无法加入的时候，可在域服务器上执行adsiedit.msc（此工具存在于windows安装盘的supporttools中的support tools中。展开DOMAIN NC节点，选择&amp;quot;DC=&amp;quot;对象，右键选择 &lt;br&gt;属性，选择ms-DS-MachineAccountQutota进行编辑即可。&lt;br&gt;2、ISA中RADMIN服务。装了一台代理服务器，配置windows2003 R2 SP2，代理软件为ISA &lt;br&gt;2006 SP1,服务器上装有软件(radmin ( remote administrator 2.2)，可怎么也联不上。于是不停的实验，最后成功（不过联接速度不快）。&lt;br&gt;主要是元素为TCP 入站 端口为RADMIn的端口号(inbound,outbound）设成一致即可。还一个主要的就是要在辅助要设tcp 出站 端口为radmin 端口。&lt;br&gt;原因：一般都设前面的，后面不设。当你发起联接的时候，也有数据流出（要不怎么双向？）不知道大家明白没？&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-8173655336024501351?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/8173655336024501351/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=8173655336024501351' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/8173655336024501351'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/8173655336024501351'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/10/blog-post.html' title='技术两则'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-5944594869738898569</id><published>2008-10-07T14:02:00.002+08:00</published><updated>2008-10-07T14:03:07.515+08:00</updated><title type='text'>PostgreSQL 在 FreeBSD 上的大版本升级</title><content type='html'>唉！升级...升级...升级...这一阵子一直升级，这次轮到 PostgreSQL 大升级。PostgreSQL 不像其它软件，即使是 8.2 升级到 8.3，也必须大改，所以无法直接用 upgrade 工具直接升。即使是 Windows 版本，也必须劳心费力一番。这次我用 FreeBSD 版本的升级做为例子，来说明最简单也是最正确的大改版升级步骤。&lt;br /&gt;首先，请先把原本数据库的数据完全备份下来。如果你是 Windows 的使用者或是 Linux 的使用者，你可以考虑使用 pgAdmin III 的「工具」选单中的「备份」或「备份全域」来做，这样简单很多，但是由于 pgAdmin III 的说明太少，我实在看不懂「备份」对话框中选项的含意，所以干脆不用。最正式的方法是使用在 console 下的工具：pg_dump 和 pg_dumpall。两者的差别在于，前者可以针对某个特定的 database 做备份，而后者一般用来把整个服务器数据做完整的备份。我建议直接使用 pg_dumpall 比较方便和快速。方法如下：&lt;br /&gt;$ pg_dumpall &gt; filename&lt;br /&gt;而 filename 你可以自己取，比如 host_a.20080206.full.dump 之类的。名称中加入日期可以让你更清楚知道这个备份档备份的日期。加入 full 字眼，可以提醒自己，这是完整备份，而非一般维护时所做的连续性部份备份的一份。如果你所管理的 PostgreSQL 有超过一台以上，那么最好连数据库主机名称都注明。&lt;br /&gt;对了，差点忘了一件极重要的事！在 Windows 上，只要你使用 administrators 群组中的任何一位使用者登入，然后从开始菜单→PostgreSQL 8.3→Command Prompt，就可以打开「命令提示字符」，而且可以下达 pg_dumpall 指令；但是，在 FreeBSD，一般安装时，预设 root 是不允许执行 PostgreSQL 的相关指令的，所以请先切换成 pgsql 用户，如果你没更动 pgsql 的密码，那么预设的密码很「随机」，也就是任你怎么猜也都猜不出来，但是你可以先用 su 切成 root，再用 su - pgsql 切换成 pgsql 使用者，不用输入任何密码即可，这时就可以执行上述指令。但是请注意，这时最好把这个备份文件移到安全位置，以免继续进行的安装过程中不傎误砍。所以这时候你最好是先跳回 root，请下 exit 指令，然后用 cp 指令把刚才那个 dump 檔 copy 到任何你暂存的位置。&lt;br /&gt;接着正式执行安装。在安装新版本之前，必须先移除旧版本，否则两个 daemon 会抢同一个 TCP port，开机时会有无法预知的状况出现。首先先看一下你的服务器中，目前装了哪些和 PostgreSQL 相关的 package：&lt;br /&gt;# pkg_info  grep postgresql&lt;br /&gt;这时候你至少可以看到两个 package 出现在清单中，而我多了一个：&lt;br /&gt;postgresql-client-8.2.6_1 PostgreSQL database (client)postgresql-contrib-8.2.6 The contrib utilities from the PostgreSQL distributionpostgresql-server-8.2.6 The most advanced open-source database available anywhere&lt;br /&gt;一般来说，如果你没有安装Server instrumentation 功能，那么应该只有 client 和 server 两个 package。但是这个小清单并不完整，如果你还有安装 php 和 PostgreSQL 相关的驱动程序，那么这时候并不会出现在这个清单当中。不用担心，你若移除的顺序不对，出现相依的套件，那么把相依套件移除，再来移除目标套件即可。只是这时候你最好拿只笔记下你一共移除了哪些套件，将来才能再一一重新安装回去。我们先以这三个 package 来说好了，如果你没移除旧版本的 server，那么直接移除 client 会被提醒，而且停止进行安装动作。同样的，如果你没先移除旧版本的 contrib 和 php 相关 package，你在移除 client 时也会因为相依套件尚未被移除，而被停止移除 client 的动作。所以若以上述三者为例，则移除的顺序为：&lt;br /&gt;# /usr/local/etc/rc.d/postgresql stop &lt;-- 先停掉目前的 PostgreSQL server# pkg_delete postgresql-contrib-8.2.6# pkg_delete postgresql-server-8.2.6# pkg_delete postgresql-client-8.2.6_1&lt;br /&gt;这时请把 /usr/local/pgsql/data 整个目录移走，像我只是把它改个名称，而让它继续留着，说不定哪天还会用到目录中的某些档案：mv /usr/local/pgsql/data /usr/local/pgsql/data_8.2。然后就可以开始使用 port 来安装 PostgreSQL 8.3 了。在安装前，请先确定你的服务器上的 port tree 是否已是最新的版本，如果你的 port tree 是在 2008/2/5 天亮前更新的，可能 postgresql-server-8.3 还不是最新版本，请先手动更新 port tree。如果已是最新版本，那么切到该 port 目录：&lt;br /&gt;# cd /usr/ports/databases/postgresql83-server# make install clean&lt;br /&gt;FreeBSD 会自动帮你将 8.3 版的 server 和 client 都一并装好。接着把 contrib package 也装起来：&lt;br /&gt;# cd ../postgresql-contrib# make install clean&lt;br /&gt;如果你曾经把 php5 的 driver 移除掉或 JDBC 等等等之前移除掉的套件，现在也请用同样的方法把所有新的版本一一装回去。这样就好了吗？还早，请先看一下你的 /usr/local/pgsql 下是否已经建好新的数据库？&lt;br /&gt;# ls /usr/local/pgsql&lt;br /&gt;如果这个目录下只出现一个刚才更名的 data_8.2，那么代表 Makefile 并没有自动帮你做 initdb，请执行：&lt;br /&gt;# /usr/local/etc/rc.d/postgresql initdb &lt;a href="http://www.cheeren.com/?q=node/152#[1]#[1]"&gt;[1]&lt;/a&gt;&lt;br /&gt;这时你再下 ls /usr/local/pgsql 指令时，就可以看到多出一个 data 目录了，这样才能正确启动 PostgreSQL：&lt;br /&gt;# /usr/local/etc/rc.d/postgresql start &lt;a href="http://www.cheeren.com/?q=node/152#[2]#[2]"&gt;[2]&lt;/a&gt;&lt;br /&gt;如果没出现任何错误讯息，那么先恭喜你，安装好了。但是工作才完成一半，再来是把原来备份的数据回存回数据库中：&lt;br /&gt;# su - pgsql$ psql -f filename postgres&lt;br /&gt;也就是先切成 pgsql 使用者，接着执行 PostgreSQL 的交互式指令输入工具：psql，然后把刚才你的 dump 档的名称(这里当然是完整路径名称)取代上面的 filename。接着一些讯息代表着数据库回存的动作，正在做什么动作。如果一切错误讯息都没有出现过，那么恭喜你，工作完成了 80%。对于 Windows 的使用者来说，只要记住最后一条指令，就可以把刚才 pg_dumpall 所备份的数据回存了。Windows 的使用者真幸福。&lt;br /&gt;什么？才完成 80%？是的，有两个档可能之前的版本你有更动过，分别是 postgresql.conf 和 pg_hba.conf，它们在 FreeBSD 中应该位于 /usr/local/pgsql/data 目录下，请把之前曾经更动过的改回去，但是请把 release notes 先读过一遍，因为 postgresql.conf 中很多管理项目都更动过了，可能之前你所更改的项目，8.3 版已经把该项和其它项目合并，并取了新的项目名称了，先读过 release notes 的 E.1.2.2. Configuration Parameters 是很重要的。还有，刚才如果把旧的 8.2 版的 /usr/local/pgsql/data 目录直接删掉，那此刻就糗了，你必须用你的记忆力回想你曾经更动过的项目和内容，所以我才会建议只需把它更名，保留下来。&lt;br /&gt;若是你对 PostgreSQL 的备份和回存有兴趣，英文程序也还可以，那么请进一步参考 PostgreSQL 的在线说明：&lt;a title="Chapter 24. Backup and Restore" href="http://www.postgresql.org/docs/8.3/static/backup.html" target="_blank"&gt;Chapter 24. Backup and Restore&lt;/a&gt;。&lt;br /&gt;附注：&lt;a name="[1]"&gt;&lt;/a&gt;[1] 当然啰，如果新的 data 目录已经生成，也就是 Makefile 已经自动帮你执行 initdb 的动作了，那么 initdb 这个动作就可以省了。我会特别这样提的原因是，我现这两天的抢先版本的 Makefile 怪怪的，有时不会自动执行 initdb 动作。 &lt;a name="[2]"&gt;&lt;/a&gt;[2] 如果你没有像我这么麻烦的用 pg_dumpall 和 psql 来备份回存，直接升级(还是得先移除旧版本再安装新版本)，表面上看起来还是可以升级，但是，事实上 Makefile 会把你旧版本的 postgresql.conf 和 pg_hba.conf 复制一份到新的 data 目录中。如我文中所说的，postgresql.conf 在这个版本中有大更动，因此，当你打算启动数据库时，会出现 FATAL ERROR！解决方法很简单，用不着重灌，把新的 data 目录移走(一样用更名的)，执行 /usr/local/etc/postgresql initdb，重做一次 initdb，就会有一个全新版本的 data 了。[3] 这篇文章仅适用于负载不大的服务器上，倘若你的服务器是 mission critical 的大用量服务器，虽然基本的升级概念是一样的，也就是数据库大升级等同重新安装，所以服务势必一定得中断，但是事前的演练和良好的计划，可以让停机服务的时间减少。在这种情况，建议必须得增加备援服务器，在主服务器升级的同时，让备援服务器先暂时服务。说到这里，就得牵涉到「数据库复制」(replication) 的主题了。等我有空再来写一篇 PostgreSQL 和 replication 相关的文章。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-5944594869738898569?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/5944594869738898569/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=5944594869738898569' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5944594869738898569'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5944594869738898569'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/10/postgresql-freebsd.html' title='PostgreSQL 在 FreeBSD 上的大版本升级'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-5504318480522744638</id><published>2008-10-07T14:02:00.001+08:00</published><updated>2008-10-07T14:02:42.653+08:00</updated><title type='text'>FreeBSD 安装 PostgreSQL 的笔记</title><content type='html'>本文是笔者用来记录 FreeBSD 安装 PostgreSQL 的笔记，文中有提到为了增加 PostgreSQL 的 max_connections 数目，而调整了 FreeBSD 系统的 /etc/sysctl.conf &amp;amp; /boot/loader.conf 两个档案。如果你只是想安装 PostgreSQL 玩玩，而不需要调整 max_connections 数目，你可以忽略修改上述两个档案的内容。&lt;br /&gt;1.修改 FreeBSD 系统参数&lt;br /&gt;修改 /etc/sysctl.conf 增加以下指令kern.ipc.shmmax=134217728kern.ipc.shmall=32768kern.ipc.semmap=256&lt;br /&gt;修改 /boot/loader.conf 增加以下指令kern.ipc.semmni=256kern.ipc.semmns=512kern.ipc.semmnu=256&lt;br /&gt;2.安装 PostgreSQLcd /usr/ports/databases/postgresql83-servermake install&lt;br /&gt;安装 libxml2 模块cd /usr/ports/textproc/libxml2make install&lt;br /&gt;安装 libxslt 模块cd /usr/ports/textproc/libxsltmake install&lt;br /&gt;安装 XML for PostgreSQLcd /usr/ports/databases/postgresql83-server/work/postgresql-8.3.3/contrib/xml2gmake install&lt;br /&gt;安装 adminpackcd /usr/ports/databases/postgresql83-server/work/postgresql-8.3.3/contrib/adminpackgmake install&lt;br /&gt;3.修改 /etc/rc.conf 增加以下指令，以便开机自动执行 PostgreSQL&lt;br /&gt;postgresql_enable=”YES”# optionalpostgresql_data=”/pgdb”postgresql_flags=”-w -s -m fast”postgresql_initdb_flags=”–encoding=utf-8 –lc-collate=C”postgresql_class=”default”&lt;br /&gt;4.初始 PostgreSQL 数据库建立放置 PostgreSQL 数据库档案的目录，同时修改该数据匣权限，改完权限后便初始化 PostgreSQL 数据库&lt;br /&gt;mkdir /pgdb&lt;br /&gt;chown pgsql:pgsql /pgdb&lt;br /&gt;su -l pgsql -c “initdb -D /pgdb -E utf8″&lt;br /&gt;5.修改 /pgdb/postgresql.conf 以便符合实际系统运作需求，这边大家可以斟酌调整listen_addresses = ‘*’ //聆听其它主机联机讯号max_connections = 200 //增加同时联机数量#log_destination = ’syslog’ // 批注log_destination = ’stderr’ // 标准输出 loglog_directory = ‘pg_log’log_filename = ‘postgresql-%Y-%m-%d_%H%M%S.log’log_rotation_age = 1dlog_rotation_size = 10MBclient_min_messages = noticelog_min_messages = noticelog_error_verbosity = defaultlog_min_error_statement = errorlog_duration = onlog_line_prefix = ‘%u %d %h %i’log_statement = ‘mod’stats_start_collector = onstats_row_level = on&lt;br /&gt;6.修改 /pgdb/pg_hba.conf 以便可以透过网络连接该 PostgreSQL 服务器。# “local” is for Unix domain socket connections onlylocal all all trust# IPv4 local connections:host all all 127.0.0.1/32 trusthost all all 10.3.1.21/32 trusthost all all 10.3.1.22/32 trusthost all all 10.3.1.23/32 trusthost all all 10.1.1.0/32 trusthost all all 10.2.1.0/24 md5# IPv6 local connections:host all all ::1/128 md5host all smart_teacher 10.3.1.0/24 md5host all postgres 10.3.1.0/24 md5host all ischool 10.3.1.0/24 md5&lt;br /&gt;7.启动 PostgreSQL/usr/local/etc/rc.d/postgresql start&lt;br /&gt;8.建立预设使用者su -l pgsql -c “createuser -P”&lt;br /&gt;账号名称：postgres&lt;br /&gt;9.启用其它相关外挂套件&lt;br /&gt;启用 adminpacksu -l pgsql -c “psql -U postgres postgres &lt; /usr/local/share/postgresql/contrib/adminpack.sql”&lt;br /&gt;启用 XML 支援 for PostgreSQLsu -l pgsql -c “psql -U postgres postgres &lt; /usr/local/share/postgresql/contrib/pgxml.sql”&lt;br /&gt;完成以上步骤，基本上你的 PostgreSQL 应该就可以正常运作了。&lt;br /&gt;— 2008/08/13 新增 —&lt;br /&gt;PostgreSQL 安装时修改 Makefile 档案，可以解决 xslt_process 无法安装的问题&lt;br /&gt;找到底下设定&lt;br /&gt;CONFIGURE_ARGS+=–with-libraries=${LOCALBASE}/lib \–with-includes=${LOCALBASE}/include \–enable-thread-safety \–with-docdir=${DOCSDIR} \–with-libxslt \–with-libxml增加红色的部份&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-5504318480522744638?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/5504318480522744638/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=5504318480522744638' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5504318480522744638'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5504318480522744638'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/10/freebsd-postgresql.html' title='FreeBSD 安装 PostgreSQL 的笔记'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-3880335112717937904</id><published>2008-10-07T13:06:00.001+08:00</published><updated>2008-10-07T13:08:30.696+08:00</updated><title type='text'>ASP.Net2.0连接PostgreSQL数据库</title><content type='html'>PostgreSQL 是一种非常先进的对象-关系型数据库管理系统（ORDBMS），目前功能最强大，特性最丰富和最先进的自由软件数据库系统。有些特性甚至连商业数据库都不具备。这个起源于伯克利（BSD）的数据库研究计划目前已经衍生成一项国际开发项目，并且有非常广泛的用户。自从MySQL 被Sun 收购后，相信很多对该收购不放心的朋友会转而看好PostgreSQL 的前途。之前我曾经博客中介绍过Ubuntu中通过源码安装编译安装PostgreSQL。在ASP.Net中使用PostgreSQL数据库作为后端数据存储，连接方法有以下两种：&lt;br /&gt; &lt;br /&gt;一、采用商业组件的方式PostgreSQLDirect .NET目前商业组件使用较多的是PostgreSQLDirect .NET，不过这个需要付费，最便宜的标准版网上报价也要1000元人民币。PostgreSQLDirect .NET是一款为Microsoft .NET Framework提供直接PostgreSQL数据库连接的数据发生器控件。它完全基于ADO.NET方法，因此您完全可以采用标准ADO.NET数据提供的方法来使用它。安装之后会在Visual Studio 2005工具栏出现PostgreSQLDirect组件包含了PgSqlConnection PgSqlCommand PgSqlDataAdapter 等控件(如下图)，然后在项目里添加引用：CoreLab.Data和CoreLab.PostgreSql，可以拖放控件连接数据库，使用方法2005的和自带控件基本相同。也可以写代码连接数据库，具体代码如下：&lt;br /&gt;PgSqlDataSet ds = new PgSqlDataSet();string sql = "SELECT * FROM test WHERE tid=3000";PgSqlConnection con = new PgSqlConnectio("user id=username;Password=pwd;host=hostname;database=test");PgSqlDataAdapter da = new PgSqlDataAdapter(sql, con);da.Fill(ds);this.dataGridView1.DataSource = ds;this.dataGridView1.DataMember = ds.Tables[0].ToString();&lt;br /&gt;&lt;br /&gt;二、使用开源组件Npgsql&lt;br /&gt;Npgsql是一个为开源数据库PostgreSQL提供.NET Framework平台下数据驱动服务的库函数程序集(.NET Data Provider)，它允许用户在.NET Framework平台下建立用于访问PostgreSQL数据库的应用。&lt;br /&gt;解压后将其中的两个dll文件复制到应用程序的Bin目录下，&lt;br /&gt;然后在项目里添加引：Mono.Security和NPgSQL，&lt;br /&gt;在代码里添加using NpgSQL;&lt;br /&gt;具体代码如下:&lt;br /&gt;string sql = "SELECT * FROM test WHERE tid=3000";&lt;br /&gt;NpgsqlConnection con = new NpgsqlConnection("server=hostname;uid=username;pwd=pwd;database=test");&lt;br /&gt;NpgsqlDataAdapter da = new NpgsqlDataAdapter(sql,con);&lt;br /&gt;DataSet ds = new DataSet();&lt;br /&gt;da.Fill(ds);&lt;br /&gt;this.dataGridView1.DataSource = ds;&lt;br /&gt;this.dataGridView1.DataMember = ds.Tables[0].ToString();&lt;br /&gt;&lt;br /&gt;相关链接：&lt;br /&gt;PostgreSQLDirect .NET官方网站 &lt;a href="http://www.crlab.com/pgsqlnet/"&gt;http://www.crlab.com/pgsqlnet/&lt;/a&gt;&lt;br /&gt;Npgsql官方网站 &lt;a href="http://pgfoundry.org/projects/npgsql"&gt;http://pgfoundry.org/projects/npgsql&lt;/a&gt;&lt;br /&gt;PostgreSQL官方网站 &lt;a href="http://www.postgresql.org/"&gt;http://www.postgresql.org/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-3880335112717937904?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/3880335112717937904/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=3880335112717937904' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3880335112717937904'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3880335112717937904'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/10/aspnet20postgresql.html' title='ASP.Net2.0连接PostgreSQL数据库'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-2066095334086889205</id><published>2008-09-15T18:57:00.001+08:00</published><updated>2008-09-15T18:57:23.632+08:00</updated><title type='text'>FlyTreeView V4.3.1.43破解手记</title><content type='html'>&lt;div class="postbody"&gt;&lt;br /&gt;    官方网址：&lt;a href="http://www.9rays.net/" target="_blank"&gt;http://www.9rays.net/&lt;/a&gt;&lt;br /&gt;     未破解前，会有45天的试用期限制。超其以后运行时会有异常：“9Rays.Net FlyTreeView for ASP.NET 2.0 evaluation  period has&lt;br /&gt;&lt;br /&gt;expired.”&lt;br /&gt;    破解工具：ildasm,ilasm,StrongNameRemove20, UEdit,  Reflector(个人习惯使用，这个随便了) [注] ildasm[vs2003版]可以到看雪&lt;span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CF%C2%D4%D8"&gt;下载&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;修改版，原版的有限制&lt;br /&gt;    这个&lt;span class="t_tag" onclick="tagshow(event)" href="tag.php?name=DLL"&gt;DLL&lt;/span&gt;的破解的关键是让它永不过期或者修改一个足够大的时间值让我们使用就可以了，网上有破解的就是直接修改它的过期期限，使用&lt;br /&gt;&lt;br /&gt;用户可以使用的期限加长，达到破解。在本例中，我使用的是直接把过期异常干掉，使得永不过期。&lt;br /&gt;&lt;br /&gt;  1.  用ildasm打开NineRays.WebControls.FlyTreeView.dll，转存为aaa.il；&lt;br /&gt;&lt;br /&gt;  2.  找到用UEdit打开aaa.il，并找到"has expired"，来到如下的&lt;span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B4%FA%C2%EB"&gt;代码&lt;/span&gt;处理&lt;br /&gt;//  为了便于分析，我把reflactor的反编译代码贴出来&lt;br /&gt;public FlyTreeView()&lt;br /&gt;{&lt;br /&gt;    this.NodeEvents  = new List&lt;flytreenodeeventargs&gt;();&lt;br /&gt;    DateTime maxValue =  DateTime.MaxValue;&lt;br /&gt;   &lt;br /&gt;    //  当然这个异常我们也可以去掉，但在本次过程中，我们主要去掉下面那个过期的异常部分&lt;br /&gt;    try&lt;br /&gt;    {&lt;br /&gt;        maxValue  = File.GetLastWriteTime(base.GetType().Assembly.Location);&lt;br /&gt;    }&lt;br /&gt;     catch&lt;br /&gt;    {&lt;br /&gt;        throw new Exception("Unknown TRIAL version error has  occurred."&lt;img alt="" src="http://www.unpack.cn/images/smilies/default/wink.gif" border="0" smilieid="4" /&gt;;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    // 我们最关心的是过期的异常，所以这个异常是关键部分&lt;br /&gt;     if (maxValue &lt; DateTime.Now.AddDays(-45))&lt;br /&gt;    {&lt;br /&gt;        throw new  Exception("9Rays.Net FlyTreeView for ASP.NET 2.0 evaluation period has  expired."&lt;img alt="" src="http://www.unpack.cn/images/smilies/default/wink.gif" border="0" smilieid="4" /&gt;;&lt;br /&gt;    }&lt;br /&gt;    this._&lt;span class="t_tag" onclick="tagshow(event)" href="tag.php?name=fly"&gt;fly&lt;/span&gt;ControlCommon = new  FlyControlCommon&lt;flytreeview&gt;(this, this.ViewState, this.Context);&lt;br /&gt;     this._dataBindings = new FlyNodeBindingCollection();&lt;br /&gt;    this._nodes = new  FlyTreeNodeCollection(this);&lt;br /&gt;    this._nodeTypes = new  FlyNodeTypeCollection();&lt;br /&gt;    this.ShadowNodes = new  FlyTreeNodeCollection(this);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;看了反编译的代码，简单一点儿，我们只要把&lt;br /&gt;    if  (maxValue &lt; DateTime.Now.AddDays(-45))&lt;br /&gt;    {&lt;br /&gt;        throw new  Exception("9Rays.Net FlyTreeView for ASP.NET 2.0 evaluation period has  expired."&lt;img alt="" src="http://www.unpack.cn/images/smilies/default/wink.gif" border="0" smilieid="4" /&gt;;&lt;br /&gt;    }&lt;br /&gt;这段代码干掉就可以了啊？当然，我们也可以把&lt;br /&gt;    try&lt;br /&gt;     {&lt;br /&gt;        maxValue =  File.GetLastWriteTime(base.GetType().Assembly.Location);&lt;br /&gt;    }&lt;br /&gt;     catch&lt;br /&gt;    {&lt;br /&gt;        throw new Exception("Unknown TRIAL version error has  occurred."&lt;img alt="" src="http://www.unpack.cn/images/smilies/default/wink.gif" border="0" smilieid="4" /&gt;;&lt;br /&gt;     }&lt;br /&gt;这段代码也干掉，呵呵。&lt;br /&gt;那我们就开始吧，&lt;br /&gt;下面我们结合反编译代码对下面的&lt;span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%B3%CC%D0%F2"&gt;程序&lt;/span&gt;进行分析，并去掉关键的异常代码部分&lt;br /&gt;&lt;br /&gt;//  源代码如下&lt;br /&gt;  .method public hidebysig specialname rtspecialname&lt;br /&gt;           instance void  .ctor() cil managed&lt;br /&gt;  {&lt;br /&gt;    // 代码大小       173 (0xad)&lt;br /&gt;     .maxstack  5&lt;br /&gt;    .locals init (valuetype [mscorlib]System.DateTime V_0,&lt;br /&gt;              string V_1,&lt;br /&gt;             valuetype [mscorlib]System.DateTime  V_2)&lt;br /&gt;&lt;br /&gt;    //***     this.NodeEvents = new  List&lt;flytreenodeeventargs&gt;(); 对应的IL代码开始   ***//&lt;br /&gt;     IL_0000:  ldarg.0&lt;br /&gt;    IL_0001:  newobj     instance void class  [mscorlib]System.Collections.Generic.List`1&lt;class &lt;br /&gt;&lt;br /&gt;NineRays.WebControls.FlyTreeNodeEventArgs&gt;::.ctor()&lt;br /&gt;     IL_0006:  stfld      class [mscorlib]System.Collections.Generic.List`1&lt;class&gt; &lt;br /&gt;&lt;br /&gt;NineRays.WebControls.FlyTreeView::NodeEvents&lt;br /&gt;    //***      this.NodeEvents = new List&lt;flytreenodeeventargs&gt;(); 对应的IL代码结束    ***//&lt;br /&gt;&lt;br /&gt;//**************** 获取最大的时间值，并保存到本地变量maxValue里对应IL就是V_0&lt;br /&gt;     //***     DateTime maxValue = DateTime.MaxValue; 对应的IL代码开始   ***//&lt;br /&gt;     IL_000b:  ldarg.0&lt;br /&gt;    IL_000c:  call       instance void  [System.Web]System.Web.UI.WebControls.HierarchicalDataBoundControl::.ctor()&lt;br /&gt;     IL_0011:  ldsfld     valuetype [mscorlib]System.DateTime  [mscorlib]System.DateTime::MaxValue&lt;br /&gt;    IL_0016:  stloc.0&lt;br /&gt;    //***      DateTime maxValue = DateTime.MaxValue; 对应的IL代码结束    ***//&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// ************************************   第一个异常的代码对应  开始  ***********************************//&lt;br /&gt;//************ 取&lt;span class="t_tag" onclick="tagshow(event)" href="tag.php?name=%CE%C4%BC%FE"&gt;文件&lt;/span&gt;的最后修改时间值，正常的话保存到本地变量maxValue里对应IL就是V_0，如果错误，则异常&lt;br /&gt;*  reflector反编译代码&lt;br /&gt;*     try&lt;br /&gt;*    {&lt;br /&gt;*        maxValue =  File.GetLastWriteTime(base.GetType().Assembly.Location);&lt;br /&gt;*    }&lt;br /&gt;*     catch&lt;br /&gt;*    {&lt;br /&gt;*        throw new Exception("Unknown TRIAL version error has  occurred."&lt;img alt="" src="http://www.unpack.cn/images/smilies/default/wink.gif" border="0" smilieid="4" /&gt;;&lt;br /&gt;*    }&lt;br /&gt;&lt;br /&gt;* 对应的IL 代码&lt;br /&gt;    .try&lt;br /&gt;    {&lt;br /&gt;       IL_0017:  ldarg.0&lt;br /&gt;      IL_0018:  call       instance class  [mscorlib]System.Type [mscorlib]System.Object::GetType()&lt;br /&gt;       IL_001d:  callvirt   instance class [mscorlib]System.Reflection.Assembly  [mscorlib]System.Type::get_Assembly()&lt;br /&gt;      IL_0022:  callvirt   instance  string [mscorlib]System.Reflection.Assembly::get_Location()&lt;br /&gt;       IL_0027:  stloc.1&lt;br /&gt;      IL_0028:  ldloc.1&lt;br /&gt;      IL_0029:  call        valuetype [mscorlib]System.DateTime  [mscorlib]System.IO.File::GetLastWriteTime(string)&lt;br /&gt;       IL_002e:  stloc.0&lt;br /&gt;      IL_002f:  leave.s    IL_003d&lt;br /&gt;&lt;br /&gt;    }  // end  .try&lt;br /&gt;    catch [mscorlib]System.Object&lt;br /&gt;    {&lt;br /&gt;      IL_0031:  pop&lt;br /&gt;       IL_0032:  ldstr      "Unknown TRIAL version error has occurred."&lt;br /&gt;       IL_0037:  newobj     instance void  [mscorlib]System.Exception::.ctor(string)&lt;br /&gt;      IL_003c:  throw&lt;br /&gt;&lt;br /&gt;     }  // end handler&lt;br /&gt;// ************************************   第一个异常的代码对应  结束  ***********************************//&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//  *************************************  第二个异常的代码对应  开始  ***********************************//&lt;br /&gt;//************  maxValue跟当前时间-45天相比较，如果在试用期内，则正常，不在试用期内，则异常&lt;br /&gt;*  reflector反编译代码&lt;br /&gt;*    if  (maxValue &lt; DateTime.Now.AddDays(-45))&lt;br /&gt;*    {&lt;br /&gt;*        throw new  Exception("9Rays.Net FlyTreeView for ASP.NET 2.0 evaluation period has  expired."&lt;img alt="" src="http://www.unpack.cn/images/smilies/default/wink.gif" border="0" smilieid="4" /&gt;;&lt;br /&gt;*    }&lt;br /&gt;&lt;br /&gt;* IL 代码开始&lt;br /&gt;    // ********  这里开始是判断当前时间与文件创建时间的比较，如果在试用期内，则正常试用，否则则抛出过期的异常&lt;br /&gt;    IL_003d:  ldloc.0&lt;br /&gt;     IL_003e:  call       valuetype [mscorlib]System.DateTime  [mscorlib]System.DateTime::get_Now()&lt;br /&gt;    IL_0043:  stloc.2&lt;br /&gt;     IL_0044:  ldloca.s   V_2&lt;br /&gt;    IL_0046:  ldc.r8     -45.&lt;br /&gt;    IL_004f:  call        instance valuetype [mscorlib]System.DateTime  [mscorlib]System.DateTime::AddDays(float64)&lt;br /&gt;    IL_0054:  call       bool  [mscorlib]System.DateTime:&lt;img alt="" src="http://www.unpack.cn/images/smilies/default/13.gif" border="0" smilieid="7" /&gt;p_LessThan(valuetype [mscorlib]System.DateTime,&lt;br /&gt;                                                                      valuetype  [mscorlib]System.DateTime)&lt;br /&gt;    IL_0059:  brfalse.s  IL_0066        //  如果没超出试用期，则跳转，否则抛异常&lt;br /&gt;// 我们的思路，不管是否超出试用期都不让它抛出异常，那么我们最简单的方法，就是把抛异常的代码段干掉&lt;br /&gt;//  那我们还等什么呀，直接把下面的关键部分代码注释掉不就行了吗，呵呵:） 是不是很Easy的啊&lt;br /&gt;//*************************    关键位置开始  ^_^  *******************************************************//&lt;br /&gt;     //IL_005b:  ldstr      "9Rays.Net FlyTreeView for ASP.NET 2.0 evaluation p"&lt;br /&gt;     //+ "eriod has expired."                //  查找到的位置***************************&lt;br /&gt;    //IL_0060:  newobj     instance void  [mscorlib]System.Exception::.ctor(string)&lt;br /&gt;     //IL_0065:  throw&lt;br /&gt;//*************************   关键位置结束 ^_^    *******************************************************//&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;//  *************************************  其他类域的初始化代码  开始  ***********************************//&lt;br /&gt;*  reflector反编译代码&lt;br /&gt;*     this._flyControlCommon = new FlyControlCommon&lt;flytreeview&gt;(this,  this.ViewState, this.Context);&lt;br /&gt;*    this._dataBindings = new  FlyNodeBindingCollection();&lt;br /&gt;*    this._nodes = new  FlyTreeNodeCollection(this);&lt;br /&gt;*    this._nodeTypes = new  FlyNodeTypeCollection();&lt;br /&gt;*    this.ShadowNodes = new  FlyTreeNodeCollection(this);&lt;br /&gt;&lt;br /&gt;* IL 代码开始&lt;br /&gt;    IL_0066:  ldarg.0&lt;br /&gt;     IL_0067:  ldarg.0&lt;br /&gt;    IL_0068:  ldarg.0&lt;br /&gt;    IL_0069:  callvirt   instance  class [System.Web]System.Web.UI.StateBag  [System.Web]System.Web.UI.Control::get_ViewState()&lt;br /&gt;    IL_006e:  ldarg.0&lt;br /&gt;     IL_006f:  callvirt   instance class [System.Web]System.Web.HttpContext  [System.Web]System.Web.UI.Control::get_Context()&lt;br /&gt;    IL_0074:  newobj      instance void class NineRays.WebControls.FlyControlCommon`1&lt;class &lt;br /&gt;&lt;br /&gt;NineRays.WebControls.FlyTreeView&gt;::.ctor(!0,&lt;br /&gt;                                                                                                                                &lt;br /&gt;&lt;br /&gt;      class  [System.Web]System.Web.UI.StateBag,&lt;br /&gt;                                                                                                                                &lt;br /&gt;&lt;br /&gt;      class [System.Web]System.Web.HttpContext)&lt;br /&gt;     IL_0079:  stfld      class NineRays.WebControls.FlyControlCommon`1&lt;class&gt; &lt;br /&gt;&lt;br /&gt;NineRays.WebControls.FlyTreeView::_flyControlCommon&lt;br /&gt;     IL_007e:  ldarg.0&lt;br /&gt;    IL_007f:  newobj     instance void  NineRays.WebControls.FlyNodeBindingCollection::.ctor()&lt;br /&gt;    IL_0084:  stfld       class NineRays.WebControls.FlyNodeBindingCollection  NineRays.WebControls.FlyTreeView::_dataBindings&lt;br /&gt;    IL_0089:  ldarg.0&lt;br /&gt;     IL_008a:  ldarg.0&lt;br /&gt;    IL_008b:  newobj     instance void  NineRays.WebControls.FlyTreeNodeCollection::.ctor(object)&lt;br /&gt;     IL_0090:  stfld      class NineRays.WebControls.FlyTreeNodeCollection  NineRays.WebControls.FlyTreeView::_nodes&lt;br /&gt;    IL_0095:  ldarg.0&lt;br /&gt;     IL_0096:  newobj     instance void  NineRays.WebControls.FlyNodeTypeCollection::.ctor()&lt;br /&gt;    IL_009b:  stfld       class NineRays.WebControls.FlyNodeTypeCollection  NineRays.WebControls.FlyTreeView::_nodeTypes&lt;br /&gt;    IL_00a0:  ldarg.0&lt;br /&gt;     IL_00a1:  ldarg.0&lt;br /&gt;    IL_00a2:  newobj     instance void  NineRays.WebControls.FlyTreeNodeCollection::.ctor(object)&lt;br /&gt;     IL_00a7:  stfld      class NineRays.WebControls.FlyTreeNodeCollection  NineRays.WebControls.FlyTreeView::ShadowNodes&lt;br /&gt;&lt;br /&gt;//  *************************************  其他类域的初始化代码  结束  ***********************************//&lt;br /&gt;&lt;br /&gt;    IL_00ac:  ret&lt;br /&gt;  } // end  of method FlyTreeView::.ctor&lt;br /&gt;&lt;br /&gt;  3.  别忘了看一下文件开头有没有加publickey，还真的有呀，我这里找到如下的代码&lt;br /&gt;  .publickey = (00 24 00 00 04 80 00  00 94 00 00 00 06 02 00 00   // .$..............&lt;br /&gt;                00 24 00 00  52 53 41 31 00 04 00 00 01 00 01 00   // .$..RSA1........&lt;br /&gt;                EB  FD B1 7F 49 35 9E C0 95 39 EE 11 CD D2 30 A3   // ....I5...9....0.&lt;br /&gt;                 72 D3 A0 72 DD 10 42 86 EA 59 60 AB 5F C4 3F 7F   // r..r..B..Y`._.?.&lt;br /&gt;                 09 A7 6C 5E FA D0 54 FF B9 B7 12 C6 13 DD 6D C3   //  ..l^..T.......m.&lt;br /&gt;                D3 5B E4 90 76 EC CC 92 CD B0 7E 9B 22 A5 A4  71   // .[..v.....~."..q&lt;br /&gt;                D0 EA 1A EE 0D 6B BE 82 55 D6 7E B2  7F B1 32 DB   // .....k..U.~...2.&lt;br /&gt;                50 5B F7 50 07 19 91 59 22  BF FB 82 A9 0B F7 DE   // P[.P...Y".......&lt;br /&gt;                87 36 F9 6C 19 CA  D9 63 55 63 78 44 C6 33 6C 55   // .6.l...cUcxD.3lU&lt;br /&gt;                39 00 7B  0A 89 8E C2 C5 8E 4A 52 C2 8E 23 37 B3 ) // 9.{......JR..#7.&lt;br /&gt;  .hash  algorithm 0x00008004&lt;br /&gt;&lt;br /&gt;  还在想什么呢？直接删除呀，嘿嘿&lt;img alt="" src="http://www.unpack.cn/images/smilies/default/icon8.gif" border="0" smilieid="8" /&gt;&lt;br /&gt;&lt;br /&gt;  4. 到现在破解就完工了，可以编译新的程序了。ilasm /dll /resource=aaa.res  aaa.il，得到的aaa.dll即为完美破解版了。&lt;br /&gt;&lt;br /&gt;  顺便说一句,使用的时候,最好先安装原版,再把破解版覆盖,就好了&lt;br /&gt;  如果感觉好用,请支持正版&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-2066095334086889205?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/2066095334086889205/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=2066095334086889205' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/2066095334086889205'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/2066095334086889205'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/09/flytreeview-v43143.html' title='FlyTreeView V4.3.1.43破解手记'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-1596301453692042360</id><published>2008-09-15T08:40:00.000+08:00</published><updated>2008-09-15T08:41:33.946+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='compileMethod'/><title type='text'>hook compileMethod的几种常见形式</title><content type='html'>&lt;div class="tit"&gt;&lt;span class="Apple-style-span" style="color: rgb(85, 26, 139); text-decoration: underline;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;table style="TABLE-LAYOUT: fixed"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;div class="cnt"&gt;&lt;div class="Section0" style="LAYOUT-GRID:  15.6pt none"&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;compileMethod&lt;span style="font-family:宋体;"&gt;算是.NET中的万能断点，对付一般的.NET加密壳均可采用hook  compileMethod的方式得到IL代码和相关信息，保护层次较深的.NET壳除外。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;我们自己在编写程序hook该方法时，一般有以下几种形式。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;第一种形式是&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;：my_compileMethod（既需要替换的方法）&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;采用compileMethod的原型&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;。这种形式代码漂亮，结构工整，编程方便，推荐使用。通常&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;代码可以如下定义：&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;int __stdcall  my_compileMethod(ULONG_PTR classthis, &lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;                                                      ICorJitInfo *comp,&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;                                                      CORINFO_METHOD_INFO *info, &lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;                                                       unsigned flags,&lt;/span&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;BYTE **nativeEntry,  &lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;                                                      ULONG   *nativeSizeOfCode)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;//&lt;span style="font-family:宋体;"&gt;你的代码&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;//&lt;span style="font-family:宋体;"&gt;调用原始的compileMethod&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;int nRet =  compileMethod(classthis, comp, info, flags, nativeEntry,  nativeSizeOfCode);&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;return  nRet;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="color:#0000ff;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;上面的代码还有一个优点，就是&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;可直接兼容x64位&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;     第二种形式：naked&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;。既调用约定不采用__stdcall，而是用naked。代码如下：&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;void  __declspec(naked) mycompileMethod()&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;//&lt;span style="font-family:宋体;"&gt;你的代码&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="color:#0000ff;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;这种形式明显低级一些，许多工作要自己做，比如取&lt;/span&gt;&lt;/span&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;CORINFO_METHOD_INFO *&lt;/span&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;时，就要从堆栈中取值：&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;__asm&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;{&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;pushad&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;pushfd&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;mov eax,DWORD  PTR[esp+48]&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;push  eax&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="color:#0000ff;"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;pop  pmethodinfo&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="color:#0000ff;"&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;还有就是，直接使用x86汇编代码则无法兼容x64，需编写两套程序。当然，也不是一点好处没有，比如很多hook程序在开始喜欢保存全部的寄存器和状态，这里就可以使用pushad和pushfd了。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;上面两种方法，在具体hook时，通常采取替换CILJit::'vtable'的第一项： dd offset  CILJit::compileMethod的地址实现。该值可以通过getJit()函数获得。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;&lt;span style="font-family:宋体;"&gt;第三种方法就更直接了，在JIT的路径中找到合适的位置后，直接Jmp。这种naked+jmp的方式，最底层，也最灵活，在对于某些hook位置较深的壳来说，这也是唯一的方法。不过代码编写时，工作量就比前两种要稍大一些了。&lt;/span&gt;&lt;/span&gt;&lt;/p&gt; &lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span style="FONT-SIZE: 10.5pt; mso-spacerun: yes"&gt;Btw&lt;span style="font-family:宋体;"&gt;：在编写.NET内核hook程序时，C++/CLI是不二之选。真得很爽！&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span class="Apple-style-span" style="font-family: 宋体; font-size: 14px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt;&lt;p class="p0" style="MARGIN-TOP: 0pt; MARGIN-BOTTOM: 0pt; TEXT-INDENT: 21pt"&gt;&lt;span class="Apple-style-span" style="font-family: 宋体; font-size: 14px;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;    compileMethod方法在各类.NET内核的文章中出现频率相当高，因为它是JIT引擎工作的关键函数。其原型如下（参考sscli代码）：&lt;/p&gt; &lt;div style="MARGIN: 5px 20px 20px"&gt; &lt;div class="smallfont" style="MARGIN-BOTTOM: 2px"&gt;代码:&lt;/div&gt;&lt;pre dir="ltr" style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 5px; BORDER-TOP: 1px inset; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 640px; PADDING-TOP: 5px; BORDER-BOTTOM: 1px inset; BACKGROUND-COLOR: #dedfdf; TEXT-ALIGN: left"&gt;&lt;span style="color:#0000ff;"&gt;CorJitResult __stdcall FJitCompiler::compileMethod (                ICorJitInfo*                  compHnd,               /* IN */                CORINFO_METHOD_INFO*           info,                  /* IN */                unsigned                   flags,                 /* IN */                BYTE **                    entryAddress,          /* OUT */                ULONG     *                   nativeSizeOfCode       /* OUT */                )&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;      一般的用法是通过该函数的第二个参数COFINFO_METHOD_INFO取得代码的IL和大小。但其实还可以更加深入，注意第一个传入参数很有意思，指向了ICorJitInfo接口。该接口定义如下：&lt;br /&gt;&lt;div style="MARGIN: 5px 20px 20px"&gt; &lt;div class="smallfont" style="MARGIN-BOTTOM: 2px"&gt;代码:&lt;/div&gt;&lt;pre dir="ltr" style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 5px; BORDER-TOP: 1px inset; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 640px; PADDING-TOP: 5px; BORDER-BOTTOM: 1px inset; BACKGROUND-COLOR: #dedfdf; TEXT-ALIGN: left"&gt;&lt;span style="color:#0000ff;"&gt;/*********************************************************************************  * a ICorJitInfo is the main interface that the JIT uses to call back to the EE and  *      get information  *********************************************************************************/ class ICorJitInfo : public virtual ICorDynamicInfo {//省略}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;     这说明ICorJitInfo继承了ICorDynamicInfo接口。而后者的定义如下：&lt;br /&gt;&lt;div style="MARGIN: 5px 20px 20px"&gt; &lt;div class="smallfont" style="MARGIN-BOTTOM: 2px"&gt;代码:&lt;/div&gt;&lt;pre dir="ltr" style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 5px; BORDER-TOP: 1px inset; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 640px; PADDING-TOP: 5px; BORDER-BOTTOM: 1px inset; BACKGROUND-COLOR: #dedfdf; TEXT-ALIGN: left"&gt;&lt;span style="color:#0000ff;"&gt;/*****************************************************************************  * ICorDynamicInfo contains EE interface methods which return values that may  * change from invocation to invocation.     They cannot be embedded in persisted  * data; they must be requeried each time the EE is run.  *****************************************************************************/  class ICorDynamicInfo : public virtual ICorStaticInfo {//省略}&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;      这说明ICorDynamicInfo又继承了ICorStaticInfo。接着来，继续看ICorStaticInfo的代码：&lt;br /&gt;&lt;br /&gt;&lt;div style="MARGIN: 5px 20px 20px"&gt; &lt;div class="smallfont" style="MARGIN-BOTTOM: 2px"&gt;代码:&lt;/div&gt;&lt;pre dir="ltr" style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 5px; BORDER-TOP: 1px inset; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 640px; PADDING-TOP: 5px; BORDER-BOTTOM: 1px inset; BACKGROUND-COLOR: #dedfdf; TEXT-ALIGN: left"&gt;&lt;span style="color:#0000ff;"&gt;/*****************************************************************************  * ICorStaticInfo contains EE interface methods which return values that are  * constant from invocation to invocation.     Thus they may be embedded in  * persisted information like statically generated code. (This is of course  * assuming that all code versions are identical each time.)  *****************************************************************************/ class ICorStaticInfo : public virtual ICorMethodInfo, public virtual ICorModuleInfo,                           public virtual ICorClassInfo,     public virtual ICorFieldInfo,                           public virtual ICorDebugInfo,     public virtual ICorArgInfo,                           public virtual ICorLinkInfo,      public virtual ICorErrorInfo&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;      这一次牛了，ICorStaticInfo继承了8个接口的方法，其中第一个为ICorMethodInfo。该接口定义了许多与方法相关的函数，如果能调用它，在hook中是非常爽的。那可不可以调用呢？当然可以，compileMethod的第一个参数就是我们需要的。&lt;br /&gt;      比如我们需要取得当前hook方法的方法名，可以调用ICorMethodInfo中的如下方法：&lt;br /&gt;&lt;div style="MARGIN: 5px 20px 20px"&gt; &lt;div class="smallfont" style="MARGIN-BOTTOM: 2px"&gt;代码:&lt;/div&gt;&lt;pre dir="ltr" style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 5px; BORDER-TOP: 1px inset; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 640px; PADDING-TOP: 5px; BORDER-BOTTOM: 1px inset; BACKGROUND-COLOR: #dedfdf; TEXT-ALIGN: left"&gt;&lt;span style="color:#0000ff;"&gt;       virtual const char* __stdcall getMethodName (                CORINFO_METHOD_HANDLE          ftn,           /* IN */                const char                   **moduleName     /* OUT */                ) = 0;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;      这里需要传入CORINFO_METHOD_HANDLE这个参数，该参数是.NET内核中表示方法的核心结构，在sscli中也未公开。不过它的值是可以取得的，从compileMethod第二个参数CORINFO_METHOD_INFO结构的第一项中便可以取得：&lt;br /&gt;&lt;div style="MARGIN: 5px 20px 20px"&gt; &lt;div class="smallfont" style="MARGIN-BOTTOM: 2px"&gt;代码:&lt;/div&gt;&lt;pre dir="ltr" style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 5px; BORDER-TOP: 1px inset; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 640px; PADDING-TOP: 5px; BORDER-BOTTOM: 1px inset; BACKGROUND-COLOR: #dedfdf; TEXT-ALIGN: left"&gt;&lt;span style="color:#0000ff;"&gt;struct CORINFO_METHOD_INFO {     &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&lt;strong&gt;CORINFO_METHOD_HANDLE          ftn;        CORINFO_MODULE_HANDLE          scope;&lt;/strong&gt;               BYTE *                         ILCode;        unsigned                       ILCodeSize;        unsigned short                 maxStack;        unsigned short                 EHcount;        CorInfoOptions                 options;        CORINFO_SIG_INFO               args;        CORINFO_SIG_INFO               locals; };&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;      同样，在调用ICorModuleInfor接口中的许多方法时，也需要传入CORINFO_MODULE_HANDLE作为参数，同样可以从CORINFO_METHOD_INFO结构中获得该值。比如调用findClass函数，以取得CORINFO_CLASS_HANDLE，定义如下：&lt;br /&gt;&lt;div style="MARGIN: 5px 20px 20px"&gt; &lt;div class="smallfont" style="MARGIN-BOTTOM: 2px"&gt;代码:&lt;/div&gt;&lt;pre dir="ltr" style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 5px; BORDER-TOP: 1px inset; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 640px; PADDING-TOP: 5px; BORDER-BOTTOM: 1px inset; BACKGROUND-COLOR: #dedfdf; TEXT-ALIGN: left"&gt;&lt;span style="color:#0000ff;"&gt;       virtual CORINFO_CLASS_HANDLE __stdcall findClass (                CORINFO_MODULE_HANDLE          module,        /* IN     */                unsigned                       metaTOK,       /* IN     */                CORINFO_CONTEXT_HANDLE         context,       /* IN     */                CorInfoTokenKind               tokenKind = CORINFO_TOKENKIND_Default /* IN     */                ) = 0;&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;      其中出现了CORINFO_CONTEXT_HANDLE。该结构也非常容易取得，具体参考sscli，就不详述了。&lt;br /&gt;      具体在VS中编程时，可以添加corinfo.h和corjit.h，并在同一目录下添加corhdr.h，便可顺利编译通过。&lt;br /&gt;      最后还有一个问题，sscli毕竟是早期框架了，还是精简版，现在还能直接使用吗？不妨分析一下。随便运行一个.NET程序，用WinDbg调试并中断在compileMethod处，查看ICorJitInfo值所指的内存：&lt;br /&gt;&lt;div style="MARGIN: 5px 20px 20px"&gt; &lt;div class="smallfont" style="MARGIN-BOTTOM: 2px"&gt;代码:&lt;/div&gt;&lt;pre dir="ltr" style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 5px; BORDER-TOP: 1px inset; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 640px; PADDING-TOP: 5px; BORDER-BOTTOM: 1px inset; BACKGROUND-COLOR: #dedfdf; TEXT-ALIGN: left"&gt;&lt;span style="color:#0000ff;"&gt;0012ea38 79f10654 mscorwks!CEEJitInfo::`vbtable' 0012ea3c 00174d18  0012ea40 00997850  0012ea44 00107210  0012ea48 00000000  0012ea4c 0018a610  0012ea50 00000000  0012ea54 00000000  0012ea58 00000000  0012ea5c 0012ea40  0012ea60 00000000  0012ea64 00000000  0012ea68 00000000  0012ea6c 79f105b8 mscorwks!CEEJitInfo::`vftable' 0012ea70 00000000  0012ea74 79f10584 mscorwks!CEEJitInfo::`vftable' 0012ea78 00000000  0012ea7c 79f104e0 mscorwks!CEEJitInfo::`vftable' 0012ea80 00000000  0012ea84 79f104bc mscorwks!CEEJitInfo::`vftable' 0012ea88 00000000  0012ea8c 79f104a4 mscorwks!CEEJitInfo::`vftable' 0012ea90 00000000  0012ea94 79f10498 mscorwks!CEEJitInfo::`vftable' 0012ea98 00000000  0012ea9c 79f10494 mscorwks!CEEJitInfo::`vftable' ...//下略&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;      这里又涉及到VC编译器对类的vftable和vbtable在内存中的布局问题了，最先两项是类自身定义的虚方法表和虚基址表，相关资料请自己查阅。我们跟进vftable：&lt;br /&gt;&lt;div style="MARGIN: 5px 20px 20px"&gt; &lt;div class="smallfont" style="MARGIN-BOTTOM: 2px"&gt;代码:&lt;/div&gt;&lt;pre dir="ltr" style="BORDER-RIGHT: 1px inset; PADDING-RIGHT: 5px; BORDER-TOP: 1px inset; PADDING-LEFT: 5px; PADDING-BOTTOM: 5px; MARGIN: 0px; OVERFLOW: auto; BORDER-LEFT: 1px inset; WIDTH: 640px; PADDING-TOP: 5px; BORDER-BOTTOM: 1px inset; BACKGROUND-COLOR: #dedfdf; TEXT-ALIGN: left"&gt;&lt;span style="color:#0000ff;"&gt;79f10624 79f106ac mscorwks!CEEJitInfo::getMemoryManager 79f10628 79f11d82 mscorwks!CEEJitInfo::allocMem 79f1062c 79f11f39 mscorwks!CEEJitInfo::allocGCInfo 79f10630 7a12b8cb mscorwks!CEEJitInfo::getEHInfo 79f10634 7a12b6cf mscorwks!CEEJitInfo::yieldExecution 79f10638 79f16373 mscorwks!CEEJitInfo::setEHcount 79f1063c 79f16491 mscorwks!CEEJitInfo::setEHinfo 79f10640 7a12ed41 mscorwks!CEEJitInfo::logMsg 79f10644 7a27ffcc mscorwks!ZapperModule::doAssert 79f10648 7a12eeb6 mscorwks!CEEJitInfo::allocBBProfileBuffer 79f1064c 7a2c2fa1 mscorwks!MDInternalRO::ConvertTextSigToComSig 79f10650 79f0efee mscorwks!CEEJitInfo::isVerifyOnly 79f10654 fffffffc&lt;/span&gt;&lt;/pre&gt;&lt;/div&gt;        这些地址在静态编译时就已经确定了，因此如果用IDA反编译mscorwks.dll，同样会得到这些值。这便是最新的.NET框架内核中ICorJitInfo定义的方法。和sscli对比下（在corjit.h文件中），完全一样！（也可以再对比其它关键接口的方法，应该也是一样，我没有详细对比了。）&lt;br /&gt;      这样，我们就得到如下的结论：.NET内核框架从2.0开始，内核变化不大，包括sscli的内核代码，这些可以从内部函数的定义看出来；通过hook  compileMethod，可以得到ICorJitInfo等关键接口，并调用其中的许多内部方法；具体编写时，可以在VS中引入sscli的corinfo.h、corjit.h和corhdr.h等文件，之后便可以直接调用。因此，通过compileMethod，我们可以做的事很多很多，远不限于仅获得某个方法的IL。&lt;br /&gt;&lt;p&gt;&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-1596301453692042360?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/1596301453692042360/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=1596301453692042360' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/1596301453692042360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/1596301453692042360'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/09/hook-compilemethod.html' title='hook compileMethod的几种常见形式'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-3738414711314140154</id><published>2008-09-15T08:28:00.002+08:00</published><updated>2008-09-15T08:29:15.632+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Net 2.0 、泛型'/><title type='text'>Net 2.0 的泛型小结</title><content type='html'>微软在.Net FrameWork 2.0中，引入了范型，相比.Net FrameWork 1.1中的三个集合类。&lt;br /&gt;范型具有类型安全、无需GC的优点，对值类型无需进行性能损失很大的装箱与拆箱操作。&lt;br /&gt;主要看 System.Collections.Generic 命名空间，略作总结：&lt;br /&gt;ArrayList --&gt; List&lt;t&gt;&lt;br /&gt;Hashtable --&gt; Dictionary&lt;tkey,&gt;&lt;br /&gt;SortedList --&gt; SortedDictionary&lt;tkey,&gt;&lt;br /&gt;Stack --&gt; Stack&lt;t&gt;&lt;br /&gt;Queue --&gt; Queue&lt;t&gt;&lt;br /&gt;LinkedList&lt;t&gt; 无对应类&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-3738414711314140154?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/3738414711314140154/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=3738414711314140154' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3738414711314140154'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3738414711314140154'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/09/net-20.html' title='Net 2.0 的泛型小结'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-3427974964518414685</id><published>2008-09-15T08:24:00.000+08:00</published><updated>2008-09-15T08:25:50.041+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Reflactor、反编译、.Net'/><title type='text'>使用Reflactor反编译.Net程序的经验</title><content type='html'>相信大多数.Net程序员都有使用Reflactor的经历。无论出于什么目的，当用Reflactor反编译托管程序后，还想对其代码加以修改，那么本文所列举的可能是一份有用的参考。&lt;br /&gt;&lt;br /&gt;用Reflactor的FileGenerator插件反编译代码后可以得到包括项目文件的源代码，但代码中存在各种问题，一般无法一次编译通过，以下将详谈这些问题：&lt;br /&gt;枚举问题&lt;br /&gt;&lt;br /&gt;为了代码可读，可能需要花点时间查阅metadata把int值修改回枚举值，尤其是想利用窗体设计器的，VS2008可能还不理解int值。&lt;br /&gt;属性问题&lt;br /&gt;&lt;br /&gt;比如一个叫Names的属性被反编译后，可能还原为的set_Names(names)，get_Names()方法，逐个替换可能很慢，可采用正则表达式整体替换。对于set_Xxx(xxx)方法，可替换set_{[a-z]*}\(为\1 = (对于get_Xxx()方法，可替换get_{[a-z]*}\(\)为\1然后，再修复个别被误换的方法。&lt;br /&gt;委托和回调函数问题&lt;br /&gt;&lt;br /&gt;一般会被还原为add_Xxx(MethodsName)方法，需要改为 += MethodsName&lt;br /&gt;资源问题&lt;br /&gt;&lt;br /&gt;需要使用.Net Framework SDK 下的 resgen.exe 工具，反编译嵌入资源文件*.resources为*.resx文件，语法为：ResGen.exe *.resources *.resx，然后将*.resx包含入项目，就会自动和同名的窗体文件*.cs关联，如果没有关联可采用先排除再添加大法，一一搞定。&lt;br /&gt;命名空间问题&lt;br /&gt;&lt;br /&gt;如果需要切换到IDE的窗体设计器，而不出错，则还需要在*.cs中添加比如System.Windows.Forms的命名空间前缀。&lt;br /&gt;窗体设计器识别问题&lt;br /&gt;&lt;br /&gt;需要把以下代码ComponentResourceManager manager = new ComponentResourceManager(typeof(ClassName));替换为System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ClassName));窗体设计器才能正常识别。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-3427974964518414685?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/3427974964518414685/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=3427974964518414685' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3427974964518414685'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3427974964518414685'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/09/reflactornet.html' title='使用Reflactor反编译.Net程序的经验'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-3657943901152765758</id><published>2008-06-29T20:40:00.001+08:00</published><updated>2008-06-29T20:40:16.873+08:00</updated><title type='text'>windows2003 免费杀毒软件</title><content type='html'>AntiVir Personal Edition 中文名叫&amp;quot;小红伞&amp;quot;，是一款相当优秀的免费杀毒软件，主要特色是系统资源占用很少，内存占用很低，杀毒能力不一般。在系统资源占用上只有NOD32能与其匹敌，但NOD32在木马查杀方面却很弱。我在使用了Avira+LNS（一款防火墙）后电脑几乎没有中过毒。主要缺点是有时会有误杀现象，不过，现在这种现象越来越少。07年4月份，小红伞升级版本，不支持windows 2003 操作系统，但通过以下设 &lt;br&gt;置我们发现可以实现完美安装。&lt;p&gt;&lt;p&gt;第一种方法：下载 AntiVir Personal Edition  老版－07年以前的版本，安装后，下载 &lt;br&gt; AntiVir Personal Edition 最新版本（Avira AntiVir PersonalEdition Classic &lt;br&gt;Windows 2000 / XP / Vista 32 Bit and 64 Bit），覆盖安装即可。&lt;p&gt;第二种方法：下载AntiVir Personal Edition  老版，安装后到这里下载License file（授权文件）－这是小红伞的官方网站。下载后可将该文件直接放到Avira Antivir 的安装目录下。重新启动，升级病毒库 &lt;br&gt;后，你就会发现你的小红伞已经更新到最新版了。&lt;p&gt;下面的图片是我的windows 2003中Avira Antivir 所占的内存，你看是不是很省内存？&lt;p&gt;&lt;p&gt;当然，你一切安装完毕后，需要对它进行一下设置。下载这个德国小红伞设置图，参照设置一下就可以了&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-3657943901152765758?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/3657943901152765758/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=3657943901152765758' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3657943901152765758'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3657943901152765758'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/06/windows2003.html' title='windows2003 免费杀毒软件'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-3319310642454531535</id><published>2008-05-21T17:13:00.001+08:00</published><updated>2008-05-21T17:13:32.719+08:00</updated><title type='text'>EXcel多表之间操作(VBA)</title><content type='html'>&lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;"from [产品资料$] a,[进货$] b,[销售$] c where a.产品代码=b.产品代码   and a.产品代码=c.产品代码"&lt;BR&gt;'[a65536].End(xlUp).Offset(1, 0).CopyFromRecordset   conn.Execute(Sql)&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;Sub 汇总()&lt;BR&gt;Range("A2:J100").ClearContents&lt;BR&gt;Set conn   = CreateObject("adodb.connection")&lt;BR&gt;conn.Open   "provider=microsoft.jet.oledb.4.0;extended properties=excel 8.0;data source="   &amp;amp; ThisWorkbook.FullName&lt;BR&gt;Sql = "select   A.产品代码,A.名称,sum(B.进货数量),B.进货单价,sum(B.进货金额),sum(C.销售数量),C.销售单价,sum(C.销售金额),sum(C.销售数量)*(C.销售单价-B.进货单价),sum(B.进货数量)-sum(C.销售数量)   from [产品资料$] as A,[进货$] as B,[销售$] as C where A.产品代码=B.产品代码 and B.产品代码=C.产品代码   group by A.产品代码,A.名称,B.进货单价,C.销售单价"&lt;BR&gt;Sheet2.[a2].CopyFromRecordset   conn.Execute(Sql)&lt;BR&gt;conn.Close&lt;BR&gt;Set conn = Nothing&lt;BR&gt;End Sub&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-3319310642454531535?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/3319310642454531535/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=3319310642454531535' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3319310642454531535'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3319310642454531535'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/05/excelvba.html' title='EXcel多表之间操作(VBA)'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-3332064082584758657</id><published>2008-05-21T13:50:00.001+08:00</published><updated>2008-05-21T13:50:43.934+08:00</updated><title type='text'>Excel表格下面的SQL对比</title><content type='html'>&lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;在excel工具--宏下面--VBA然后在模块中加入模块1，然后显示窗体设计器下面加入一个按钮&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;Sub 查询()&lt;BR&gt;&amp;nbsp; Dim MYSTR As String&lt;BR&gt;&amp;nbsp;&amp;nbsp;   Range("A2:AT1500").ClearContents&lt;BR&gt;&amp;nbsp;&amp;nbsp; Set CONN =   CreateObject("adodb.connection")&lt;BR&gt;&amp;nbsp;&amp;nbsp; CONN.Open   "provider=microsoft.jet.oledb.4.0;extended properties=excel 8.0;data source="   &amp;amp; ThisWorkbook.FullName&lt;BR&gt;&amp;nbsp; ' For I = 1 To Sheets.Count -   2&lt;BR&gt;&amp;nbsp;&amp;nbsp; '&amp;nbsp;&amp;nbsp;&amp;nbsp; sq1 = sq1 &amp;amp; "select * from [" &amp;amp;   Sheets(I).Name &amp;amp; "$] where 工资级别='6级'" &amp;amp; " UNION "&lt;BR&gt;&amp;nbsp; ' Next   I&lt;BR&gt;&amp;nbsp; ' sq1 = Left(sq1, Len(sq1) - 7)&lt;BR&gt;&amp;nbsp; Sq1 = "select * from ["   &amp;amp; Sheets(2).Name &amp;amp; "$] where 监管条件 like '%/B'&amp;nbsp; and b2 not in (select   b2 from [" &amp;amp; Sheets(1).Name &amp;amp; "$])"&lt;BR&gt;&amp;nbsp; [a2].CopyFromRecordset   CONN.Execute(Sq1)&lt;BR&gt;&amp;nbsp; CONN.Close&lt;BR&gt;&amp;nbsp; Set CONN = Nothing&lt;BR&gt;&amp;nbsp;End   Sub&lt;BR&gt;&lt;/DIV&gt;&lt;/FONT&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-3332064082584758657?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/3332064082584758657/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=3332064082584758657' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3332064082584758657'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3332064082584758657'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/05/excelsql.html' title='Excel表格下面的SQL对比'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-3744114158079006777</id><published>2008-05-20T09:32:00.001+08:00</published><updated>2008-05-20T09:32:13.976+08:00</updated><title type='text'>C#--事件教程</title><content type='html'>&lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&lt;BR&gt;本教程展示如何在 C# 中声明事件、调用事件和挂接到事件。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;C#   中的"事件"是当对象发生某些有趣的事情时，类向该类的客户提供通知的一种方法。事件最常见的用途是用于图形用户界面；通常，表示界面中的控件的类具有一些事件，当用户对控件进行某些操作（如单击某个按钮）时，将通知这些事件。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;但是事件未必只用于图形界面。事件为对象提供一种通常很有用的方法来发出信号表示状态更改，这些状态更改可能对该对象的客户很有用。事件是创建类的重要构造块，这些类可在大量的不同程序中重复使用。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;使用委托来声明事件。如果您尚未学习"委托教程"，您应先学习它，然后再继续。请回忆委托对象封装一个方法，以便可以匿名调用该方法。事件是类允许客户为其提供方法（事件发生时应调用这些方法）的委托的一种方法。事件发生时，将调用其客户提供给它的委托。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;除声明事件、调用事件和与事件挂钩的示例以外，本教程还介绍下列主题：&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;事件和继承 &lt;BR&gt;接口中的事件 &lt;BR&gt;.NET Framework 指南 &lt;BR&gt;示例   1&lt;BR&gt;下面的简单示例展示一个 ListWithChangedEvent 类，该类类似于标准的 ArrayList 类，而且，每当列表内容更改时，该类均调用   Changed 事件。这样一个通用用途的类可在大型程序中以多种方式使用。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;例如，某字处理器可能包含打开的文档的列表。每当该列表更改时，可能需要通知字处理器中的许多不同对象，以便能够更新用户界面。使用事件，维护文档列表的代码不需要知道需要通知谁，一旦文档列表发生了更改，将自动调用该事件，正确通知每个需要通知的对象。使用事件提高了程序的模块化程度。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;// events1.cs&lt;BR&gt;using System;&lt;BR&gt;namespace   MyCollections &lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; using System.Collections;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; // A delegate type for hooking up change   notifications.&lt;BR&gt;&amp;nbsp;&amp;nbsp; public delegate void ChangedEventHandler(object   sender, EventArgs e);&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; // A class that works just like   ArrayList, but sends event&lt;BR&gt;&amp;nbsp;&amp;nbsp; // notifications whenever the list   changes.&lt;BR&gt;&amp;nbsp;&amp;nbsp; public class ListWithChangedEvent: ArrayList   &lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // An event that clients   can use to be notified whenever the&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //   elements of the list change.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public event   ChangedEventHandler Changed;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Invoke the Changed   event; called whenever list changes&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected   virtual void OnChanged(EventArgs e) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Changed !=   null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   Changed(this, e);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Override some of the   methods that can change the list;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // invoke   event after each&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override int   Add(object value) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int i =   base.Add(value);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   OnChanged(EventArgs.Empty);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   return i;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void   Clear() &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   base.Clear();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   OnChanged(EventArgs.Empty);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override object   this[int index] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   base[index] =   value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   OnChanged(EventArgs.Empty);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;namespace TestEvents &lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; using   MyCollections;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; class EventListener &lt;BR&gt;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private ListWithChangedEvent   List;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public   EventListener(ListWithChangedEvent list) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List =   list;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Add "ListChanged"   to the Changed event on   "List".&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List.Changed += new   ChangedEventHandler(ListChanged);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // This will be called   whenever the list changes.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private void   ListChanged(object sender, EventArgs e) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("This is   called when the event fires.");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Detach()   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Detach the event and   delete the list&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List.Changed   -= new   ChangedEventHandler(ListChanged);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   List = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; class Test &lt;BR&gt;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Test the ListWithChangedEvent   class.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void Main()   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create   a new list.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ListWithChangedEvent list = new   ListWithChangedEvent();&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create a class that   listens to the list's change event.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   EventListener listener = new EventListener(list);&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Add and remove items   from the list.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; list.Add("item   1");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   list.Clear();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   listener.Detach();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;   }&lt;BR&gt;}输出&lt;BR&gt;This is called when the event fires.&lt;BR&gt;This is called when the   event fires.代码讨论&lt;BR&gt;声明事件&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   若要在类内声明事件，首先必须声明该事件的委托类型（如果尚未声明的话）。 &lt;BR&gt;&amp;nbsp;&amp;nbsp; public delegate void   ChangedEventHandler(object sender, EventArgs e);&lt;BR&gt;&amp;nbsp;&amp;nbsp;   委托类型定义传递给处理该事件的方法的一组参数。&lt;BR&gt;&amp;nbsp;&amp;nbsp;   多个事件可共享相同的委托类型，因此仅当尚未声明任何合适的委托类型时才需要执行该步骤。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;接下来，声明事件本身。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public event   ChangedEventHandler Changed;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   声明事件的方法与声明委托类型的字段类似，只是关键字 event   在事件声明前面，在修饰符后面。&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   事件通常被声明为公共事件，但允许任意可访问修饰符。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;调用事件&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   类声明了事件以后，可以就像处理所指示的委托类型的字段那样处理该事件。&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   如果没有任何客户将委托与该事件挂钩，该字段将为空；否则该字段引用应在调用该事件时调用的委托。&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   因此，调用事件时通常先检查是否为空，然后再调用事件。 &lt;BR&gt;&amp;nbsp;if (Changed != null)&lt;BR&gt;&amp;nbsp;Changed(this,   e);调用事件只能从声明该事件的类内进行。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;与事件挂钩&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;从声明事件的类外看，事件像个字段，但对该字段的访问是非常受限制的。只可进行如下操作： &lt;BR&gt;&amp;nbsp;在该字段上撰写新的委托。   &lt;BR&gt;&amp;nbsp;从字段（可能是复合字段）移除委托。 &lt;BR&gt;&amp;nbsp;使用 += 和 -=   运算符完成此操作。为开始接收事件调用，客户代码先创建事件类型的委托，&lt;BR&gt;&amp;nbsp;该委托引用应从事件调用的方法。然后它使用 +=   将该委托写到事件可能连接到的其他任何委托上。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;// Add "ListChanged" to the Changed event on   "List":&lt;BR&gt;&amp;nbsp;List.Changed += new   ChangedEventHandler(ListChanged);&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&amp;nbsp;当客户代码完成接收事件调用后，它将使用运算符 -=   从事件移除其委托。&lt;BR&gt;&amp;nbsp;// Detach the event and delete the   list:&lt;BR&gt;&amp;nbsp;List.Changed -= new   ChangedEventHandler(ListChanged);&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;事件和继承&lt;BR&gt;&amp;nbsp;当创建可以从中派生的通用组件时，事件中有时出现似乎会成为问题的情况。由于事件只能从声明它们的类中调用，&lt;BR&gt;&amp;nbsp;因此派生类不能直接调用在基类内声明的事件。虽然这有时符合需要，但通常使派生类能够自由调用事件更合适。&lt;BR&gt;&amp;nbsp;这通常通过为事件创建受保护的调用方法来实现。通过调用该调用方法，派生类便可以调用此事件。&lt;BR&gt;&amp;nbsp;为获得更大的灵活性，调用方法通常声明为虚拟的，这允许派生类重写调用方法。&lt;BR&gt;&amp;nbsp;这使得派生类可以截获基类正在调用的事件，有可能对这些事件执行它自己的处理。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;在前面的示例中，这已用 OnChanged   方法实现。如果需要，派生类可调用或重写该方法。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;接口中的事件&lt;BR&gt;事件和字段之间的另一个差异是，事件可放在接口中，而字段不能。当实现接口时，实现类必须在实现接口的类中提供相应的事件。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;.NET Framework 指南&lt;BR&gt;尽管 C# 语言允许事件使用任意委托类型，但".NET   Framework"对于应为事件使用的委托类型有一些更严格的指南。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;如果打算将您的组件与".NET   Framework"一起使用，您可能希望遵守这些指南。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;".NET   Framework"指南指示用于事件的委托类型应采用两个参数：指示事件源的"对象源"参数和封装事件的其他任何相关信息的"e"参数。&lt;BR&gt;"e"参数的类型应从   EventArgs 类派生。对于不使用其他任何信息的事件，".NET   Framework"已定义了一个适当的委托类型：EventHandler。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;示例 2&lt;BR&gt;下面的示例是"示例 1"的修改版本，它遵守".NET Framework"指南。该示例使用   EventHandler 委托类型。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;// events2.cs&lt;BR&gt;using System;&lt;BR&gt;namespace   MyCollections &lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; using System.Collections;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; // A class that works just like   ArrayList, but sends event&lt;BR&gt;&amp;nbsp;&amp;nbsp; // notifications whenever the list   changes:&lt;BR&gt;&amp;nbsp;&amp;nbsp; public class ListWithChangedEvent: ArrayList   &lt;BR&gt;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // An event that clients   can use to be notified whenever the&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //   elements of the list change:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public event   EventHandler Changed;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Invoke the Changed   event; called whenever list changes:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; protected   virtual void OnChanged(EventArgs e) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (Changed !=   null)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   Changed(this,e);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Override some of the   methods that can change the list;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // invoke   event after each:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override int   Add(object value) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int i =   base.Add(value);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   OnChanged(EventArgs.Empty);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   return i;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override void   Clear() &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   base.Clear();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   OnChanged(EventArgs.Empty);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public override object   this[int index] &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; set   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   base[index] =   value;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   OnChanged(EventArgs.Empty);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;namespace TestEvents &lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; using   MyCollections;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; class EventListener &lt;BR&gt;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private ListWithChangedEvent   List;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public   EventListener(ListWithChangedEvent list) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List =   list;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Add "ListChanged"   to the Changed event on   "List":&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; List.Changed += new   EventHandler(ListChanged);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // This will be called   whenever the list changes:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private void   ListChanged(object sender, EventArgs e) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("This is   called when the event fires.");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void Detach()   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Detach the event and   delete the list:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   List.Changed -= new   EventHandler(ListChanged);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   List = null;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; class Test &lt;BR&gt;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Test the ListWithChangedEvent   class:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void Main()   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create   a new list:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ListWithChangedEvent list = new   ListWithChangedEvent();&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create a class that   listens to the list's change event:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   EventListener listener = new EventListener(list);&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Add and remove items   from the list:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; list.Add("item   1");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   list.Clear();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   listener.Detach();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;   }&lt;BR&gt;}输出&lt;BR&gt;This is called when the event fires.&lt;BR&gt;This is called when the   event fires.&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-3744114158079006777?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/3744114158079006777/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=3744114158079006777' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3744114158079006777'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/3744114158079006777'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/05/c_20.html' title='C#--事件教程'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-2847610224231392427</id><published>2008-05-20T08:35:00.001+08:00</published><updated>2008-05-20T08:35:29.532+08:00</updated><title type='text'>C#--委托教程</title><content type='html'>&lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;&amp;nbsp;本教程演示委托类型。它说明如何将委托映射到静态方法和实例方法，以及如何组合委托（多路广播）。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;C# 中的委托类似于 C 或 C++   中的函数指针。使用委托使程序员可以将方法引用封装在委托对象内。然后可以将该委托对象传递给可调用所引用方法的代码，而不必在编译时知道将调用哪个方法。与 C 或   C++ 中的函数指针不同，委托是面向对象、类型安全的，并且是安全的。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;委托声明定义一种类型，它用一组特定的参数以及返回类型封装方法。对于静态方法，委托对象封装要调用的方法。对于实例方法，委托对象同时封装一个实例和该实例上的一个方法。如果您有一个委托对象和一组适当的参数，则可以用这些参数调用该委托。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;委托的一个有趣且有用的属性是，它不知道或不关心自己引用的对象的类。任何对象都可以；只是方法的参数类型和返回类型必须与委托的参数类型和返回类型相匹配。这使得委托完全适合"匿名"调用。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;注意&amp;nbsp;&amp;nbsp;   委托是在调用方的安全权限下运行而不是声明方的权限下运行。&lt;BR&gt;此教程包括两个示例：&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;示例 1 展示如何声明、实例化和调用委托。 &lt;BR&gt;示例 2 展示如何组合两个委托。   &lt;BR&gt;此外，还讨论以下主题：&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;委托和事件 &lt;BR&gt;委托与接口 &lt;BR&gt;示例 1&lt;BR&gt;下面的示例阐释声明、实例化和使用委托。BookDB   类封装一个书店数据库，它维护一个书籍数据库。它公开 ProcessPaperbackBooks   方法，该方法在数据库中查找所有平装书，并为每本书调用一个委托。所使用的 delegate 类型称为 ProcessBookDelegate。Test   类使用该类输出平装书的书名和平均价格。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;委托的使用促进了书店数据库和客户代码之间功能的良好分隔。客户代码不知道书籍的存储方式和书店代码查找平装书的方式。书店代码也不知道找到平装书后将对平装书进行什么处理。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;// bookstore.cs&lt;BR&gt;using System;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;// A set of classes for handling a   bookstore:&lt;BR&gt;namespace Bookstore d&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; using   System.Collections;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; // Describes a book in the book   list:&lt;BR&gt;&amp;nbsp;&amp;nbsp; public struct Book&lt;BR&gt;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string   Title;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Title of the   book.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string   Author;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Author of the   book.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public decimal   Price;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Price of the   book.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public bool   Paperback;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Is it paperback?&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Book(string   title, string author, decimal price, bool   paperBack)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Title =   title;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Author =   author;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Price =   price;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Paperback =   paperBack;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; // Declare a delegate type for processing   a book:&lt;BR&gt;&amp;nbsp;&amp;nbsp; public delegate void ProcessBookDelegate(Book   book);&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; // Maintains a book   database.&lt;BR&gt;&amp;nbsp;&amp;nbsp; public class BookDB&lt;BR&gt;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // List of all books in the   database:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ArrayList list = new   ArrayList();&amp;nbsp; &lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Add a book to the   database:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void AddBook(string title,   string author, decimal price, bool paperBack)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; list.Add(new Book(title,   author, price, paperBack));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Call a passed-in   delegate on each paperback book to process it:   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public void   ProcessPaperbackBooks(ProcessBookDelegate   processBook)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; foreach (Book b in list)   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if   (b.Paperback)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   // Calling the   delegate:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   processBook(b);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   }&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;// Using the Bookstore classes:&lt;BR&gt;namespace   BookTestClient&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp; using Bookstore;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; // Class to total and average prices of   books:&lt;BR&gt;&amp;nbsp;&amp;nbsp; class PriceTotaller&lt;BR&gt;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; int countBooks =   0;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; decimal priceBooks = 0.0m;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal void   AddBookToTotal(Book book)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; countBooks +=   1;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; priceBooks +=   book.Price;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; internal decimal   AveragePrice()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return priceBooks /   countBooks;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp; // Class to test the book   database:&lt;BR&gt;&amp;nbsp;&amp;nbsp; class Test&lt;BR&gt;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Print the title of the   book.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void PrintTitle(Book   b)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   Console.WriteLine("&amp;nbsp;&amp;nbsp; {0}",   b.Title);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Execution starts   here.&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void   Main()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; BookDB bookDB = new   BookDB();&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //   Initialize the database with some   books:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   AddBooks(bookDB);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //   Print all the titles of   paperbacks:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   Console.WriteLine("Paperback Book   Titles:");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create a new   delegate object associated with the static   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // method   Test.PrintTitle:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   bookDB.ProcessPaperbackBooks(new ProcessBookDelegate(PrintTitle));&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //   Get the average price of a paperback by   using&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // a PriceTotaller   object:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; PriceTotaller   totaller = new   PriceTotaller();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create a   new delegate object associated with the nonstatic   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // method AddBookToTotal on   the object totaller:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   bookDB.ProcessPaperbackBooks(new   ProcessBookDelegate(totaller.AddBookToTotal));&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   Console.WriteLine("Average Paperback Book Price:   ${0:#.##}",&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   totaller.AveragePrice());&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Initialize the book   database with some test books:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; static void   AddBooks(BookDB bookDB)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bookDB.AddBook("The C   Programming Language",   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Brian W.   Kernighan and Dennis M. Ritchie", 19.95m,   true);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bookDB.AddBook("The   Unicode Standard 2.0",   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "The   Unicode Consortium", 39.95m,   true);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bookDB.AddBook("The   MS-DOS Encyclopedia",   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Ray   Duncan", 129.95m, false);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   bookDB.AddBook("Dogbert's Clues for the Clueless",   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; "Scott   Adams", 12.00m, true);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;   }&lt;BR&gt;}输出&lt;BR&gt;Paperback Book Titles:&lt;BR&gt;&amp;nbsp;&amp;nbsp; The C Programming   Language&lt;BR&gt;&amp;nbsp;&amp;nbsp; The Unicode Standard 2.0&lt;BR&gt;&amp;nbsp;&amp;nbsp; Dogbert's   Clues for the Clueless&lt;BR&gt;Average Paperback Book Price:   $23.97代码讨论&lt;BR&gt;声明委托&amp;nbsp;&amp;nbsp; 以下语句： &lt;BR&gt;public delegate void   ProcessBookDelegate(Book   book);声明一个新的委托类型。每个委托类型都描述参数的数目和类型，以及它可以封装的方法的返回值类型。&lt;BR&gt;每当需要一组新的参数类型或新的返回值类型时，都必须声明一个新的委托类型。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;实例化委托&amp;nbsp;&amp;nbsp;   声明了委托类型后，必须创建委托对象并使之与特定方法关联。与所有其他对象类似，新的委托对象用 new 表达式创建。但是当创建委托时，传递给 new   表达式的参数很特殊：它的编写类似于方法调用，但没有方法的参数。 &lt;BR&gt;下列语句：&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;bookDB.ProcessPaperbackBooks(new   ProcessBookDelegate(PrintTitle));创建与静态方法 Test.PrintTitle   关联的新的委托对象。下列语句：&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;bookDB.ProcessPaperbackBooks(new &lt;BR&gt;&amp;nbsp;&amp;nbsp;   ProcessBookDelegate(totaller.AddBookToTotal));创建与对象 totaller 上的非静态方法   AddBookToTotal 关联的新的委托对象。在两个例子中，新的委托对象都立即传递给 ProcessPaperbackBooks   方法。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;请注意一旦创建了委托，它所关联到的方法便永不改变：委托对象不可改变。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;调用委托&amp;nbsp;&amp;nbsp;   创建委托对象后，通常将委托对象传递给将调用该委托的其他代码。通过委托对象的名称（后面跟着要传递给委托的参数，括在括号内）调用委托对象。下面是委托调用的示例：   &lt;BR&gt;processBook(b);在此示例中，可以通过使用 BeginInvoke 和 EndInvoke   方法同步或异步调用委托。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;示例   2&lt;BR&gt;本示例演示组合委托。委托对象的一个有用属性是，它们可以"+"运算符来组合。组合的委托可调用组成它的那两个委托。只有相同类型的委托才可以组合。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;"-"运算符可用来从组合的委托移除组件委托。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;// compose.cs&lt;BR&gt;using System;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;delegate void MyDelegate(string s);&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;class MyClass&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static   void Hello(string s)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Console.WriteLine("&amp;nbsp; Hello,   {0}!", s);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void Goodbye(string   s)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   Console.WriteLine("&amp;nbsp; Goodbye, {0}!", s);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   }&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public static void   Main()&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   MyDelegate a, b, c, d;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create   the delegate object a that references   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // the method   Hello:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a = new   MyDelegate(Hello);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Create the   delegate object b that references &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   // the method Goodbye:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; b = new   MyDelegate(Goodbye);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // The two   delegates, a and b, are composed to form c:   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; c = a +   b;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Remove a from the composed   delegate, leaving d, &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // which   calls only the method Goodbye:&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; d =   c - a;&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   Console.WriteLine("Invoking delegate   a:");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   a("A");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   Console.WriteLine("Invoking delegate   b:");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   b("B");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   Console.WriteLine("Invoking delegate   c:");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   c("C");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   Console.WriteLine("Invoking delegate   d:");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;   d("D");&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}输出&lt;BR&gt;Invoking delegate a:&lt;BR&gt;&amp;nbsp; Hello,   A!&lt;BR&gt;Invoking delegate b:&lt;BR&gt;&amp;nbsp; Goodbye, B!&lt;BR&gt;Invoking delegate   c:&lt;BR&gt;&amp;nbsp; Hello, C!&lt;BR&gt;&amp;nbsp; Goodbye, C!&lt;BR&gt;Invoking delegate d:&lt;BR&gt;&amp;nbsp;   Goodbye,   D!委托和事件&lt;BR&gt;委托非常适合于用作事件（从一个组件就该组件中的更改通知"侦听器"）。有关将委托用于事件的更多信息，请参见事件教程。&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;委托与接口&lt;BR&gt;委托和接口的类似之处是，它们都允许分隔规范和实现。多个独立的作者可以生成与一个接口规范兼容的多个实现。类似地，委托指定方法的签名，多个作者可以编写与委托规范兼容的多个方法。何时应使用接口，而何时应使用委托呢？&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;委托在以下情况下很有用：&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;调用单个方法。 &lt;BR&gt;一个类可能希望有方法规范的多个实现。 &lt;BR&gt;希望允许使用静态方法实现规范。   &lt;BR&gt;希望类似事件的设计模式（有关更多信息，请参见事件教程）。 &lt;BR&gt;调用方不需要知道或获得在其上定义方法的对象。   &lt;BR&gt;实现的提供程序希望只对少数选择组件"分发"规范实现。 &lt;BR&gt;需要方便的组合。 &lt;BR&gt;接口在以下情况下很有用：&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;规范定义将调用的一组相关方法。 &lt;BR&gt;类通常只实现规范一次。   &lt;BR&gt;接口的调用方希望转换为接口类型或从接口类型转换，以获得其他接口或类。 &lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-2847610224231392427?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/2847610224231392427/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=2847610224231392427' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/2847610224231392427'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/2847610224231392427'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/05/c.html' title='C#--委托教程'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-291856052962836485</id><published>2008-05-20T08:20:00.001+08:00</published><updated>2008-05-20T08:20:33.196+08:00</updated><title type='text'>P903 X500 重启</title><content type='html'>&lt;DIV&gt;&lt;FONT face=宋体   size=2&gt;P903硬启的方式和其他PPC手机相比较为"独特"，需要用户同时按下开关以及RESET键，然后同时松开，再按下"挂断键"约5秒左右，屏幕便会提示询问是否清除本机内存，接下来要在倒计时结束时按住左软键不放，直到屏幕提示"yes"，便可以硬启手机.&lt;/FONT&gt;&lt;/DIV&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-291856052962836485?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/291856052962836485/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=291856052962836485' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/291856052962836485'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/291856052962836485'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/05/p903-x500.html' title='P903 X500 重启'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-5841936754543238463</id><published>2008-05-16T23:42:00.001+08:00</published><updated>2008-05-16T23:42:57.664+08:00</updated><title type='text'>3DES加解密</title><content type='html'>&lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&lt;FONT size=3&gt;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;summary&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;3des加密字符串&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;/summary&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;param&amp;nbsp;&amp;nbsp;&amp;nbsp;name="a_strString"&amp;gt;要加密的字符串   &amp;lt;/param&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;param&amp;nbsp;&amp;nbsp;&amp;nbsp;name="a_strKey"&amp;gt;密钥   &amp;lt;/param&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;returns&amp;gt;加密后并经base64编码的字符串 &amp;lt;/returns&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;remarks&amp;gt;静态方法，采用默认ascii编码 &amp;lt;/remarks&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;static&amp;nbsp;string&amp;nbsp;Encrypt3DES(string&amp;nbsp;a_strString,&amp;nbsp;string&amp;nbsp;a_strKey)   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TripleDESCryptoServiceProvider&amp;nbsp;DES&amp;nbsp;=&amp;nbsp;new&amp;nbsp;TripleDESCryptoServiceProvider();   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MD5CryptoServiceProvider&amp;nbsp;hashMD5&amp;nbsp;=&amp;nbsp;new&amp;nbsp;MD5CryptoServiceProvider();   &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DES.Key&amp;nbsp;=&amp;nbsp;hashMD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(a_strKey));   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DES.Mode&amp;nbsp;=&amp;nbsp;CipherMode.ECB;   &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ICryptoTransform&amp;nbsp;DESEncrypt&amp;nbsp;=&amp;nbsp;DES.CreateEncryptor();   &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;byte[]&amp;nbsp;Buffer&amp;nbsp;=&amp;nbsp;ASCIIEncoding.ASCII.GetBytes(a_strString);   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;Convert.ToBase64String(DESEncrypt.TransformFinalBlock(Buffer,&amp;nbsp;0,&amp;nbsp;Buffer.Length));   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}//end&amp;nbsp;&amp;nbsp;&amp;nbsp;method&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&lt;BR&gt;///&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;summary&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;3des解密字符串&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;/summary&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;param&amp;nbsp;&amp;nbsp;&amp;nbsp;name="a_strString"&amp;gt;要解密的字符串   &amp;lt;/param&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;param&amp;nbsp;&amp;nbsp;&amp;nbsp;name="a_strKey"&amp;gt;密钥   &amp;lt;/param&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;returns&amp;gt;解密后的字符串 &amp;lt;/returns&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;exception&amp;nbsp;&amp;nbsp;&amp;nbsp;cref=""&amp;gt;密钥错误   &amp;lt;/exception&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;///&amp;nbsp;&amp;nbsp;&amp;nbsp;   &amp;lt;remarks&amp;gt;静态方法，采用默认ascii编码 &amp;lt;/remarks&amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;public&amp;nbsp;static&amp;nbsp;string&amp;nbsp;Decrypt3DES(string&amp;nbsp;a_strString,&amp;nbsp;string&amp;nbsp;a_strKey)   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TripleDESCryptoServiceProvider&amp;nbsp;DES&amp;nbsp;=&amp;nbsp;new   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;TripleDESCryptoServiceProvider();   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MD5CryptoServiceProvider&amp;nbsp;hashMD5&amp;nbsp;=&amp;nbsp;new&amp;nbsp;MD5CryptoServiceProvider();   &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DES.Key&amp;nbsp;=&amp;nbsp;hashMD5.ComputeHash(ASCIIEncoding.ASCII.GetBytes(a_strKey));   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DES.Mode&amp;nbsp;=&amp;nbsp;CipherMode.ECB;   &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ICryptoTransform&amp;nbsp;DESDecrypt&amp;nbsp;=&amp;nbsp;DES.CreateDecryptor();   &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string&amp;nbsp;result&amp;nbsp;=&amp;nbsp;"";   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;byte[]&amp;nbsp;Buffer&amp;nbsp;=&amp;nbsp;Convert.FromBase64String(a_strString);   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;result&amp;nbsp;=&amp;nbsp;ASCIIEncoding.ASCII.GetString(DESDecrypt.TransformFinalBlock(Buffer,&amp;nbsp;0,&amp;nbsp;Buffer.Length));   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;catch&amp;nbsp;(Exception&amp;nbsp;e)   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw&amp;nbsp;(new&amp;nbsp;Exception("不是有效的&amp;nbsp;base64&amp;nbsp;&amp;nbsp;字符串",&amp;nbsp;e));   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}   &lt;BR&gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;result;   &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}//end&amp;nbsp;&amp;nbsp;&amp;nbsp;method&amp;nbsp;&amp;nbsp;&amp;nbsp;   &lt;/FONT&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/DIV&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-5841936754543238463?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/5841936754543238463/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=5841936754543238463' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5841936754543238463'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/5841936754543238463'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/05/3des.html' title='3DES加解密'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-1367053782206527505</id><published>2008-05-08T10:51:00.001+08:00</published><updated>2008-05-08T10:51:28.113+08:00</updated><title type='text'>down oracle patch</title><content type='html'>&lt;H2&gt;需要oracle补丁的请进来，oracle 补丁下载新方法。&lt;/H2&gt;  &lt;DIV class=t_msgfont id=postmessage_1005329&gt;使用迅雷新建任务下载地址填写 &lt;BR&gt;&lt;A   href="ftp://updates.oracle.com/"   target=_blank&gt;ftp://updates.oracle.com/&lt;/A&gt;&amp;lt;patch_num&amp;gt;/p&amp;lt;patch_num&amp;gt;_&amp;lt;version&amp;gt;_&amp;lt;os&amp;gt;.zip&lt;BR&gt;就可以下载到你想要的补丁了。&lt;BR&gt;&lt;BR&gt;以下是几个常用补丁的下载地址。&lt;BR&gt;(10.2.0.3   patch)&lt;BR&gt;&lt;A   title="ftp://updates.oracle.com/5337014/p5337014_10203_WINNT.zip&amp;#10;CTRL + 单击以下链接"   href="ftp://updates.oracle.com/5337014/p5337014_10203_WINNT.zip"   target=_blank&gt;ftp://updates.oracle.com/5337014/p5337014_10203_WINNT.zip&lt;/A&gt; &lt;A   href="ftp://updates.oracle.com/5337014/p5337014_10203_LINUX.zip"   target=_blank&gt;ftp://updates.oracle.com/5337014/p5337014_10203_LINUX.zip&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;oracle   9.2.0.8&lt;BR&gt;&lt;BR&gt;&lt;A   href="ftp://updates.oracle.com/4547809/p4547809_92080_WINNT.zip"   target=_blank&gt;ftp://updates.oracle.com/4547809/p4547809_92080_WINNT.zip&lt;/A&gt;&lt;BR&gt;&lt;A   href="ftp://updates.oracle.com/4547809/p4547809_92080_LINUX.zip"   target=_blank&gt;ftp://updates.oracle.com/4547809/p4547809_92080_LINUX.zip&lt;/A&gt;&lt;BR&gt;&lt;BR&gt;oracle   9.2.0.6&lt;BR&gt;&lt;A href="ftp://updates.oracle.com/3948480/p3948480_9206_WINNT.zip"   target=_blank&gt;ftp://updates.oracle.com/3948480/p3948480_9206_WINNT.zip&lt;/A&gt;&lt;BR&gt;&lt;A   href="ftp://updates.oracle.com/3948480/p3948480_9206_LINUX.zip"   target=_blank&gt;ftp://updates.oracle.com/3948480/p3948480_9206_LINUX.zip&lt;/A&gt;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-1367053782206527505?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/1367053782206527505/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=1367053782206527505' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/1367053782206527505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/1367053782206527505'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/05/down-oracle-patch.html' title='down oracle patch'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-1492917099069055848</id><published>2008-05-08T10:46:00.001+08:00</published><updated>2008-05-08T10:46:20.828+08:00</updated><title type='text'>oracle patchset</title><content type='html'>&lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;  &lt;DIV class=storyTitle&gt;Tips--Oacle 9i Database 所有大版本补丁集列表 &lt;/DIV&gt;  &lt;DIV class=noDisplay&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV   class=storytext&gt;有朋友问到补丁集的号是多少，个人通常都是用FTP来download补丁集，这里也顺便记录一下9i的所有补丁集的号。方便自己和需要的朋友查看：&lt;BR&gt;&lt;FONT   size=2&gt;4547809 Oracle PATCH SET FOR DATABASE SERVER 9.2.0.8 25-AUG-2006   &lt;BR&gt;4163445 Oracle PATCH SET FOR DATABASE SERVER 9.2.0.7 23-SEP-2005 &lt;BR&gt;3948480   Oracle PATCH SET FOR DATABASE SERVER 9.2.0.6 13-DEC-2004 &lt;BR&gt;3501955 Oracle   PATCH SET FOR DATABASE SERVER 9.2.0.5 26-MAR-2004 &lt;BR&gt;3301544 Oracle PATCH SET   FOR DATABASE SERVER 9.0.1.5 08-JAN-2004 &lt;BR&gt;3095277 Oracle PATCH SET FOR   DATABASE SERVER 9.2.0.4 05-SEP-2003 &lt;BR&gt;2761332 Oracle PATCH SET FOR DATABASE   SERVER 9.2.0.3 03-APR-2003 &lt;BR&gt;2632931 Oracle PATCH SET FOR DATABASE SERVER   9.2.0.2 13-NOV-2002 &lt;BR&gt;2517300 Oracle PATCH SET FOR DATABASE SERVER 9.0.1.4   17-AUG-2002 &lt;BR&gt;2271678 Oracle PATCH SET FOR DATA SERVER 9.0.1.3 19-MAR-2002   &lt;BR&gt;2072050 Oracle PATCH SET FOR DATA SERVER 9.0.1.2 15-NOV-2001 &lt;BR&gt;1968474   Oracle PATCH SET FOR DATA SERVER 9.0.1.1 12-SEP-2001 &lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV class=storytext&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV class=storytext&gt;  &lt;DIV class=storyTitle&gt;Tips--Oracle 8174的patch set还是可download &lt;/DIV&gt;  &lt;DIV class=noDisplay&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV class=storytext&gt;  &lt;P&gt;有很多的客户，还是跑在Oracle 8i上，所以它的patch备一份还是有必要的，要不然哪一天oracle不提供下载了，不知道到哪里找呢，patch   set number 是2376472&lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;  &lt;DIV class=storytext&gt;C:Documents and SettingsAdministrator&amp;gt;ftp   updates.oracle.com&lt;BR&gt;Connected to bigip-aru.oracle.com.&lt;BR&gt;220 FTP server   ready.&lt;BR&gt;User (bigip-aru.oracle.com:(none)): &lt;A   href="mailto:vongates@gmail.com"&gt;&lt;FONT color=#007799&gt;vongates&lt;/FONT&gt;&lt;/A&gt;&lt;BR&gt;331   Username OK, please send password.&lt;BR&gt;Password:&lt;BR&gt;230-&lt;BR&gt;230- Welcome to the   Oracle Patch Download FTP Server&lt;BR&gt;230-&lt;BR&gt;230- For detailed help, use command   "quote site help".&lt;BR&gt;230&lt;BR&gt;ftp&amp;gt; cd 2376472&lt;BR&gt;250 Changed directory   OK.&lt;BR&gt;ftp&amp;gt; ls&lt;BR&gt;200 PORT command OK.&lt;BR&gt;150 Opening data connection for   file listing.&lt;BR&gt;&lt;/DIV&gt;  &lt;DIV class=storytext&gt;  &lt;DIV class=storyTitle&gt;Tips--oracle 10g 所有大版本 patchset 列表（原） &lt;/DIV&gt;  &lt;DIV class=noDisplay&gt;&lt;BR&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV class=storytext&gt;今天有一兄弟问我10.1.0.3的patch set   number是多少。说实在的只是在10gR1刚出来的时候有自己测试过R1版本。后来没有怎么用过。现在用10gR2的比较多，接着2007OOW以后，大约在2007年的9月应该可以拿到11g的正式安装源CD吧。这里记录一下到现在的所有大的patchset   number供大家方便查看：&lt;BR&gt;  &lt;P&gt;5337014 Patchset 10.2.0.3 22-FEB-2007 &lt;BR&gt;4547817 Patchset 10.2.0.2   03-MAR-2006 &lt;BR&gt;4505133 Patchset 10.1.0.5 05-FEB-2006 &lt;BR&gt;4163362 Patchset   10.1.0.4 18-MAY-2005 &lt;BR&gt;3761843 Patchset 10.1.0.3 16-AUG-2004 &lt;/P&gt;&lt;/DIV&gt;&lt;/DIV&gt;  &lt;DIV class=storytext&gt;&amp;nbsp;&lt;/DIV&gt;&lt;/FONT&gt;&lt;/DIV&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-1492917099069055848?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/1492917099069055848/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=1492917099069055848' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/1492917099069055848'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/1492917099069055848'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/05/oracle-patchset.html' title='oracle patchset'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6939442.post-2276684239479595925</id><published>2008-05-08T08:17:00.001+08:00</published><updated>2008-05-08T08:17:58.562+08:00</updated><title type='text'>域策略设首页</title><content type='html'>&lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;开始---&amp;gt;管理工具--&amp;gt;active   directory用户和计算机--&amp;gt;选择域右键属性--&amp;gt;找到组策略tab－－》新建一个对像链接－－》打开后用户配置中windows设置－－》Internet   explorer 维护--&amp;gt;URL――――》重要URL打开就首页设置&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;然后在管理模板中--&amp;gt;windows组件--&amp;gt;Internet   Explorer--&amp;gt;禁用更改主页设置&lt;/FONT&gt;&lt;/DIV&gt;  &lt;DIV&gt;&lt;FONT face=宋体 size=2&gt;&lt;/FONT&gt;&amp;nbsp;&lt;/DIV&gt;  &lt;DIV&gt;原因：设置用户代理策略，不要设置计算机策略，这样当用户登录域时策略被应用，不登录域时，用本地帐户则不应用域策略。&lt;/DIV&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6939442-2276684239479595925?l=hzleihuan.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://hzleihuan.blogspot.com/feeds/2276684239479595925/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='https://www.blogger.com/comment.g?blogID=6939442&amp;postID=2276684239479595925' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/2276684239479595925'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6939442/posts/default/2276684239479595925'/><link rel='alternate' type='text/html' href='http://hzleihuan.blogspot.com/2008/05/blog-post.html' title='域策略设首页'/><author><name>天天</name><email>noreply@blogger.com</email><gd:extendedProperty xmlns:gd='http://schemas.google.com/g/2005' name='OpenSocialUserId' value='12423736904092573366'/></author><thr:total xmlns:thr='http://purl.org/syndication/thread/1.0'>0</thr:total></entry></feed>