<?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' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8705367749555657878</id><updated>2012-02-16T18:07:02.246+08:00</updated><category term='.Net/Windows Service'/><category term='.Net/C#'/><category term='笑口常开'/><category term='古诗词'/><category term='.Net/Remoting'/><category term='.Net/Win32'/><category term='诗词'/><category term='设计模式'/><category term='PPMM'/><category term='软件发布'/><category term='创新设计'/><category term='现代诗'/><category term='英文时事'/><category term='.Net/Asp'/><category term='心情日记'/><title type='text'>美人山下</title><subtitle type='html'>天作美人山,人以夜滨江.日行八万里,四年尤难断.古道松柏盛,潭依青麦园.除夕无雪月,桑麻就飞花.&lt;br/&gt;
旧城千年事,四年素还乡.佳朋不邀酒,各自为情长.鞭炮语渐浓,陋席话团圆.梦与君往事,泪容湿枕衫.&lt;br/&gt;
岁月有升浮,福禄寿平安!(春节)</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>93</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-4112891124545994194</id><published>2008-08-16T11:49:00.001+08:00</published><updated>2008-08-16T11:49:27.447+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='心情日记'/><title type='text'>周末闲谈：IT人的成长(职业规划？)</title><content type='html'>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 一般说来，到了周末我肯定周旋于“魔兽”、“将军”、“红警”之间的；可以说是无聊，也可以说是“泄愤”。我向来主张生活“有张有驰”，工作的时候用心，玩的时候用力。这周六我值班，我为奥运做贡献！&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; “好好活就是做有意义的事”，与其在各类八卦文章中度日，不如回顾一年前的自己，对比现在的自己，想想未来的路，劝勉周围的同仁。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这是一个特殊的时代，我们一面拥有前所未有的繁荣，另一方面也面对历史所重复的压力：各阶层对平等的诉求，社会对和谐的企盼。更切近的说，那么多的年轻人，如何有个可赖以生活的职业，或者有个称心如意的归宿？&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们这行当比较庆幸，虽然经历过“网络泡沫”等诸多骇人的阶段，但大浪过后，多数的从业人员依旧比其他各行同龄人拿着更多的收入。IT工作者头上渐渐有了些光环，就如高干子弟一样；一个靠自己的能力、努力成为中产阶级，一个靠父辈的付出与优越的软硬环境成为弄潮儿。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们过多的关注了行业的佼佼者，而忽略了行业的底层，尤指那些收入勉强果腹的前辈。如今房价高起，大多数的年轻人完全依靠自己很难在大都市立足；一年的光景，不过换来大城市的一间厕所。很多人奴役自己，为地主、老财做牛做马。这些前辈，真的是在“果腹”，而全没有中高收入带来的快感。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 去年刚毕业的时候，我根本不知道什么叫“生活”：生活需要一个处所，一间让“她的父母”看得上的房，然后才能“生”、“活”。我只是憧憬我的职业，想着大有作为，想着入金如土。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 人在恋爱的时候往往就是这个状态，一副不食人间烟火的姿态，想着“他好我也好”；只在多次分手后才悟到：再心动的爱情，新鲜期过后也就过期。正如我一贯主张的，爱情的归宿是亲情，唯有亲情最值得人牵挂一生。与她不能建立亲情，如何共度“柴米油盐”？&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IT工作也是这样，不能寄期望于高收入、高自主甚至优越感；这些迟早会褪色。那么高的房价、教育、医疗开支，&lt;strong&gt;多数&lt;/strong&gt;的我们，所谓的“高收入”能折腾几次？软件创业是相对简单，但多少能成了气候？至于“优越感”，时间将淡化一切。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 初出茅庐的我们，有一颗悸动的心，就像读小学的时候老师问我们的愿望是什么，我们答“科学家、国家主席”。现在的自己，基本平滑了心里期望值。我定位自己是个普通的职员，有着一份较稳定的工作，我应该不辜负公司，不辜负父母，工作上多一些勤恳，待遇上少一些焦躁。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 但我有愿望。我希望自己将来能够成为一位“姐夫赵”般的人物，或者一位称职的中高层管理者。但这梦想又是那么的漫长。我只是工作了一年多，却好像在人间打拼了大半生。试想余下的三五年，甚至几个十年，我需要耗费多少次生命？最近的记忆总比较久的记忆来得清晰、拖沓。因此，我唯有“忍”与“熬”。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果你思考自己的成长，如果你为成长迷茫，我劝你跟我一样，毕竟我们是普通的就业人员，而不是早期自诩的“软件精英”，我们只有在普通的岗位有所起色，才能成为明日某个公司的栋梁；在考虑问题的时候，更多的考虑自身的不足。我要像郎闲平教授强调“信托责任”那样强调我们的“职业操守”，呵呵。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 身边的好多“牛人”进的比我晚，跳的却远在我之前；从前交往时，我崇拜他们，但如今想来，多了一些伤感，而不全是崇拜。不是所有人都能改变一个公司，就好像不是所有人都能实现他的政治抱负；然而&lt;strong&gt;频繁&lt;/strong&gt;换主，会恶坏我们的生存环境。你让后来人如何仿效？你让公司如何看待新人？&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 工龄太短，发表技术文章是让人笑话，只能谈感想，哈哈。&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-4112891124545994194?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/4112891124545994194/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=4112891124545994194&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4112891124545994194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4112891124545994194'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/08/it.html' title='周末闲谈：IT人的成长(职业规划？)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-8800705894347309119</id><published>2008-06-18T10:42:00.000+08:00</published><updated>2008-06-18T10:43:18.504+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='古诗词'/><category scheme='http://www.blogger.com/atom/ns#' term='诗词'/><title type='text'>采</title><content type='html'>&lt;p&gt;荒野一席花，&lt;/p&gt; &lt;p&gt;映日赛金芒。&lt;/p&gt; &lt;p&gt;洒籽风无意，&lt;/p&gt; &lt;p&gt;折枝人情长。&lt;/p&gt; &lt;p&gt;(2008端午节)&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-8800705894347309119?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/8800705894347309119/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=8800705894347309119&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/8800705894347309119'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/8800705894347309119'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/06/blog-post_18.html' title='采'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-2489263549586034487</id><published>2008-06-10T12:58:00.000+08:00</published><updated>2008-06-10T13:01:04.070+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='笑口常开'/><title type='text'>男人抱着女人睡，女人你要明白其中的道理</title><content type='html'>&lt;p&gt;（原文地址：&lt;a title="http://www.lqqm.net/Lqqm.NetAs7A1TpFJOMFSGJVFXFLISGPUQUTTLGYOVBCO_B/?t=1213073491" href="http://www.lqqm.net/Lqqm.NetAs7A1TpFJOMFSGJVFXFLISGPUQUTTLGYOVBCO_B/?t=1213073491"&gt;http://www.lqqm.net/Lqqm.NetAs7A1TpFJOMFSGJVFXFLISGPUQUTTLGYOVBCO_B/?t=1213073491&lt;/a&gt;）&lt;/p&gt; &lt;p&gt;(A)热恋的时候,男人抱着女人睡. &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; &lt;br&gt;　 当他们成为夫妻以后,有一天女人投诉:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;　「你晚上睡觉都没抱着我,这和我一个人睡有什么分别.」&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;　 男人说:「抱在一起,大家都睡不好,难道你不觉得吗?」&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;(B)某天,男人会突然在闹市中把女人抱起,走长长的一段路.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;　 女人笑说:「你疯了吗?快把我放下来,让人看到不好.」&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;　 男人说:「怕什么?我喜欢抱着你.」&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;　 若干年以后,女人在闹市中向男人撒娇:「抱我!」&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;　 男人说:「你疯了吗?」&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;(C)某天,女人跟男人说:「抱我!」&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;　 男人乖乖弯腰,把女人抱上床&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;　 若干年以后,女人跟男人说:「抱我上床!」&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;　 男人没好气的说:「你脚断了吗?」&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;(D)某天,男人向女人许诺:&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;　「即使你将来变成一个大肥婆,我也要天天抱你&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;&amp;nbsp;&amp;nbsp; &lt;br&gt;　 男人没好气地说:「你想压死我吗?」&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt; &lt;p&gt;很难相信,当天抱你和若干年之后不抱你的,竟是同一个男人&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;结婚后,他抱你,福气 !&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;若干年后 没抱你,正常 !&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;别介意 ! !&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;不过,无论如何,看完这文章,女人要谅解,男人要检讨! !&lt;/p&gt;  &lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-2489263549586034487?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/2489263549586034487/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=2489263549586034487&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/2489263549586034487'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/2489263549586034487'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/06/blog-post.html' title='男人抱着女人睡，女人你要明白其中的道理'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-2001532112266428293</id><published>2008-02-26T17:51:00.001+08:00</published><updated>2008-02-26T17:51:56.124+08:00</updated><title type='text'>预想《汉语考级卷子》zz</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;发信人: 小熊猫 (以德报怨，何以报德？), 信区: Joke &lt;br&gt;标 &amp;nbsp;题: 卷子zz &lt;br&gt;发信站: 两全其美网 (Sun Feb 24 20:28:49 2008), 本站(lqqm.net) &lt;br&gt;　　第一大题 &lt;br&gt;　　说明向导：在这一大题中，你将听到10个短对话。每个短对话结束后，将有一 &lt;br&gt;个关于这个短对话的提问。每个短对话和它的问题都将只读一遍。每个问题提出后 &lt;br&gt;都将有短暂的停顿。在停顿的时间中，你必须阅读四个标有a），B），C）和D）的 &lt;br&gt;选项，并决定哪个选项是最佳答案。然后在答题卡上相应的选项中央划一条横线。 &lt;br&gt;　　举例：你将会听到： &lt;br&gt;　　男：我们什么时候开始工作呢，珍妮？ &lt;br&gt;　　女：明天上午9点开始吧。但是我们必须抓紧时间，因为我们不得不在下午2点 &lt;br&gt;之前完成所有的工作。 &lt;br&gt;　　问：他俩可以工作多长时间？ &lt;br&gt;　　你将读到：a）2小时。 B）3小时。 &lt;br&gt;　　C）4小时。 D）5小时。 &lt;br&gt;　　从该对话中我们知道这两个人是在说他们将于上午9点开始工作并必须在下午2 &lt;br&gt;点完成。因此，D）“5小时”是最确切的答案。你应该在答题卡上选项D）的中央划 &lt;br&gt;一条横线。 &lt;br&gt;　　1.女：回来了？今天车子挤吗？ &lt;br&gt;　　男：还可以。第一站和我一起上来10个下去6个。第二站上来5个下去15个。 &lt;br&gt;　　第三站上来17个下去20个。第四站上来24个和我一起下去7个。 &lt;br&gt;　　问：这个男的一共坐了几站车？ &lt;br&gt;　　a）10站。 B）4站。 C）3站。 D）5站。 &lt;br&gt;　　2．男：来我老家开分基地吧，把农民都拉过来。 &lt;br&gt;　　女：哎，只能这样了。 &lt;br&gt;　　问：这个场景最可能发生在什么地方？ &lt;br&gt;　　a）小村落。 B）网吧。 C）农田里。 D）基地组织里。 &lt;br&gt;　　3．女：你知道吗？中国队昨天以6比0击败了韩国队！ &lt;br&gt;　　男：啊？真的吗？万岁！ &lt;br&gt;　　问：从这个对话中我们可以推断出什么？ &lt;br&gt;　　a）韩国队退步了。 B）中国队进步了。 C）这个女的很兴奋。 D）这个男的很 &lt;br&gt;好骗。 &lt;br&gt;　　4．男：对不起，我忘记做了。 &lt;br&gt;　　女：你有没有长脑子啊？怎么不会忘记吃饭呀？ &lt;br&gt;　　问：这个女的最可能是什么身份？ &lt;br&gt;　　a）中学教师。 B）博士生导师。 C）精神病患者。 D）机器狂人。 &lt;br&gt;　　5．女：这衣服好象太小了点啊？我还是去别处看看吧。 &lt;br&gt;　　男：不会啊小姐，我还没见过有人穿这身衣裳比你更美的呢！ &lt;br&gt;　　问：这个男的为何这样说？ &lt;br&gt;　　a）他是个色狼。 B）想追求这个女的。 C）睁着眼说瞎话。 D）他在说梦话。 &lt;br&gt;　　6．男：做我的女朋友吧，我会对你好的。 &lt;br&gt;　　女：其实你是个很不错的男孩，和我在一起只会糟蹋了你。 &lt;br&gt;　　问：这个女的这样说是什么意思？ &lt;br&gt;　　a）她觉得自己配不上他。 B）谦虚几句。 C）答非所问。 D）拒绝他。 &lt;br&gt;　　7．女：我这次英语6级答案对下来不算作文85分，不知道能不能过，担心死了 &lt;br&gt;。 &lt;br&gt;　　男：你。。。。。。 &lt;br&gt;　　问：为什么这个男的说不出话？ &lt;br&gt;　　a）他也不知道她能不能过。 B）他不忍心告诉她结果。 &lt;br&gt;　　C）他没听清楚她的话。 D）他准备扁她一顿。 &lt;br&gt;　　8．男：你们老师有没有划过什么翎子啦？ &lt;br&gt;　　女：没有啊，这次大家都死定了。 &lt;br&gt;　　问：从对话中我们可以看出什么？ &lt;br&gt;　　a）快考试了。 B）战争要爆发了。 C）地球要爆炸了。 D）老师不负责任。 &lt;br&gt;　　9．女：明天要交论文了，能借用一下你的电脑吗？ &lt;br&gt;　　男：你去问别人借吧，我的电脑连不上网。 &lt;br&gt;　　问：男的为什么让女的去问别人借电脑？ &lt;br&gt;　　a）他的Word是网络版的。 B）连不上网的电脑对写论文没有帮助。 &lt;br&gt;　　B）他很小气。 D）他的电脑坏了。 &lt;br&gt;　　10．男：待会儿你就坐在我边上，和我打手势就行了。 &lt;br&gt;　　女：不好吧，这样会不会太危险了？ &lt;br&gt;　　问：他们将要去做什么？ &lt;br&gt;　　a）学习打手语。 B）做警察卧底。 C）参加考试。 D）培养感情。 &lt;br&gt;　　（本大题共10分，一题1分） &lt;br&gt;　　第二大题：复式听写 &lt;br&gt;　　曾经有一份(S1)____的感情(S2)____我面前，我没有(S3)____，等我(S4)____ &lt;br&gt;的时候我才(S5)____莫及，人世间最 (S6)____的事(S7)____于此 &lt;br&gt;　　，如果上天(S8)______________________________，我会对那个女孩子(S9)__ &lt;br&gt;____________________________。如果非要(S10) &lt;br&gt;　　______________________________，我希望是……一万年！ &lt;br&gt;　　（本大题共10分，前面七空0.5分一个，后面三空一共6.5分） &lt;br&gt;　　第二部分：阅读理解（35分钟） &lt;br&gt;　　说明向导：在这一部分有4篇文章。在每篇文章后面有若干问题。每个问题都有 &lt;br&gt;四个选项并标有a），B），C）和D）。你应当选择最恰当的一个 &lt;br&gt;　　答案并在答题卡上相应的选项中央划一条横线。 &lt;br&gt;　　第一篇文章 &lt;br&gt;　　第21到25题将建立在下面这段文章中： &lt;br&gt;　　中国有一种植物叫葳蕤。 &lt;br&gt;　　从前有个人叫蔺芈。他想用一张罽子去捕一只鸩。不小心被葳蕤绊了一个跟头 &lt;br&gt;。他很踯蹰该不该再去捉。忽然他发现了一根扃,于是便用扃去打 &lt;br&gt;　　鸩,可是鸩飞走了。蔺芈气愤地说：“再抓到你就把你做成俎醢！” &lt;br&gt;　　虽然恨,但此时却没办法。于是蔺芈只好采了几根葳蕤回家了。 &lt;br&gt;　　21．葳蕤为什么要绊蔺芈？ &lt;br&gt;　　a）蔺芈犯贱。 &lt;br&gt;　　B）这是自然规律。 &lt;br&gt;　　C）蔺芈走路不小心。 &lt;br&gt;　　D）文章中没有给出。 &lt;br&gt;　　22．蔺芈为什么要捉鸩？ &lt;br&gt;　　a）想烤了吃。 &lt;br&gt;　　B）捉回来虐待。 &lt;br&gt;　　C）他爱上了鸩。 &lt;br&gt;　　D）文章中没有给出。 &lt;br&gt;　　23．从上下文来看，“踯蹰”（第二段第一行）的意思是__________。 &lt;br&gt;　　a）犹豫。 &lt;br&gt;　　B）磨蹭。 &lt;br&gt;　　C）故意拖延时间。 &lt;br&gt;　　D）痴呆。 &lt;br&gt;　　24．文章最后一段，为什么说蔺芈要“恨”？ &lt;br&gt;　　a）他没有捉到鸩。 &lt;br&gt;　　B）他被葳蕤绊了一个跟头。 &lt;br&gt;　　C）他没有用扃打到鸠。 &lt;br&gt;　　D）他怪自己不果断。 &lt;br&gt;　　25．请给这篇文章拟一个合适的题目。 &lt;br&gt;　　a）鸩的故事。 &lt;br&gt;　　B）白痴蔺芈。 &lt;br&gt;　　C）草本植物葳蕤。 &lt;br&gt;　　D）得不偿失。 &lt;br&gt;　　第二篇文章 &lt;br&gt;　　第26到30题将建立在下面这段文章中： &lt;br&gt;　　一天早上，晴空万里，小明一个人走在大街上，这时，一阵风吹了过来，树倒 &lt;br&gt;了，把走在路上的小明压死了。 &lt;br&gt;　　这是近年来发生的最惨痛的一次事故，足足有前年发生事故的6倍严重！但是这 &lt;br&gt;件事却一直没有得到有关方面的足够重视。一直到最近著名作家 &lt;br&gt;　　芭芭拉在她的新书中以一个女英雄设法救小明最终失败的方式记叙了这件惨案 &lt;br&gt;。 &lt;br&gt;　　人们终于认识到可以开始正视这件事了，当然不是用它与过去发生的事故去比 &lt;br&gt;较，而只是客观地去讲述这件事。 &lt;br&gt;　　26．小明是什么时候被压死的？ &lt;br&gt;　　a）树压在他身上的时候 &lt;br&gt;　　B）风吹过来的时候。 &lt;br&gt;　　C）一阵风把树吹倒的时候。 &lt;br&gt;　　D）天晴的时候。 &lt;br&gt;　　27．为什么说这次事故有前年发生的事故6倍严重？ &lt;br&gt;　　a）因为小明还只是个孩子。 &lt;br&gt;　　B）因为小明是活活被压死的。 &lt;br&gt;　　C）因为死伤人数最多。 &lt;br&gt;　　D）文章中没有给出。 &lt;br&gt;　　28．作家芭芭拉以怎样的方式记叙了这个故事？ &lt;br&gt;　　a）以非常细致的描写。 &lt;br&gt;　　B）以夸张的描写。 &lt;br&gt;　　C）以一个女英雄救人的方式。 &lt;br&gt;　　D）以传记的方式。 &lt;br&gt;　　29．我们可以从这篇文章推断出__________。 &lt;br&gt;　　a）人们感到拿这件事与以前的事比是不对的。 &lt;br&gt;　　B）人们对这件事的发生感到愧疚。 &lt;br&gt;　　C）人们开始正视这件事了。 &lt;br&gt;　　D）人们开始向小明表示哀悼了。 &lt;br&gt;　　30．从文章中来看，小明的真正死因是__________。 &lt;br&gt;　　a）有关方面不重视。 &lt;br&gt;　　B）被树压死。 &lt;br&gt;　　C）女英雄水平太次。 &lt;br&gt;　　D）小明太呆，这么大一棵树你不知道躲开呀？ &lt;br&gt;　　第三篇文章 &lt;br&gt;　　第31到35题将建立在下面这段文章中： &lt;br&gt;　　mm说：“我爱你。” &lt;br&gt;　　我脸红了,我不想害她：“我没钱,更没有房子和车。” mm盯着我的眼睛：“我 &lt;br&gt;知道。” “我的月薪只有一千五。” mm的目光仍然坚定无比： &lt;br&gt;　　“以后会多的。” 我用颤抖的双手拿出一支烟叼在嘴上：“我每天要抽一包烟 &lt;br&gt;,一喝酒就闹事。” mm笑了,“以后有我在,你放心。” 我的脊 &lt;br&gt;　　梁上冒起一阵寒意,结结巴巴地对她说：“其实……其实我很流氓……幼儿园就 &lt;br&gt;喜欢去女厕所,小学就没了初吻,中学就……” mm没等我说完就 &lt;br&gt;　　软在了我的怀里,声音细若蚊鸣：“早知道你好色,你老偷偷瞄我胸脯… …” &lt;br&gt;一股鼻血喷涌而出,我抱紧了mm,温热娇小的身体让我热血沸腾。 &lt;br&gt;　　这时我忽然想到了一件很重要的事情,我决定把这事告诉mm...... 五秒钟后mm &lt;br&gt;抬头问我：“真的？” 我悲愤地点点头。 &lt;br&gt;　　mm沉默片刻挣开我的怀抱抬手给了我一个耳光,她愤怒地朝我喊道：“你丫竟然 &lt;br&gt;没有英语四级证书！” &lt;br&gt;　　31．文章中的“mm”是指什么东西？ &lt;br&gt;　　a）老太婆。 &lt;br&gt;　　B）猫科动物的一种。 &lt;br&gt;　　C）女孩子。 &lt;br&gt;　　D）疯子。 &lt;br&gt;　　32．mm为什么要打人？ &lt;br&gt;　　a）因为不打白不打。 &lt;br&gt;　　B）因为她的男朋友没有四级证书。 &lt;br&gt;　　C）因为这种动物性情暴烈。 &lt;br&gt;　　D）因为她的男朋友欺骗她。 &lt;br&gt;　　33．从这篇文章中，我们可以推断出__________。 &lt;br&gt;　　a）见到mm这种东西应该离远点。 &lt;br&gt;　　B）骗人是没有好下场的。 &lt;br&gt;　　C）四级证书是非常重要的。 &lt;br&gt;　　D）拿不到四级证书就拿不到学位证书了。 &lt;br&gt;　　34．文中的男生为什么说那么贬低自己的话？ &lt;br&gt;　　a）他变态。 &lt;br&gt;　　B）他谦虚。 &lt;br&gt;　　C）他痴呆。 &lt;br&gt;　　D）他诚实。 &lt;br&gt;　　35．综观全文，这段文章的体裁应该是__________。 &lt;br&gt;　　a）小说。 &lt;br&gt;　　B）散文。 &lt;br&gt;　　C）诗歌。 &lt;br&gt;　　D）幽默。 &lt;br&gt;　　第四篇文章 &lt;br&gt;　　第36到40题将建立在下面这段文章中： &lt;br&gt;　　首先我声明，我不是什么英迷，但是你的帖子让我恶心，让我甚至宁可看那些 &lt;br&gt;没水平的唾骂，那些也许肤浅，也许单纯，甚至不讲道理的唾骂 &lt;br&gt;　　！ &lt;br&gt;　　你说你不希望那些人喜欢英格兰，请问你：你是什么东西？世界球迷协会理事 &lt;br&gt;？我还希望粱永祺不要嫁给小郑呢！你说什么“几年来我一直在 &lt;br&gt;　　讽刺英格兰，我等着有英迷能站出来对我进行反驳，然而到现在为止，对我的 &lt;br&gt;反驳除了粗话、骂娘以外，没有一个人能从足球的层面上分析与 &lt;br&gt;　　驳斥我”。天哪。。你在哪里等待？是在自己昏暗小屋的衣柜里等待呢？还是 &lt;br&gt;在遍布英格兰球迷甚至是英格兰足球流氓的街头等待？（我想你 &lt;br&gt;　　也没哪个胆量） &lt;br&gt;　　你居然用对法国两分钟连丢两球来做例，证明英格兰如何的无能。。。且不说 &lt;br&gt;英格兰现在是什么水平，单单看你能用这样一个偶然的结果来做 &lt;br&gt;　　例子，那么，你可以把全世界的球队都看成三流队伍！ &lt;br&gt;　　其实装内行不是你的错，但是跑这里来丢人就是你的不对了！ &lt;br&gt;　　36．从上下文看，“英迷”（第一段第一行）指的是__________。 &lt;br&gt;　　a）喜欢英俊潇洒的人。 &lt;br&gt;　　B）喜欢英格兰队的人。 &lt;br&gt;　　C）英格兰足球流氓。 &lt;br&gt;　　D）热爱英雄的人。 &lt;br&gt;　　37．从文章中我们可以推断，作者__________。 &lt;br&gt;　　a）是个“英迷”。 &lt;br&gt;　　B）崇拜法国队。 &lt;br&gt;　　C）喜欢粱永祺。 &lt;br&gt;　　D）讨厌小郑。 &lt;br&gt;　　38．文章第二段最后一句话是什么意思？ &lt;br&gt;　　a）作者喜欢他能加入英格兰足球流氓的行列。 &lt;br&gt;　　B）英格兰足球流氓善于等待。 &lt;br&gt;　　C）作者很有胆量。 &lt;br&gt;　　D）作者的一种挖苦和讽刺。 &lt;br&gt;　　39．作者认为对方究竟错在哪里？ &lt;br&gt;　　a）假装内行。 &lt;br&gt;　　B）乱举例子。 &lt;br&gt;　　C）跑出来丢人。 &lt;br&gt;　　D）发没水平的帖子。 &lt;br&gt;　　40．这段文章最有可能选自什么地方？ &lt;br&gt;　　a）《人民日报》评论员文章。 &lt;br&gt;　　B）金庸作品集。 &lt;br&gt;　　C）新浪网的体育BBS。 &lt;br&gt;　　D）白宫发言稿。 &lt;br&gt;　　（本大题共40分，一题一分） &lt;br&gt;　　第三部分：词汇（20分钟） &lt;br&gt;　　说明向导：这部分有30句未完成的句子。每句句子后面有四个分别标有a），B &lt;br&gt;），C）和D）的选项。请选择最佳的答案然后在答题卡上相应的 &lt;br&gt;　　选项中央划一条横线。 &lt;br&gt;　　41．我们下课后一起去_____电脑。 &lt;br&gt;　　a）打 B）操 C）干 D）搞 &lt;br&gt;　　42．他打_____他一巴掌。 &lt;br&gt;　　a） 上 B）过 C）了 D着 &lt;br&gt;　　43．我去见了网友，然而令我失望的是，她却是个_____。 &lt;br&gt;　　a）美女 B）恐龙 C）猩猩 D）长颈鹿 &lt;br&gt;　　44．齐达内_____又进球了。 &lt;br&gt;　　a）秃子 B）胖子 C）猴子 D）呆子 &lt;br&gt;　　45．你在干吗_____？ &lt;br&gt;　　a）呼 B）呀 C）呵 D）了 &lt;br&gt;　　46．这几天论坛上怎么没人来_____了？ &lt;br&gt;　　a）灭火 B）浇花 C）种田 D）灌水 &lt;br&gt;　　47．他说得太好了，大伙儿一起_____他啊！ &lt;br&gt;　　a）宰了 B）解决 C）顶死 D）弄死 &lt;br&gt;　　48．这篇文章写得很_____。 &lt;br&gt;　　a）次 B）幽雅 C）硬朗 D）苦闷 &lt;br&gt;　　49．这考试太难了，我们请个_____吧。 &lt;br&gt;　　a）剑士 B）枪手 C）狙击手 D）CS高手 &lt;br&gt;　　50．来我家，我俩_____FIFa。 &lt;br&gt;　　a）玩弄 B）游戏 C）对殴 D）单挑 &lt;br&gt;　　51．停车_____枫林晚，霜叶红于二月花。 &lt;br&gt;　　a）做爱 B）坐爱 C）喝酒 D）品茶 &lt;br&gt;　　52．他一天到晚就知道_____女人。 &lt;br&gt;　　a）浸 B）泡 C）浸泡 D）烘干 &lt;br&gt;　　53．他阅读居然得了40分，实在太_____了！ &lt;br&gt;　　a）英俊 B）帅呆 C）牛B D）变态 &lt;br&gt;　　54．你又被爆头了，真是个_____。 &lt;br&gt;　　a）龙虾 B）带鱼 C）黄鳝 D）菜鸟 &lt;br&gt;　　55．翠花，_____酸菜。 &lt;br&gt;　　a）上 B）下 C）左 D）右 &lt;br&gt;　　56．田野里到处都是_____。 &lt;br&gt;　　a）旺财 B）小强 C）胖墩 D）皮蛋 &lt;br&gt;　　57．60分万岁，多一分_____。 &lt;br&gt;　　a）也好 B）浪费 C）奢侈 D）万岁 &lt;br&gt;　　58．子曰：学而时习之，不亦_____乎。 &lt;br&gt;　　a）说 B）悦 C兑 D）免 &lt;br&gt;　　59．如果我有_____，我要叫他小叮当。 &lt;br&gt;　　a）阿拉蕾 B）机器猫 C）呼呼猪 D）蓝皮鼠 &lt;br&gt;　　60．我们都是_____球迷。 &lt;br&gt;　　a）榔头 B）钉子 C）铁杆 D）竹竿 &lt;br&gt;　　61．这么狡猾的人你还说他老实？他老实个_____！ &lt;br&gt;　　a）鱼 B）鸟 C）虫 D）草 &lt;br&gt;　　62．新东方的老师个个都是_____。 &lt;br&gt;　　a）秃驴 B）** C）牛人 D）老头 &lt;br&gt;　　63．女人是_____做的。 &lt;br&gt;　　a）水 B）冰 C）馒头 D）面粉 &lt;br&gt;　　64．我是一只来自北方的_____。 &lt;br&gt;　　a）猪 B）狼 C）羊 D）狗熊 &lt;br&gt;　　65．你_____什么呀？不就一次考得好吗？ &lt;br&gt;　　a）激动 B）拽 C）喊 D）疯 &lt;br&gt;　　66．用炮打他的_____。 &lt;br&gt;　　a）马 B）牛 C）羊 D）炉 &lt;br&gt;　　67．英语四、六级考试马上要_____啦。 &lt;br&gt;　　a）取消 B）实行 C）崩溃 D）改革 &lt;br&gt;　　68．更多选择更多欢笑，就在_____。 &lt;br&gt;　　a）肯德基 B）必胜客 C）麦当劳 D）塔克贝 &lt;br&gt;　　69．舒克舒克舒克舒克舒克舒克舒克舒克_____的舒克。 &lt;br&gt;　　a）尿床 B）偷东西 C）开飞机 D）扔炸弹 &lt;br&gt;　　70．将_____进行到底。 &lt;br&gt;　　a）作弊 B）爱情 C）比赛 D）革命 &lt;br&gt;　　（本大题共15分，一题0.5分） &lt;br&gt;　　第四部分：综合改错（15分钟） &lt;br&gt;　　说明向导：这部分中有一篇短文。在这篇短文中一共有10个错误，每个后面划 &lt;br&gt;横线的句子中有一个错误。你可以改一个词语，加一个词语或者 &lt;br&gt;　　删一个词语。如果你想改一个词语，把错误的那个词划去并把正确的写在横线 &lt;br&gt;上。如果你想加一个词语，在要加入处写一个插入记号（∧）并 &lt;br&gt;　　把要加的词语写在横线上。如果你想删去一个词语，划掉它并在横线上划一斜 &lt;br&gt;横即可。 &lt;br&gt;　　举例： &lt;br&gt;　　电视正在很快地成为我们这个期间的文学。 1. 时期 &lt;br&gt;　　许多有被用作文学这门学校的课程学习的观点 2. ---- &lt;br&gt;　　也同样适用于电视∧门学科的研究。 3. 这__ &lt;br&gt;　　近年来外国人学习汉语的热情不断增高， &lt;br&gt;　　但绝大多数人能够熟练掌握汉语。为了便于外 71. _____ &lt;br&gt;　　国人检测自己的汉语水平，现成立国家大学汉 &lt;br&gt;　　语四、六级考试委员会并设立着汉语四、六级 72. _____ &lt;br&gt;　　考试。该考试将要参照英语四、六级考试的形 73. _____ &lt;br&gt;　　式，各部分题型与其基本保持一致。考生报名 &lt;br&gt;　　参加或通过者将授予证书，证书上贴有防伪标 74. _____ &lt;br&gt;　　志，任何个人和单位不得仿冒，违者不究其法 75. _____ &lt;br&gt;　　律责任。另外，考生报名需持本人无效证件， 76. _____ &lt;br&gt;　　不得他人代报，更除此不得冒名顶替，发现有 77. _____ &lt;br&gt;　　以上现象的，将取消其中考试成绩，并责令其 78. _____ &lt;br&gt;　　回国，终身不得参加该项考试。该汉语考试将 &lt;br&gt;　　于2005年开始，每年设立1月和6月两门考 79. _____ &lt;br&gt;　　试，报名具体时间和注意事项请观赏我们的官 80. _____ &lt;br&gt;　　方网站：www.cct4-6.com.cn请各位朋友互相 &lt;br&gt;　　转告，谢谢。 &lt;br&gt;　　（本大题共10分，一个1分） &lt;br&gt;　　第五部分：写作 &lt;br&gt;　　说明向导：在这个部分，你将有三十分钟来写一篇题目为：汉语四、六级真好 &lt;br&gt;的作文。字数不可少于150字，你可以以下面的提示作为文章的主 &lt;br&gt;　　线： &lt;br&gt;　　1． The College Chinese Test is so good! &lt;br&gt;　　2． How nice the College Chinese Test is!  &lt;p&gt;（原文：&lt;a title="http://www.lqqm.net/Lqqm.NetBYcA1TpPUPCTJMHMDMGXUETUUCEMATLMMKVGE_B/?t=1204018672" href="http://www.lqqm.net/Lqqm.NetBYcA1TpPUPCTJMHMDMGXUETUUCEMATLMMKVGE_B/?t=1204018672"&gt;http://www.lqqm.net/Lqqm.NetBYcA1TpPUPCTJMHMDMGXUETUUCEMATLMMKVGE_B/?t=1204018672&lt;/a&gt;）&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-2001532112266428293?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/2001532112266428293/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=2001532112266428293&amp;isPopup=true' title='1 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/2001532112266428293'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/2001532112266428293'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/02/zz.html' title='预想《汉语考级卷子》zz'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-2249974042310581517</id><published>2008-02-21T09:12:00.001+08:00</published><updated>2008-02-21T09:12:17.186+08:00</updated><title type='text'>朝鲜见闻：百姓虽穷但素质高热爱伟大领袖</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;发信人: hausely (hausely), 信区: Joke &lt;br&gt;标 &amp;nbsp;题: 朝鲜见闻：百姓虽穷但素质高热爱伟大领袖 &lt;br&gt;发信站: 两全其美网 (Wed Feb 20 13:46:32 2008), 本站(lqqm.net) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;赴朝鲜前三天，丹东国际旅行社发来一张传真，是《赴朝旅游须知》：　　新义州到平壤的沿途不允许向窗外扔任何纪念品和食品，以免引起朝鲜人民的误解。 &lt;br&gt;　　沿途景物不许拍照。 &lt;br&gt;　　不许携带手提电话、望远镜、朝鲜币进入朝鲜。 &lt;br&gt;　　对朝鲜政治、经济状况不要妄加评论，不要把自己的观点强加于人，特别是对朝鲜人民爱戴的领袖不要加以评论。向金日成主席献花和照相时要保持严肃，不能模仿领袖的姿态照相。 &lt;br&gt;　　到了丹东，导游又告诉我，最好不要带有文字的东西进入朝鲜。因为朝鲜海关检查时紧时松，遇到紧张时，这些东西都要被没收。路上看的几本杂志只好存放在朋友家。 &lt;br&gt;　　新义州不大，车辆稀少。一路上喧闹兴奋的游客都静了下来。过鸭绿江大桥前，导游已再三嘱咐，到了朝鲜，要注意自己的言行。 &lt;br&gt;　　我们乘坐的是朝鲜的国际列车。外表比较陈旧，不过车窗很宽大，里面全部是包厢。车出了新义州火车站，忽然看到街道上一位妇女面带笑容，朝列车挥手。再往前走，三三两两的人站在在铁路两边路边看火车。不少人向火车招手致意。原来，他们是向“外国朋友”表示友好。 &lt;br&gt;　　从新义州到平壤，路上再没经过城市，只有农村和小镇。朝鲜的每个村庄房屋样式非常整齐划一，一般是灰瓦白墙的平房，也有的是别墅式小楼，不过施工比较粗糙。一路所经过所有的院落周围，都是一米左右高的白墙，可以看得出全部是刚刚粉刷过不久。可能是因为刚刚过去的几大节日，也可能是为了迎接外国旅客的到来。 &lt;br&gt;　　农田里没有防护林，望过去坦坦荡荡。村庄里也很少见到树木。许多山坡上植上了树，不过都还没有长成材。看来成材的树木都被砍掉了。没见到柏油路，也没有见到沙石路，我们看到的只有土筑的公路，仅容一车通过。不过我们并没有见到汽车，上面走着的都是牛车，偶尔还可以见到拖拉机。一路所见的牛车都是木制车轮，粗犷朴拙，连铁皮都没包。 &lt;br&gt;　　一个老人挺着胸膛站在田间小路上，一只手背着，另一只手向火车频频挥舞。穿着蓝色制服系着红领巾的小学生们也专门停下来向火车招手，等火车过去才继续走路。 &lt;br&gt;　　我拿出照相机想拍几张照片，和我同包厢的一位老人劝我不要惹麻烦。他是锦州市人大的主任，前锦州市长。一上车他就说车厢里可能有窃听设备，因此建议大家不要轻易发表言论。和他同行的锦州朋友一致表示同意。 &lt;br&gt;　　朝鲜导游学生模样，看上去十分憨厚，也很乐于和我交谈。他是平壤旅游学校的学生，这次是上车实习。他说今年对朝鲜人民来说是特殊的一年。四月十五日是伟大领袖金日成的生日，是朝鲜人民最大的节日“太阳节”，今年又是伟大的领导者金正日同志诞生六十周年，四月二十五日是朝鲜人民军建立七十周年。“几天前在平壤隆重地举行了盛大的阅兵式，伟大的领导者亲自检阅了军队。晚上，朝鲜青年举行了盛大的主题游行。”所以今年是一个非常幸福的年份。你们能在今年来到朝鲜，是非常幸运的。 &lt;br&gt;　　今年是“主体”九一年。朝鲜从一九九二决议废除了公历纪年，以伟大领袖出生的那一年为“主体元年”。有了金日成大元帅的朝鲜人民是世界上最幸福的太阳民族，伟大领袖金日成是太阳民族的始祖，所以，伟大领袖的生日被定为“太阳节”。 &lt;br&gt;　　导游和我讨论了国际问题。他说美帝国主义的干涉是朝鲜问题的原因。911事件说明，美帝国主义在世界各在都遭到了惨败，美帝国主义在世界上到处都是敌人，所以，他们迟早是要失败的，朝鲜很快就会统一。 &lt;br&gt;　　在平壤郊区的公路上，看到一辆公共汽车，不但里面挤满了人，外面的车门上还“挂”了七八个人，看起来相当惊心动魂。这是进入朝鲜境内看到的第一辆公共汽车。 &lt;br&gt;　　下午三点半，火车“正点”抵达平壤。听说朝鲜现在遇到了暂时的经济困难，电力火车经常会因为停电而晚点，这段路走上八个小时、十个小时都有可能。我们一路顺风，二百二十公里的路只用了五个小时就到了，不可不谓顺利。 &lt;br&gt;　　平壤是一座宽敞、整洁、高大的城市。马路动辄一百米宽，车辆稀少，一尘不染。高层建筑很多，居民楼动辄二三十层高。所有的建筑都是水泥本色。 &lt;br&gt;　　第一站是“主体思想塔”。车过大同江桥，宽阔的江面两侧，一座座高大的建筑疏朗有致地林立在灿烂的阳光之下，江面上整齐地腾起几柱雪白的喷泉，据导游讲高度达一百多米。壮观、平静、美丽。江边上那座高耸入云的宝剑型纪念碑就是主体思想塔。 &lt;br&gt;　　所谓“主体思想”，也就是“金日成思想”。其大概意思和中国的“自力更生”相近，强调一个人的命运要掌握在自己手中，本民族的命运要掌握在本民族的手中。导游讲，朝鲜人民就是在“主体思想”的光辉指导下，独立自主地打败了美帝国主义对朝鲜的侵略。 &lt;br&gt;　　主体思想塔是在金日成大元帅七十周年时建立的，高一百五十米，连同上面的红色火炬高一百七十米。下面是一面墙，上面镶嵌着一百五十多块铜牌，是一百五十多个国家在建设主体思想塔时赠送的，上面用不同的文字刻着“伟大的主体思想万岁”、“主体思想无限光辉”之类的文字。两边有六组人物铜雕，分别代表大丰收、知识至上、铜墙铁壁等意义。朝鲜的国徽，由镰刀、斧头和毛笔构成，毛笔位于中间，表示朝鲜劳动党特别重视知识的作用。 &lt;br&gt;　　阳光特别好，主体思想塔前的广场开阔整洁，人的心情不由得不愉快。在别人照相的时候，我脱离大部队，来到塔身左侧。这里有三三两两的市民在树荫下休息。他们衣着都很整洁，有的在看书，有的在眺望，还有一对穿着深蓝制服的高中生模样的学生，在雕塑下说着什么，两个人的表情都有点害羞，像是在谈恋爱。应该也是早恋吧，朝鲜人一般都是二十八岁以后才结婚的。穿着红裙子的小孩子正在蹦跳玩耍，看到戴着“朝鲜之旅”牌子的我，立刻警惕地跑开了。大人们则对我视而不见，一副见多识广的样子。 &lt;br&gt;　　下一站是万寿台。中间不知道为什么在一处广场上停了一下。正是五点多钟，马路边上突然出现了无数下了班的平壤人，排着长队在等公共汽车。队伍起码有二百米长。广场的一端有一面画壁，上面是微笑着的伟大领袖金日成，镜片明亮，牙齿洁白，笑容慈祥，完美无瑕。我把“朝鲜之旅”的牌子摘下来放进口袋，拦住一个过路的青年，请他给我照一张相。他好奇地看着我的傻瓜相机，拿过去摆弄了一下，又还给了我。不知道是不会用还是不明白我的意思。突然，他用手托住自己胸前的金日成像，比划着问我为什么不戴领袖的像。我对他大声说着汉语“中国”，他好像通一点汉语，用汉语问我“你的民族？”这时，周围已经围上了十多个朝鲜人，而且还有越来越多的趋势。都好奇地看着我和我手中的相机，其中一个青年还往地下吐了口痰，粉碎关于朝鲜人不随地吐痰的说法。眼看全广场的人都向我涌来，我急忙冲出重围，回到了大部队那里。这时我才注意到，朝鲜人衣服上都别着领袖像，无一例外。所以一个外国人在朝鲜很容易被区分出来。 &lt;br&gt;　　晚上住在“西山宾馆”，是市郊一座三十层高的大厦。第一顿晚餐比游客们想象的要丰盛。有烧牛肉、炸鱼、炒狗宝、烧菠菜四样菜，还有饺子、米饭和啤酒。每一样饭菜都分盛四个小盘，所以摆到桌上，共二十多盘，显得丰盛无比。一开始大家以为米饭是限量的，所以一上来赶紧每人盛了一碗。然而吃完试着再要，很痛快地就端上来了。以后几天的经验也证明，在朝鲜如果你饭时努力吃，就没有饥饿的威胁。那些背了大包小裹面包、方便面、饼干的人看来失策了。 &lt;br&gt;　　吃完了饭，到总台换了十元外汇券，在商品部买了一本朝鲜外文出版社出版的《我所认识的金正日》。朝币对人民币的比率是一比四，十元外汇券相当于四十元人民币。而这本书不过四百多页，小开本，纸张比较粗糙。由于是关于领袖的，定价和别的商品比起来，还算是相当低廉的。中国人在这里终于尝到了当“老外”被宰的滋味。据说在黑市上，一元人民币可以换几十朝币。 &lt;br&gt;　　房间的电视也是从日立牌的，还是手动的那种。有三个台，都播送着歌颂节日的歌舞节目。报幕员的声音颤抖而激动，台下的掌声热烈而整齐。看不懂，关了看书。床头灯是二十度的灯泡，昏黄暗淡。 &lt;br&gt;　　拉开窗帘，窗外的巨大的平壤城一片漆黑。没有路灯，没有霓虹，甚至居民楼里也没有电灯。只有零零星星的楼房闪着灯光。这些三四十层的住宅建筑因为没有电，下班后人们得一层层爬上去。 &lt;br&gt;　　第二天的第一站是平壤地铁。平壤地铁长度达三十公里，我们要去的是复兴站，应该是最漂亮的一站了。电梯足足有三百米长，因为这个站深达一百米，在世界上应该是最深的地铁了。壁画自然是伟大领袖和伟大的领导者。我问导游为什么要修这样深，导游说这个他不太清楚。估计是为了备战吧。 &lt;br&gt;　　第二站是大学习堂，藏书可达三千万册，全国十七岁以上的公民都可以入内学习。当然，整个大学习堂里人并不太多。 &lt;br&gt;　　第三站是凯旋门。高六十米。和平壤市的大部分建筑一样造型呆板。据说六十米的高度是为了比巴黎的凯旋门高一米，主体思想塔的高度也恰比美国华盛顿纪念塔高一米，不知道是不是巧合。 &lt;br&gt;　　朝鲜人对高度的崇拜质朴可爱。从六十年代到八十年代，平壤的建筑一座比一座高。凡是路过纪念性建筑，导游都要提一下高度。在市中心，还耸立着一座金字塔型的水泥大厦，高三百多米，因为资金不足，已经停工多年，一直没有封顶。 &lt;br&gt;　　下一站是中朝友谊塔。相比主体思想塔及旁边的电视塔，这个一九五九年建筑的纪念塔就显得太矮小了。塔室里面有两本手写的纪念册，上面是一些朝鲜战争中牺牲的中国志愿军英雄的名字。一个自费旅游的志愿军老兵颤抖着手，从名册上找他战友的名字。在大家的帮助下，不久他找到了。他说，朝鲜战争时他是副排长，这个战士是他排里的。说着眼泪流了下来。 &lt;br&gt;　　中午回到西山饭店吃午饭。下午要参观祖国解放战争纪念馆，即朝鲜战争纪念馆。我们参观的是中国人民志愿军馆，在毛主席像边上，一幅巨大的标语牌，上面用朝鲜语写着：“在中国的五星红旗里，有朝鲜人的鲜血。” &lt;br&gt;　　大家听完了导游的翻译，都小声说，是翻译反了吧。 &lt;br&gt;　　回去研究朝鲜外文出版社的书，才发现导游翻译的没有错。那本书上说：“从1945年11月到1949年9月中共和国民党时行内战时期，由于蒋介石军队的美国的援助下向中共军队发动进攻，中共面临了危机。在这紧急关头，约25万名朝鲜青年参加中国东北解放战役，英勇战斗，为中国共产党的胜利和中华人民共和国的成立做出了巨大贡献。中国人民志愿军赴朝参战，可以说是以德报德。” &lt;br&gt;　　在祖国解放战争纪念馆中，中国人民志愿军馆不过是一个分馆，导游甚至连“黄继光”、“邱少云”的名字都没有听说过。 &lt;br&gt;　　参观完纪念馆，下一站是万景台金日成故居。这是平壤市郊的一个园林，中间是金主席家的三间草房。周围古木参天，鲜花遍地，风景十分优美。 &lt;br&gt;　　晚上还有一个重头节目，就是“阿里郎”文艺演出。本来赴朝三日游的报价是一千八百元，但由于朝鲜举办了这个“阿里郎”演出，外国游客必须观看，票价是二百六十元人民币，所以整个团费就变成了二千零六十，几乎相当于从辽宁到海南双飞五日游的价格。 &lt;br&gt;　　演出在能容纳十万人的五一体育场。这个带遮阳蓬的巨大体育场确实十分壮观，在整个亚洲也应该是一流的。所谓阿里郎演出，实际上就是大型团体操表演。我们进场时，全场正响起热烈的掌声，原来第一幕已经接近尾声，背景台上出现了一轮巨大的太阳，场地里人们也站成阳光幅射状。 &lt;br&gt;　　接下来的一幕一开始阴风四垂，背景台上打出了旧社会朝鲜的悲惨景象，乞丐、孤儿、死尸¨¨¨场中团体操队员也悲天抢地，捶胸顿足。然后，背景台上映射出两条巨大的铁索，一道道闪电劈向索链，场地中，队员们朝着一个方向齐心协力地舞动，做竭尽全力状。突然，铁索断裂，阳光迸发，金日成将军微笑的画像出现在背景台上，整整齐齐坐在两侧看台上的朝鲜人民齐刷刷热烈鼓掌。 &lt;br&gt;　　接下来的几幕，分别表现北朝鲜的“苦难的行军”，朝鲜人民如青松翠柏屹立在大雪之中；朝鲜的儿童，祖国的未来；朝鲜的农业和畜牧业，一群鸡鸭兔子之类地场地中欢快地跳舞；南北统一；朝鲜的体育；朝鲜的军队，一群军人进行枪刺肉搏表演。 &lt;br&gt;　　朝鲜的团体操确实是世界第一，其整齐准确规模庞大编排精心让人叹为观止。旁边的上海人说，上海八运会的团体操，就是请朝鲜人去进行指导的。 &lt;br&gt;　　第三天的上午没有什么安排，只有购物一项。然而，平壤的外国人商店确实没有什么可买的。工艺品做工有些粗糙，标价却不低。我想买一枚金日成或者金正日的像章，商店里却没有。我问导游怎么才能得到一枚领袖的像章。 &lt;br&gt;　　导游郑重地说，一般外国人是不能得到领袖像章的。不过，如果你是真心敬爱伟大领袖和伟大的领导者的话，你可以提出申请，如果朝鲜政府审察合格，会派一名部长发给你领袖像章，不过这个周期最快七天，最慢十五天。因此，很遗憾，你没有办法得到领袖的像章。 &lt;br&gt;　　真是很遗憾。 &lt;br&gt;　　回国的车十一点准时发车。这次随车的是另一个导游，他到新义州接下一个团。一路上和他聊了很久。和他聊起朝鲜历史，他所知道的朝鲜历史名人除了金日成、金正日、金正淑、金九之外，只有檀君和李舜臣。前者是朝鲜始祖，后者是李朝的抗日英雄。关于朝鲜的始祖，这位导游又提出了新的说法。历史上，朝鲜是以五千年的檀君为始祖。但解放后，朝鲜已经成为太阳民族，和以前有了质的不同。太阳民族的始祖是金日成大元帅。因此也可以说朝鲜有两个始祖：传说中的檀君和现实中的金日成大元帅。 &lt;br&gt;　　他对中国显然很隔膜。他不知道什么叫英特网，他认为北京只有一个五星级宾馆。他问我是不是被因为工作出色思想先进被建行选派出来到朝鲜参观。 &lt;br&gt;　　回去的路上，又和锦州市人大主任坐在了一起。谈起对朝鲜的观感，他一路赞不绝口。这倒不是说给朝鲜导游听的，看得出来他确实很感慨。他一路指着窗外说：你看，人家这农村搞得多整齐，房前房后干干净净，你再看中国，前头一个柴火垛后面一个粪堆。你看平壤市多干净，市民素质多高。这说明人家管理上有一套办法，人家思想统一，劲往一处使。你再想想中国，到处是办证的广告，和人家朝鲜怎么比。虽然人家穷，但人家精神状态好，走路都刷刷的。 &lt;br&gt;　　大家纷纷点点称是。 &lt;br&gt;　　对“阿里郎”表演他更是叹为观止，认为比奥运会开幕市还要好看。 &lt;br&gt;　　朝鲜导游立刻坐到他身边，记下了他的单位和他的话，说要回去汇报。 &lt;br&gt;&lt;img src="http://www.lqqm.net/smilies/icon_lol.gif"&gt;&lt;br&gt;-- &lt;br&gt;※ 来源:．两全其美网 http://lqqm.net [FROM: 202.96.4.26]&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-2249974042310581517?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/2249974042310581517/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=2249974042310581517&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/2249974042310581517'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/2249974042310581517'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/02/blog-post_21.html' title='朝鲜见闻：百姓虽穷但素质高热爱伟大领袖'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-6514274056710194602</id><published>2008-02-03T11:48:00.001+08:00</published><updated>2008-02-03T11:48:51.452+08:00</updated><title type='text'>动态站点后台建设的一点思考</title><content type='html'>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 最近“大事”比较多，一来春节在即，二来大雪封邦，等等；公司网站部分做了很多应时的“内容页”，但建设的人不是技术人员，而是普通的编辑人员：他（她）们着实很辛苦的。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 偶尔伤感到，是不是我们有些失职了？还是圈子里默许这样的“茹毛饮血”？我向来以为那些个互联网资源都有一个强大的后台，所有用户看到的内容，是由编辑人员通过较友好的管理工具制作出来的；但如今亲眼见到含具体内容的“静态页”手工绘制、发布，令我“不寒而栗”。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 出现这样的情况，大体是因为“应用”的即时、瞬时性，而开发人员视能力、人员数目的不同需要投入不等的时间造成的；出于成本的考虑，或许在流程上某些公司团体选择了简化、原始的内容制作方式。可我还是觉得，主要矛盾在于“后台”的开发方式。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果前台制作需要一周的时间，那么后台将耗费两周甚至一个月的时间，后台对于动态数据的支持，要求严格的自测甚至一定的功能扩展性；我所见到的前辈们的“页面管理后台”，多以“前台 &amp;lt;=&amp;gt; 数据库&amp;nbsp;&amp;lt;=&amp;gt; 后台”的形式展现。这种设计在逻辑上颇能服人，所谓“扩展性”多体现在数据库端表、字段的预留以及松耦合等。可惜我并不看好他。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 一段时间以来，我在实践一种“前台数据库&amp;nbsp;&amp;lt;=&amp;gt; 前台页面&amp;nbsp;&amp;lt;= 后台系统&amp;nbsp;&amp;lt;=&amp;gt; 后台数据库”的设计思想；这样的做法无非是将“用户交互数据”与“页面展现数据”隔离开来，前者是“前台数据”，后者为“后台数据”。对于某些应用，前后台数据会有交叉。这样做的好处，使得“后台适配器”管理模式成为可能。下面一一解释他们之间的具体关系。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; “前台数据库 &amp;lt;=&amp;gt; 前台页面”，对于纯静态内容页，数据库可以抹去；动态交互站点，表示前台的操作更新到数据库，而数据库亦反馈数据给前台更新页面。过去、现在以至将来，这种方式或许都不会变。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; “前台页面 &amp;lt;= 后台系统”，对于静态或动态前台内容页，其源码都由后台系统生成（而不是编辑人员手工制作）并“发布”，使得编辑人员可以花更多的时间勾勒页面的具体内容，而不是去了解甚至学习像html这样的标记语言。即时、瞬时的页面需求，可以调用后台系统的前台页面模板，继而按系统提示编辑用户可见内容，并发布页面。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; “后台系统 &amp;lt;=&amp;gt; 后台数据库”，显然，后台数据库里存放着各类“前台页面”的源码信息以及各类模板的源码信息；他的特点在于“适配器”功能，即后台开发不再是用VS2005这样的专业软件，而是在这个“后台”进行“新后台”的开发。乍看挺像“自学习”的软件；由于引用了已有的“页面生成、管理”过程，使得测试变得轻松、愉快（而不那么紧张、严格）；最重要的，细微的需求变更可以直接在“后台”重开发完成，而不要走完所有“开发 -&amp;gt; 测试”等管理流程（我想多数人还是了解，那种软件重复打包、提包、部署的过程，即便是补丁，是很熬人的；软件人可能都讨厌重复的人工劳动吧）。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 类似这样的“站点建设”专业软件我倒是见过的（功能没仔细推敲过），而且貌似更强大（各种站点数据统计功能）、商业化（收费与售后），只是成本以及可控性让相当一些企业有所顾虑吧。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 搞软件的大体都是“懒人”。我这样做，无非想要简化后台开发方式，特别是，让“界面开发人员”与“后台开发人员”工作隔离。如果有一天，某前台站点的“界面样式”等需要变更，可由界面开发人员在后台进行更改操作，而无需后台开发者的参与（传统方式，界面开发人员打包给后台开发人员，后台开发者再打包、提交等）；另外，面对前台页面内容类型、编辑模式的变更，可由后台开发人员在后台更改相关前台页面的源码数据（参数），而尽量少的利用VS2005等工具重开发类似后台，减少开发时间、规避部署出错等风险。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 考虑到项目还处于实践、完善阶段，更考虑到公司相关站点的安全性（现在看来，这点愈为重要），本文没有演示现有解决方案的源码甚至类图关系。惭愧的是，文字表达晦涩难解，怕只怕过些日子自己都读不通顺，那“笔录”算是白做了；留点念想吧。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 望自己再接再厉，使得成品的可用性真如自己预想的那样，彼时或许大脑一热，还真敢“开源”了。下篇文章想写《动态站点静态化以及合作形式的一点思考》，是对站点性能提升以及与其他公司合作方式的小结；注意了，我所指的性能提升，绝不是“缓存”的概念。呵呵，这些个好像都是明年的事了。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 朋友们、网友们春节愉快！&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-6514274056710194602?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/6514274056710194602/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=6514274056710194602&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6514274056710194602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6514274056710194602'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/02/blog-post.html' title='动态站点后台建设的一点思考'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-649984842961718858</id><published>2008-01-31T09:45:00.001+08:00</published><updated>2008-01-31T09:45:35.397+08:00</updated><title type='text'>政治是比色情更肮脏的东西</title><content type='html'>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 突然意识到，现在网络上各类“激情”横道，是不是某些人的一种策略？&lt;/p&gt; &lt;p&gt;用这种方式转移我们这些年轻人的视线，继而使得我们“无暇”顾及国邦兴安。&lt;/p&gt; &lt;p&gt;当一个孩子迷恋着游戏机的时候，他也就没那么强的想法去关心父母的婚姻状态、&lt;/p&gt; &lt;p&gt;家庭的经济状况；甚至，通过电子游戏，孩子由父母、家庭带来的心理压抑得以释放。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 揣测别人的心理是困难的，更何况“以小人之心度君子之腹”。但我“向来不掸以&lt;/p&gt; &lt;p&gt;最坏的心态去推测他人”。肉眼看，各个商家以抢占市场、获取利润的名义大肆宣传&lt;/p&gt; &lt;p&gt;“肉文化”；心眼瞧，这是个阴谋。这是某些人的谈资，他们会以“很黄很暴力”等&lt;/p&gt; &lt;p&gt;诸多口舌引起我们关注这个虚拟世界，却让我们忘记了关注我们生活的这个活生生的&lt;/p&gt; &lt;p&gt;充满“很坏很压迫”的真实国度！&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; “黑暗”表示我们(我)深处其中、难以回避；“肮脏”则反映了我们(我)的厌恶！&lt;/p&gt; &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/8705367749555657878-649984842961718858?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/649984842961718858/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=649984842961718858&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/649984842961718858'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/649984842961718858'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/blog-post_31.html' title='政治是比色情更肮脏的东西'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-3828538613156015207</id><published>2008-01-30T10:35:00.001+08:00</published><updated>2008-01-30T10:35:20.145+08:00</updated><title type='text'>南京话 VS 普通话</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;li&gt;活闹鬼——小混混，鼓惑仔的意思。  &lt;li&gt;一米多高——形容很过分，很严重的意思！（一bd糟，dai的一b）  &lt;li&gt;潘西——女朋友的意思  &lt;li&gt;潘东——男朋友啦  &lt;li&gt;小秆子——是对男孩子，或小年青的中比较邪头的人的称呼。  &lt;li&gt;老杆子——。。。。不翻译了  &lt;li&gt;甩子（甩蛋，甩B）——是指做事冲动，不理智，做事喜欢胡干蛮干的人！  &lt;li&gt;二胡——是对实际能力与表象差距太大，象绣花枕头，中看不用的人的称呼。通常指男性！  &lt;li&gt;照枝——会面，相见的意思！（没听说过）  &lt;li&gt;日烂——毁坏，破坏的意思！（这个我没听说过）  &lt;li&gt;促馊(促凑)——指人不地道，喜欢玩鬼花样的意思！（这个也没听说过）  &lt;li&gt;颠（形容词）——指人很兴奋，有点兴奋过火的意思  &lt;li&gt;颠（动词）——指人溜掉了例如：“他颠的哦！”有时也用“蹿”这个字来形容  &lt;li&gt;烦不了——指做事不考虑後果的意思！  &lt;li&gt;吊不揉——指不害怕，不给人面子的意思（虾米东西啊）  &lt;li&gt;活丑——丢脸，献丑的意思！  &lt;li&gt;窝（第2声）— 鹅  &lt;li&gt;耸（SONG）样（形容词）－－是形容做人缩手缩脚，胆小怕事的样子。（贬义词）  &lt;li&gt;高头，高面——上面的意思，挺土的现在好像没人这么说了  &lt;li&gt;粘几瓜（巴）达——形容东西上面有粘液  &lt;li&gt;杆儿——女人的老公或男朋友（要有性关系）  &lt;li&gt;杆子——俚语，男的对男的说相当于“hey，哥们”  &lt;li&gt;傻里吧唧的——说你傻的狠  &lt;li&gt;霍是的——不知道普通话怎么说跟bullshit差不多的意思，但文明一点（无意义的词，应该属于语气助词一类吧。用于藐视对方或者反驳对方的语句开头。吵架时常用。）  &lt;li&gt;二百五，二五郎当的——同甩子  &lt;li&gt;啊是的啊--“是不是的啊？”的意思。  &lt;li&gt;我也不能跟你急咯，不能急咯——前几年叫流行的一句  &lt;li&gt;么得feel咯——最近较流行，多指没有兴趣  &lt;li&gt;活比丑——指很倒霉  &lt;li&gt;塞——动词，指用拳头打人，如：你再跳老子蛮塞你咯！  &lt;li&gt;撤谎——撒谎  &lt;li&gt;老姘——姘头!  &lt;li&gt;呲（ci1）——指用水射，且必须是玩具水枪，高压水枪等射出的水柱  &lt;li&gt;犯嫌——讨厌，形容词  &lt;li&gt;“喝七麻乌地”（11245）或者“ 乌七麻喝地”(43315)——外面很黑  &lt;li&gt;胡里八涂——糊涂  &lt;li&gt;作死——找死  &lt;li&gt;包卢——玉米  &lt;li&gt;磕七头——膝盖  &lt;li&gt;条走——扫把  &lt;li&gt;搓拨——簸箕  &lt;li&gt;依怪——同广州话里的“核突”有恶心的意思  &lt;li&gt;目得－－"没有"的意思  &lt;li&gt;五二带鬼——人不上路子  &lt;li&gt;一踏带一抹——程度副词,表示非常的意思.一般後置。如:这道菜好吃的一踏带一抹!  &lt;li&gt;来丝--形容一个人或一个事物很厉害  &lt;li&gt;不对箍子--不对头  &lt;li&gt;干么司--干什么  &lt;li&gt;胎气--大方  &lt;li&gt;小儿阔--小气  &lt;li&gt;一得儿--一点  &lt;li&gt;喝人吧啦得--很吓人得  &lt;li&gt;作死--找死  &lt;li&gt;茅司--厕所  &lt;li&gt;恩--硬  &lt;li&gt;哪块--哪边  &lt;p&gt;(原文地址: &lt;a title="http://www.cnic.org/wiki/%E5%8D%97%E4%BA%AC%E8%AF%9D%E5%A4%A9%E4%B9%A6" href="http://www.cnic.org/wiki/%E5%8D%97%E4%BA%AC%E8%AF%9D%E5%A4%A9%E4%B9%A6"&gt;http://www.cnic.org/wiki/%E5%8D%97%E4%BA%AC%E8%AF%9D%E5%A4%A9%E4%B9%A6&lt;/a&gt;)&lt;/p&gt;&lt;/li&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-3828538613156015207?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/3828538613156015207/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=3828538613156015207&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/3828538613156015207'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/3828538613156015207'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/vs.html' title='南京话 VS 普通话'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-4343154324786993042</id><published>2008-01-30T10:16:00.001+08:00</published><updated>2008-01-30T10:16:46.933+08:00</updated><title type='text'>南京话四级考题流传网络，好玩地“一塌带一抹”</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;(2006-01-05 08:24:52)  &lt;p&gt;【金陵晚报报道】 “风的南京话读音？车的南京话读音？”“癔怪，曾见于《红楼梦》一书，南京话的两个意思分别是？癔里巴怪，又是什么意思？”  &lt;p&gt;“公交车司机每到一个人少的小站会问：啊下……这两个字的意思是？南京话中‘啊’字是哪个字的变音？……”  &lt;p&gt;近日，一则《南京话四级测试》的帖子在BBS网站西祠胡同上被转载得沸沸扬扬，吸引了不少网民跟帖，一度把这个“口水帖”顶到胡同口。这个搞笑测试总分为100分，其中包括80分的笔试和20分的口试。笔试题选了近百个南京经典土话作为考点，让不少人笑得喷饭之余，又倍感亲切。  &lt;p&gt;&lt;strong&gt;南京话试卷洋洋洒洒&lt;/strong&gt;  &lt;p&gt;&lt;strong&gt;网友反应：褒贬不一&lt;/strong&gt;&lt;br&gt;　　这篇《南京话四级测试》已经不知道是何人所作。在题目“设置”上，既有“小炮子”这样的老南京话，也有“不能急了”这样近年比较流行的新南京话。既有生活用语，也有骂人粗口，十分全面。因而每一次在BBS上转载，都会引起极大反响，不少人都会照着考题煞有其事地填写一番。  &lt;p&gt;“楼主来丝的一塌带一抹哎。真是盖了帽捞，不能急捞。”“8错8错！”……《南京话四级测试》一经公布就迅速得到了网民的响应，不少人索性就用南京话跟帖。一些网民甚至发出“归归，今天算是开眼界了——，唉，白白做了几十年南京人咯”、“让外地人领略了南京的博大精深！”的感慨。还有一些网友另外跟贴了一些“经典”的南京话作为补充。  &lt;p&gt;不过，也不是所有人都抱着有趣的态度看待这份试卷。  &lt;p&gt;在一些网友大呼“好玩”“有趣”的同时，也有一些人对过度“调侃”、不避“粗俗”南京方言提出了质疑。  &lt;p&gt;“南京方言就是粗话太多。包括前段时间网络流行的那首歌曲《喝馄饨》。”“看着稚气未脱的孩子满口“喝馄饨”的粗口，我的心情很不平静。它能代表我们的地域文化吗？”  &lt;p&gt;&lt;strong&gt;方言考试层出不穷&lt;/strong&gt;  &lt;p&gt;&lt;strong&gt;专家：只能玩笑对待&lt;/strong&gt;&lt;br&gt;　　尽管南京话考试在网上还是刚出炉不久的新鲜事儿，但“方言等级考试”并不是南京人的首创。在《南京话四级测试》出台之前，各种方言等级测试早已在网络上流传开了。  &lt;p&gt;早在今年五六月份，一些网民就以外语等级考试的形式，在一些论坛上推出“东北话四级考试”、“东北话六级考试”、“陕西话四级考试”等帖子。其中一些考试除了有笔试和口试外，甚至加上了听力试题，让被各种等级考试围困的学生网民过了把“调侃瘾”。  &lt;p&gt;“只有普通话水平测试，哪来的方言水平测试？”听到有南京话考试，南京市普通话培训测试站的一位专家感到很意外。“这种测试不能当真。如果社会上真的有这种测试的话，我们当然不赞成。网上测试只能当玩笑来看待。”  &lt;p&gt;“推广和保存当地方言，无可厚非。”专家介绍说，经过几十年来的普及和推广，普通话已经成为绝大多数地区受教育人群的正式场合用语。这个时候，地方方言倒因为“俏皮”、“土”成了年轻人刻意追逐的对象，用各种地方方言演绎的网络歌曲、段子，以及现在出来的方言考级试卷都是在年轻人中流传，说明了这一种反潮流的思维方式。  &lt;p&gt;“不过，应该提醒青少年，方言俏皮话和保护地方文化遗产是要区别对待的，以南京话来说，地道的南京话保留了普通话中的阴平阳平上声去声等四音，还保留了普通话所没有的入音，此外还有切、破等发音，因此南京至今还有“白局”这样的艺术形式……但是，现在的年轻人总觉得南京话就是“啊要辣油啊”这样的“嬉皮”语言。这就是不正确的态度。  &lt;p&gt;&lt;strong&gt;南京话曾差点成“国语”&lt;/strong&gt;  &lt;p&gt;尽管在主流媒体中“滥用”南京方言遭到不少专家学者的反对，但历史上，南京话差点还成了中国的国语。  &lt;p&gt;清末民初1900年前后，开始对“官话”、“国语”的标准提出了要求。关于用什么话来统一全国的语言和怎样来统一全国的语言，学者们则各有己见。1892年，中国第一个提出统一全国语音的学者卢戆章最早提出以南京话作为官话的标准。他主张把“南京话”（即所谓“蓝青官话”）作为“各省之正音”。他认为“十九省之中，除广、福、台而外，其余十六省大概属官话，而官话之最通行者，莫如南腔。”  &lt;p&gt;王照则坚决主张用“京话”（北京官话），认为“……宜取京话。因北至黑龙江，西逾太行宛洛，南距扬子江，东傅于海，纵横数千里之土语，与京语略通。是以京话推广最便，故曰‘官话’。余谓‘官’者公也，‘官话’者公用之话，自宜择其占幅员人数多者。”后来，卢戆章放弃了“南腔”，同意改用“京音官话”作为“通行国语”。而南京话最终也和“国语”失之交臂，没有能够成为中国的通用语言得以推广和普及。  &lt;p&gt;&lt;strong&gt;南京话四级测试题目&lt;/strong&gt;  &lt;p&gt;1、“风”的南京话读音？“车”的南京话读音？  &lt;p&gt;2、“癔怪”，曾见于《红楼梦》一书，南京话的两个意思分别是？“癔里巴怪”，又是什么意思？  &lt;p&gt;3、公交车司机每到一个人少的小站会问：啊下……这两个字的意思是？南京话中‘啊’字是哪个字的变音？  &lt;p&gt;4、你到哪过Ki啊……翻译成普通话为？  &lt;p&gt;5、“口罗嗦”用一个经典的南京字代替是？  &lt;p&gt;6、南京人说“小婴儿”用一个什么词？  &lt;p&gt;7、南京人如何说“碗”，用拼音打出来？  &lt;p&gt;8、你吃馄饨时最经典的一句问话是？  &lt;p&gt;9、“伯伯”，南京话如何念？  &lt;p&gt;10、“哥哥”，南京话如何念？  &lt;p&gt;11、“你站着别走。”请用正宗南京话回答。  &lt;p&gt;12、你喊奶奶，用一个字去喊，该如何念？  &lt;p&gt;13、“对面”南京人更爱怎么说？张爱玲的书里也这么说过。  &lt;p&gt;14、宋楚瑜致辞通篇地道南京话：“我离开南京时还是小三子”。小三子是什么意思？  &lt;p&gt;15、“黑漆吗乌”是什么意思？“黑”南京话怎么念？  &lt;p&gt;16、“二五”是什么意思？“二五郎当”，意思是？  &lt;p&gt;17、“舌（shi2声）答子”是什么意思？“十里八达”呢？  &lt;p&gt;18、“小炮子”是什么意思？  &lt;p&gt;19、“夹生”的意思？  &lt;p&gt;20、“孤苏”的意思？  &lt;p&gt;21、“犯嫌”的意思？  &lt;p&gt;22、“胎气”是什么意思？  &lt;p&gt;23、“老巴子”的意思？  &lt;p&gt;24、“刷括”的意思？  &lt;p&gt;25、“搛菜”的意思？  &lt;p&gt;26、“磕膝头”的意思？  &lt;p&gt;27、“来丝”的意思？来源于英语哪个词语？  &lt;p&gt;28、“直不弄冬”的意思？  &lt;p&gt;29、“瘴乌”的意思？  &lt;p&gt;30、“活丑”，意思是？  &lt;p&gt;31、兴得一头核子，核应该怎么念？意思是？  &lt;p&gt;32、南京经典骂人话：“甩”的意思是？  &lt;p&gt;33、“啊是地呀”的意思？  &lt;p&gt;34、“算活拉倒”的意思？  &lt;p&gt;35、南京话“啊油——”是什么意思？  &lt;p&gt;36、南京话“没有”怎么说？  &lt;p&gt;37、你不买马就没的了……请问“马就”是哪三个字的速读？这句话的意思是？  &lt;p&gt;38、“水煮得要漫出来了”用一个字去形容？  &lt;p&gt;39、“一塌带一抹”这个词的含义  &lt;p&gt;40、“猴子”的猴字，南京话中有“猴到树上去”和“冻得猴猴的”等用法。请问这两个用法的含义分别是？  &lt;p&gt;41、“干么丝啊”，南京话含义？  &lt;p&gt;42、“窝赖”，南京话含义。  &lt;p&gt;43、“喝人巴拉的”意思是？同样，“吓”这个字南京人怎么念？  &lt;p&gt;44、“胡里八涂”，什么意思？  &lt;p&gt;45、“一得儿”什么意思？  &lt;p&gt;46、“你到哪快去”什么意思？  &lt;p&gt;47、“硬”南京话的读音是？  &lt;p&gt;49、“作死”意思是？  &lt;p&gt;50、“某人踮掉了”，在南京话中什么意思？  &lt;p&gt;51、南京话“玉米棒”怎么说？  &lt;p&gt;52、“活闹鬼”，在南京话中什么意思？  &lt;p&gt;53、“勺子”南京话怎么说？  &lt;p&gt;54、南京话，“二胡”是什么意思？比如说，“你真是个二胡！”  &lt;p&gt;55、“扫把”和“簸箕”南京话怎么说？  &lt;p&gt;56、“厕所”南京话怎么说？  &lt;p&gt;57、“脱鼻龙”在南京话中是什么意思？  &lt;p&gt;58、“耸（SONG，2声）样”南京话什么意思？  &lt;p&gt;59、“红配绿，丑得哭”，这句话应该如何念？  &lt;p&gt;60、“喝水”的“喝”字应该如何念？饿应该如何念？课字呢？  &lt;p&gt;61、“月头放卫星，月中吃半斤，月底鬼转经。”“鬼转经”南京话中的意思为？  &lt;p&gt;62、“多大事啊？”意思为？  &lt;p&gt;63、“小兵辣子”南京话意思为？  &lt;p&gt;63、“姨（念衣）子”，“二姨（念衣）子”，什么意思？  &lt;p&gt;64、河歪是某种水里生物？歪歪蜜又是什么东西？  &lt;p&gt;65、“你想花我？骗子！”这句话的意思是？  &lt;p&gt;66、“神过到唠”，意思是？  &lt;p&gt;67、“开洋荤”，意思是？  &lt;p&gt;68、“月亮巴巴”，意思是？“巴巴”，南京话指的是？  &lt;p&gt;69、“潮了”，意思是？  &lt;p&gt;70、“人五人六”，意思是？  &lt;p&gt;71、抖火（第一声）意思是？火（第一声）二屁，意思是？那么火（第一声）的意思又是？  &lt;p&gt;72、“喳吧喳吧”意思是？“喳唬”意思是？  &lt;p&gt;73、“筋筋拽拽（如：带筋的牛肉，吃到口里筋筋拽拽的，好吃！）”，是什么意思？  &lt;p&gt;74、“木里是故”意思是？  &lt;p&gt;75、“拿桥”意思是？  &lt;p&gt;76、“乖乖隆地冬”意思是？  &lt;p&gt;77、“搔包”意思是？  &lt;p&gt;78、“长抽到了”、“长铺到了”，形容的分别是什么？  &lt;p&gt;79、“你把我东西粗哪块去啦？”其中“粗”字的含义是？  &lt;p&gt;80、南京话“淋雨”怎么说？“淋”字用哪个字代替？  &lt;p&gt;最后20分口试题：请用南京话报出10条南京路名，10个景点名字。  &lt;p&gt;(编辑　涵烁)  &lt;p&gt;(原文地址: &lt;a title="http://www.njnews.cn/t/ca711246.htm" href="http://www.njnews.cn/t/ca711246.htm"&gt;http://www.njnews.cn/t/ca711246.htm&lt;/a&gt;)&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-4343154324786993042?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/4343154324786993042/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=4343154324786993042&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4343154324786993042'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4343154324786993042'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/blog-post_30.html' title='南京话四级考题流传网络，好玩地“一塌带一抹”'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-4693594830364369433</id><published>2008-01-29T11:03:00.001+08:00</published><updated>2008-01-29T11:03:38.431+08:00</updated><title type='text'>赵本山宋丹丹最新小品《很黄很暴利》</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;h4&gt;（赵本山站在自己的煎饼摊子钱面色阴沉，宋丹丹走了过来）&lt;br&gt;宋丹丹（下简称宋）：大哥，你为啥闷闷不乐呢？&lt;br&gt;赵本山（以下简称赵）：乐啥呀，煎饼摊都要让人给和谐了，乐得出来啊？！&lt;br&gt;宋：好好的，和谐你干啥啊？&lt;br&gt;赵：你没听中央台新闻说啊，说我这个摊子卖的煎饼很黄很暴利，需要整顿，国有&amp;nbsp; &amp;nbsp;&amp;nbsp; &amp;nbsp; 资本要在这里边占控股地位。 &lt;br&gt;宋：你这煎饼咋就很黄很暴利呢？不沾边啊。&lt;br&gt;赵：我这煎饼里不是卧着鸡蛋嘛，很黄。&lt;br&gt;宋：那很暴利呢？&lt;br&gt;赵：他们找专家核查成本，说我这个煎饼成本一块，卖一块五一个，利润率50%。暴利。&lt;br&gt;宋：哎呀，大哥你厉害啊。50%利润率你都赶上中国移动了&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; 税我还得倒赔，干脆我就刘备俩兄弟得了。&lt;br&gt;宋：怎么讲啊？&lt;br&gt;赵：关张呗&lt;br&gt;宋：那以后街上煎饼摊都国有了，有啥变化啊&lt;br&gt;赵：不黄不暴利了，鸡蛋不放了，卖两块一个&lt;br&gt;宋：啊！那不更暴利了&lt;br&gt;赵：一听这话你就觉悟低，人家领导说了，国有企业的暴利是利国利民的，是&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; 饼，不用国有化。&lt;/h4&gt; &lt;p&gt;[原帖:&lt;a title="http://bbs.huash.com/viewthread.php?tid=410446" href="http://bbs.huash.com/viewthread.php?tid=410446"&gt;http://bbs.huash.com/viewthread.php?tid=410446&lt;/a&gt;]&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-4693594830364369433?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/4693594830364369433/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=4693594830364369433&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4693594830364369433'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4693594830364369433'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/blog-post_29.html' title='赵本山宋丹丹最新小品《很黄很暴利》'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-3436769209913426347</id><published>2008-01-28T14:27:00.001+08:00</published><updated>2008-01-28T14:27:05.603+08:00</updated><title type='text'>很烦很杂</title><content type='html'>&lt;p&gt;外面雪下的很大，听到的是michael在抓狂；&lt;/p&gt; &lt;p&gt;无名的压抑愈发浓烈，不知谁能将这一口饮下？&lt;/p&gt; &lt;p&gt;昨天还是百花齐放，今日换作茉莉独香；&lt;/p&gt; &lt;p&gt;事件接踵而至，我等待着命运的分享。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;这世界本是一块砧板，我在上面静静的躺；&lt;/p&gt; &lt;p&gt;我听到的不是什么jam，而是那分明的磨刀霍霍：&lt;/p&gt; &lt;p&gt;谁是那待宰的牛羊？&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;据说雪会越下越大，不知道心情会变作什么样。&lt;/p&gt; &lt;p&gt;可现在雪停了，风也出奇的轻，&lt;/p&gt; &lt;p&gt;老天爷忘记了自己的信誓旦旦？&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;那眼是瞎的，那耳是聋的，&lt;/p&gt; &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/8705367749555657878-3436769209913426347?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/3436769209913426347/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=3436769209913426347&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/3436769209913426347'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/3436769209913426347'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/blog-post_28.html' title='很烦很杂'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-5592117233232397712</id><published>2008-01-24T11:00:00.001+08:00</published><updated>2008-01-24T11:00:51.042+08:00</updated><title type='text'>某地理老师的暴强言论</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;发信人: christinetwo (christinetwo), 信区: Joke &lt;br&gt;标 &amp;nbsp;题: zz某地理老师的暴强言论~爆笑经典！！强力推荐！ &lt;br&gt;发信站: 两全其美网 (Wed Jan 23 12:01:01 2008), 本站(lqqm.net) &lt;br&gt;第1辑 &lt;br&gt;1:你这种人天理地理都难容。（他就是这么骂人的） &lt;br&gt;2：存在即合理。 &lt;br&gt;3：某些同学考试时脑袋偏转的角度不要超过黄赤交角。（监考时说的） &lt;br&gt;4：这位同学，你的灵魂现在比大西洋还遥远。 &lt;br&gt;5：这个题目不知道，你该下19层地狱，不是一般的地狱。 &lt;br&gt;6：到现在你们对气候还一窍不通，你们死有余辜，这种东西烧成灰你们都 &lt;br&gt;要记得。 &lt;br&gt;7：很多题目真是只有不知廉耻的同学才会做错（极言题目简单） &lt;br&gt;8：两艘船一艘在热带一艘在温带捕鱼，哪艘船更容易沉掉？温带的，为什 &lt;br&gt;么，温带鱼多，船装不下就沉了（万式无厘头） &lt;br&gt;9：开小差的同学，争取误差在8秒之内。 &lt;br&gt;10：太阳耀斑爆发是很可怕的，但我要是被惹火了的话，会比耀斑还可怕 &lt;br&gt;数万倍。（所以他有个外号叫万耀斑） (耀平)是他原名 &lt;br&gt;11：有些登峰造极的同学现在彗星还写成慧星，真是充满智慧的扫把 &lt;br&gt;星。 &lt;br&gt;12：今天地理课上我发了火，头上出了汗，太阳一出来蒸发了，在太仓南 &lt;br&gt;部上空形成了水汽，下了场雨，碰巧有几滴又落回我头上，这就是一个水 &lt;br&gt;循环。（如此举例） &lt;br&gt;13：这位同学站在悬崖上面对著大海，反思他刚才在地理课上的所作所 &lt;br&gt;为，如果这时是白天，那么他是安全的，如果是晚上，吹起一阵风，他就 &lt;br&gt;会感觉到一双罪恶的手在把他往悬崖下推。（水的海陆间循环那节课上， &lt;br&gt;他这样解释海风和陆风） &lt;br&gt;14：请那些在下面面无表情的女同学注视著我，虽然我知道我的形象不怎 &lt;br&gt;么光辉。 &lt;br&gt;15：我这个人饭量很大，一顿要吃5碗饭，但是我脑力体力消耗得大，那位 &lt;br&gt;同学一顿只吃一碗，但他一天到晚做著不动，两年下来，他成了只肉球， &lt;br&gt;而我变成了木乃伊。（用比喻手法解释径流量和蒸发量） &lt;br&gt;16：这个纸不是给你做草稿的，更不是给你做草纸的。 &lt;br&gt;17：山上积了很多雪，就想冰激凌一样，对不对。（有人说这个比喻很可 &lt;br&gt;爱） &lt;br&gt;18：海沟听说过吗？海底下有阴沟啊？ &lt;br&gt;19：中国十二点，日本就是十三点（讲时区的时候说的） &lt;br&gt;20：有的同学让我有犯罪感，让我觉得对不起他爸爸妈妈爷爷奶奶列祖列 &lt;br&gt;宗。 &lt;br&gt;第2辑 &lt;br&gt;21：请用0.003秒回答这个问题。 &lt;br&gt;22：全班刚才失踪同学一名，经调查，该生系进行非法位移，以后如果还 &lt;br&gt;有这样的同学，希望大家把他往死里打。（说的是**，同情他） &lt;br&gt;23：你这花岗岩脑袋！ &lt;br&gt;24：岩石熔化成岩浆的过程就是重新投胎的过程。 &lt;br&gt;25：今天我们要研究地质山。这位同学以后去开拖拉机，拼死拼活在平地 &lt;br&gt;山堆起一座土山，这种山不是我们要研究的山。 &lt;br&gt;26：不能以貌取人，也不能以貌取山。 &lt;br&gt;27：堆积层用化石来解释，最下一层的化石肯定最简单最古老，到了最上 &lt;br&gt;面一层，可能就出土你老祖宗的遗骸了。 &lt;br&gt;28：一座山现在是背斜现在怎么变成向斜了那？就像一个人出生时是个小 &lt;br&gt;男孩80岁后就变成老太婆了。 &lt;br&gt;29：解释倒置地形：一个同学进来时候全校第一，但他在这里除了学习什 &lt;br&gt;么都做，一个学期他就倒数第一了，这就是倒置。 &lt;br&gt;30：有句话叫“自古华山一条路”。山上这条路，下山还是这条路，如果 &lt;br&gt;说还有一条的话，就是自由落体了。 &lt;br&gt;31：下面我们来讲火山，有些同学前面讲的山都不喜欢，就对火山感兴 &lt;br&gt;趣，上课的时候也希望我时不时火山爆发一下。 &lt;br&gt;32：后面几位同学灵魂又要游离到身体外面了，我居然还要当你们灵魂的 &lt;br&gt;守护者，随时帮你们把它招回来。 &lt;br&gt;33：有的火山我们已经可以盖棺定论了，他们长得像火山，但已经动不了 &lt;br&gt;了，但还有比如地中海沿岸的火山，时不时就有火光发出，甚至可以作为 &lt;br&gt;地中海航行的灯塔了。 &lt;br&gt;34：现在，男同学和女同学，听懂了的请举手，两种都不是的，可以不 &lt;br&gt;举。 &lt;br&gt;35：现在我们的时间利用率应达到NBA第四场的最后一分钟。 &lt;br&gt;36：哪个同学再发出声音的话，枭首示众。 &lt;br&gt;37：在我讲的时候除了教室的回音外，不允许有其它任何声音。 &lt;br&gt;38：所有的岩石，当他们厌倦岩石生涯的时候，都可以借外力回到地下， &lt;br&gt;重新投胎。 &lt;br&gt;39：如果一条公路沿途不经过一个城市，那等于是给野人修的。 &lt;br&gt;40：河谷和沟谷的区别，简单说，就是河流与阴沟的区别。 &lt;br&gt;第3辑 &lt;br&gt;41：洪水是不会乖乖跟著河谷流的，它脾气比我还大。 &lt;br&gt;42：从上次抽查的结果来看，大部分同学死定了。 &lt;br&gt;43：我现在是在帮你们，有一两个混蛋还不听，马上要死了，给你救命稻 &lt;br&gt;草都不要，视死如归，可歌可泣。 &lt;br&gt;44：我知道我的声音不好听，对某些同学来说简直是噪声，如果你不想 &lt;br&gt;听，你可以到外面晒太阳，在阴冷的教室里听我的噪声，对你来说简直是 &lt;br&gt;折磨，会影响你生长发育是吧。 &lt;br&gt;45：以苏洁同学为例，整张试卷他就做对了两题，我不知道他那肥硕的大 &lt;br&gt;脑袋里装的是什么，学习是要靠记忆的，就像我怎么知道苏洁的，如果我 &lt;br&gt;不用记忆，我只能说那是只长著巨大脑袋的动物。（苏洁，我们班第一号 &lt;br&gt;胖子。） &lt;br&gt;46：有的同学到现在一道题都没做对，这是人类的悲哀，你看苏洁他还在 &lt;br&gt;恬不知耻地笑，那张巨大的脸全是由脸皮构成的。 &lt;br&gt;47：这种题做错是不容易的。 &lt;br&gt;48：这题选错的同学，我强烈建议你立即下沉到地底。 &lt;br&gt;49：咸海地区的沙尘暴厉害到什么程度，沙子伴著盐刮到你脸上，刮了几 &lt;br&gt;次，你人就成一块咸肉了。（妈的，博学） &lt;br&gt;50：你声音怎么这么小，你不该来这儿，你应该去聋哑学校。 &lt;br&gt;51：热带季风气候居然写成了沙漠气候，难道我们这儿，你的家乡是一片 &lt;br&gt;沙漠？还是你的大脑是一片沙漠。 &lt;br&gt;52：如果这一道题你选D，你以后千万不要和人说你高中时学过地理。 &lt;br&gt;53：我罚你们抄，不是我不原谅你们，是科学不原谅你们。 &lt;br&gt;54：问你气压高低，你答什么反气旋，问你是男是女，你说你吃过饭 &lt;br&gt;了？ &lt;br&gt;55：我们要感谢细菌微生物，如果没有它们，地球上将被以前的尸体覆 &lt;br&gt;盖，你100代祖宗的样子现在还栩栩如生。 &lt;br&gt;56：当我们中国人还是野人的时候，我们就活跃在黄河流域。所以有人说 &lt;br&gt;怪不得我们是黄种人，就是从黄河流域跑出来的人。 &lt;br&gt;57：我们学校有些学生来这里纯粹只是为给学校小店创收益。 &lt;br&gt;58：有些人来学校里除了读书什么都做。 &lt;br&gt;59：字典里什么叫混蛋，这个同学就是原始定义。 &lt;br&gt;60：为什么叫石灰岩，它能烧出石灰就是石灰岩，它能烧出水泥就是水泥 &lt;br&gt;岩了。 &lt;br&gt;第4辑 &lt;br&gt;61：那边那个混蛋请站起来一下。 &lt;br&gt;62：向斜从中间到两边出土的化石会越来越新，到最边上这一带甚至会出 &lt;br&gt;土你老祖宗的化石。 &lt;br&gt;63：试卷上的这两张烂图……证明了中国印刷术的倒退。 &lt;br&gt;64：你们这些同学下课就往小店跑的，可能在无形中就破坏了内蒙古的草 &lt;br&gt;原，因为你们买那些甘草蜜饯啊，甘草是只有蒙古草原出产的。 &lt;br&gt;65：你是混蛋，但还不算坏蛋。 &lt;br&gt;66：这题如果你答阔叶林的话，我会毫不犹豫代表地理学，把你打死。 &lt;br&gt;67：亚洲的风性气候，你们记住三只鸡：热鸡（热季），野鸡（用土话念 &lt;br&gt;的“亚季”），瘟鸡（温季） &lt;br&gt;68：你们同学白天上课时的音量比晚自习时小多了，这是极不正常的，如 &lt;br&gt;果这种情况出现在野生动物身上，那就意味著大的自然灾害即将到来。 &lt;br&gt;69：东北的河水跟我们这不一样，一年有两次汛期，所以东北人一年有两 &lt;br&gt;次淹死的机会。 &lt;br&gt;70：这题选c的同学，有明显的反人类倾向。 &lt;br&gt;71：笔不要转，转你的大脑。 &lt;br&gt;73：如果哪个同学说西北高温多雨的话，我强烈建议他在吹西北风的时 &lt;br&gt;候，脱光衣服，去操场上跑两圈，好好享受他的高温多雨。 &lt;br&gt;74：我发现我们班有一位女同学，无论我说什么，她都以一个火星人的态 &lt;br&gt;度旁观这一切，注意，我现在说的是太阳系的知识，你火星人也有关系的 &lt;br&gt;啊。 &lt;br&gt;75：有的同学无论我说什么他都始终面无表情，你是不是有面瘫啊？你跟 &lt;br&gt;史泰龙什么关系？ &lt;br&gt;76：现在后排有些同学，他始终带著忧郁的表情坐在那儿思考，什么也不 &lt;br&gt;做。在他的脸上我看到了范仲淹的风采，先天下之忧而忧。 &lt;br&gt;77：我给一个学生讲什么是东南风，讲了半个小时他还是不懂，我跟只猴 &lt;br&gt;子它都懂了！ &lt;br&gt;78：现在我们教室低纬地区的个别女同学请注意。 &lt;br&gt;79：你这个混蛋的作业是白板，你这种人以后考试考得好的话是对科学的 &lt;br&gt;侮辱。 &lt;br&gt;80：大家都是高级灵长类，差别怎么就那么大呢。 &lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-5592117233232397712?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/5592117233232397712/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=5592117233232397712&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/5592117233232397712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/5592117233232397712'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/blog-post_24.html' title='某地理老师的暴强言论'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-3348896482484025843</id><published>2008-01-23T09:07:00.001+08:00</published><updated>2008-01-23T09:07:11.263+08:00</updated><title type='text'>兵马俑偶得</title><content type='html'>&lt;p&gt;岁寒长安几重雪，几刻桑梓入眼帘。&lt;/p&gt; &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/8705367749555657878-3348896482484025843?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/3348896482484025843/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=3348896482484025843&amp;isPopup=true' title='2 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/3348896482484025843'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/3348896482484025843'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/blog-post_23.html' title='兵马俑偶得'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-154128592596624265</id><published>2008-01-22T16:47:00.001+08:00</published><updated>2008-01-22T16:47:22.747+08:00</updated><title type='text'>雪</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;迎面沪西雪，怯怯如春闺；清风轻语去，落花谁家院？&lt;br&gt;香气淡似水，柔情释陈怨。铁汉几多愁，又添一处恋。&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-154128592596624265?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/154128592596624265/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=154128592596624265&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/154128592596624265'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/154128592596624265'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/blog-post_22.html' title='雪'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-7371127965187667876</id><published>2008-01-21T12:50:00.001+08:00</published><updated>2008-01-21T12:50:09.211+08:00</updated><title type='text'>迟来的怀念</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;“极目青郊外，烟霾步正浓。&lt;br&gt;中原方逐鹿，博浪踵相踪。&lt;br&gt;&lt;br&gt;大江歌罢掉头东，邃密群科济世穷。&lt;br&gt;面壁十年图壁破，难愁蹈海亦英雄。&lt;br&gt;&lt;br&gt;人間的万象真理，愈求愈模糊；&lt;br&gt;　　━━模糊中偶然見着一点光明，&lt;br&gt;　　真愈覚嬌妍。&lt;br&gt;&lt;br&gt;扪虱倾谈惊四座，持螯下酒话当年。&lt;br&gt;险夷不变应尝胆，道义争担敢息肩。”&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-7371127965187667876?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/7371127965187667876/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=7371127965187667876&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/7371127965187667876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/7371127965187667876'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/blog-post_21.html' title='迟来的怀念'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-2799994888146758975</id><published>2008-01-19T12:15:00.001+08:00</published><updated>2008-01-19T12:15:58.460+08:00</updated><title type='text'>C#调用WMI更改本地网络IP设置</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;[原文地址: &lt;a title="http://www.chenjiliang.com/Article/View.aspx?ArticleID=3860&amp;amp;TypeID=84" href="http://www.chenjiliang.com/Article/View.aspx?ArticleID=3860&amp;amp;TypeID=84"&gt;http://www.chenjiliang.com/Article/View.aspx?ArticleID=3860&amp;amp;TypeID=84&lt;/a&gt;]  &lt;p&gt;下面附上我根据上面的&lt;a&gt;IP&lt;/a&gt;Provider做的一个仿系统更改网络&lt;a&gt;IP&lt;/a&gt;界面的小程序界面.呵呵 &lt;br&gt;&lt;img alt="单击显示全图，Ctrl+滚轮缩放图片" src="http://www.chenjiliang.com/Article/ArticleImage/84/3860/WmiConfigIP1.jpg" border="0"&gt;&lt;br&gt;因家中与公司的网络配置不同,而我又是带着我的笔记本在家里与公司来来回回.这就导致要经常设置不同的&lt;a&gt;IP&lt;/a&gt;和网关数据,一段时间下来后觉得特烦,做为一个程序员.为什么不好好利用自己的知识偷懒一下呢?特别是像我这样一个懒惰的人... &lt;br&gt;因为网络&lt;a&gt;IP&lt;/a&gt;设置是要涉及到硬件,C#是没有现成接口调用的.只能通过调用API或者是&lt;a&gt;WMI&lt;/a&gt;这道系统提供给我们的桥梁..在&lt;a&gt;WMI&lt;/a&gt;这个大库中用于管理网络配置的则主要是通过"&lt;a&gt;Win32_NetworkAdapterConfiguration&lt;/a&gt;"这个管理类.这里面已基本包括了&lt;a&gt;IP&lt;/a&gt;,DNS,网关的设置信息... &lt;br&gt;在C#中使用&lt;a&gt;WMI&lt;/a&gt;是很轻松的事情.下面直接给出C#实现代码,呵呵,我的文字表达能力很差,所以我也不多说了,代码量很少,看起来应该很简单的:  &lt;p&gt;&lt;img title="C#" src="http://www.chenjiliang.com/Image/Extension/cs.ico"&gt;复制 &lt;img title="保存" src="http://www.chenjiliang.com/Image/Save.jpg"&gt;保存&lt;pre&gt;&lt;b&gt;using&lt;/b&gt; System;&lt;br /&gt;&lt;b&gt;using&lt;/b&gt; System.Collections;&lt;br /&gt;&lt;b&gt;using&lt;/b&gt; System.Text;&lt;br /&gt;&lt;b&gt;using&lt;/b&gt; System.Management;&lt;br /&gt;&lt;b&gt;using&lt;/b&gt; System.Text.RegularExpressions;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;namespace&lt;/b&gt; Kingthy.Windows.IPChanger.Providers&lt;br /&gt;{&lt;br /&gt;    &lt;b&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;&lt;/b&gt;    &lt;b&gt;/// IPProvider 的摘要说明。&lt;br /&gt;&lt;/b&gt;    &lt;b&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;&lt;/b&gt;    &lt;b&gt;public&lt;/b&gt; &lt;b&gt;class&lt;/b&gt; IPProvider&lt;br /&gt;    {&lt;br /&gt;        &lt;b&gt;public&lt;/b&gt; IPProvider()&lt;br /&gt;        {&lt;br /&gt;            &lt;b&gt;//&lt;br /&gt;&lt;/b&gt;            &lt;b&gt;// TODO: 在此处添加构造函数逻辑&lt;br /&gt;&lt;/b&gt;            &lt;b&gt;//&lt;br /&gt;&lt;/b&gt;        }&lt;br /&gt;        &lt;b&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// 设置DNS&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="dns"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;public&lt;/b&gt; &lt;b&gt;static&lt;/b&gt; &lt;b&gt;void&lt;/b&gt; SetDNS(&lt;b&gt;string&lt;/b&gt;[] dns)&lt;br /&gt;        {&lt;br /&gt;            SetIPAddress(&lt;b&gt;null&lt;/b&gt;, &lt;b&gt;null&lt;/b&gt;, &lt;b&gt;null&lt;/b&gt;, dns);&lt;br /&gt;        }&lt;br /&gt;        &lt;b&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// 设置网关&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="getway"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;public&lt;/b&gt; &lt;b&gt;static&lt;/b&gt; &lt;b&gt;void&lt;/b&gt; SetGetWay(&lt;b&gt;string&lt;/b&gt; getway)&lt;br /&gt;        {&lt;br /&gt;            SetIPAddress(&lt;b&gt;null&lt;/b&gt;, &lt;b&gt;null&lt;/b&gt;, &lt;b&gt;new&lt;/b&gt; &lt;b&gt;string&lt;/b&gt;[] { getway }, &lt;b&gt;null&lt;/b&gt;);&lt;br /&gt;        }&lt;br /&gt;        &lt;b&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// 设置网关&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="getway"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;public&lt;/b&gt; &lt;b&gt;static&lt;/b&gt; &lt;b&gt;void&lt;/b&gt; SetGetWay(&lt;b&gt;string&lt;/b&gt;[] getway)&lt;br /&gt;        {&lt;br /&gt;            SetIPAddress(&lt;b&gt;null&lt;/b&gt;, &lt;b&gt;null&lt;/b&gt;, getway, &lt;b&gt;null&lt;/b&gt;);&lt;br /&gt;        }&lt;br /&gt;        &lt;b&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// 设置IP地址和掩码&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="ip"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="submask"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;public&lt;/b&gt; &lt;b&gt;static&lt;/b&gt; &lt;b&gt;void&lt;/b&gt; SetIPAddress(&lt;b&gt;string&lt;/b&gt; ip, &lt;b&gt;string&lt;/b&gt; submask)&lt;br /&gt;        {&lt;br /&gt;            SetIPAddress(&lt;b&gt;new&lt;/b&gt; &lt;b&gt;string&lt;/b&gt;[] { ip }, &lt;b&gt;new&lt;/b&gt; &lt;b&gt;string&lt;/b&gt;[] { submask }, &lt;b&gt;null&lt;/b&gt;, &lt;b&gt;null&lt;/b&gt;);&lt;br /&gt;        }&lt;br /&gt;        &lt;b&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// 设置IP地址，掩码和网关&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="ip"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="submask"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="getway"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;public&lt;/b&gt; &lt;b&gt;static&lt;/b&gt; &lt;b&gt;void&lt;/b&gt; SetIPAddress(&lt;b&gt;string&lt;/b&gt; ip, &lt;b&gt;string&lt;/b&gt; submask, &lt;b&gt;string&lt;/b&gt; getway)&lt;br /&gt;        {&lt;br /&gt;            SetIPAddress(&lt;b&gt;new&lt;/b&gt; &lt;b&gt;string&lt;/b&gt;[] { ip }, &lt;b&gt;new&lt;/b&gt; &lt;b&gt;string&lt;/b&gt;[] { submask }, &lt;b&gt;new&lt;/b&gt; &lt;b&gt;string&lt;/b&gt;[] { getway }, &lt;b&gt;null&lt;/b&gt;);&lt;br /&gt;        }&lt;br /&gt;        &lt;b&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// 设置IP地址，掩码，网关和DNS&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="ip"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="submask"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="getway"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="dns"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;public&lt;/b&gt; &lt;b&gt;static&lt;/b&gt; &lt;b&gt;void&lt;/b&gt; SetIPAddress(&lt;b&gt;string&lt;/b&gt;[] ip, &lt;b&gt;string&lt;/b&gt;[] submask, &lt;b&gt;string&lt;/b&gt;[] getway, &lt;b&gt;string&lt;/b&gt;[] dns)&lt;br /&gt;        {&lt;br /&gt;            ManagementClass wmi = &lt;b&gt;new&lt;/b&gt; ManagementClass(&lt;b&gt;"Win32_NetworkAdapterConfiguration"&lt;/b&gt;);&lt;br /&gt;            ManagementObjectCollection moc = wmi.GetInstances();&lt;br /&gt;            ManagementBaseObject inPar = &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;            ManagementBaseObject outPar = &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;            &lt;b&gt;foreach&lt;/b&gt; (ManagementObject mo &lt;b&gt;in&lt;/b&gt; moc)&lt;br /&gt;            {&lt;br /&gt;                &lt;b&gt;//如果没有启用IP设置的网络设备则跳过&lt;br /&gt;&lt;/b&gt;                &lt;b&gt;if&lt;/b&gt; (!(&lt;b&gt;bool&lt;/b&gt;) mo[&lt;b&gt;"IPEnabled"&lt;/b&gt;])&lt;br /&gt;                    &lt;b&gt;continue&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;                &lt;b&gt;//设置IP地址和掩码&lt;br /&gt;&lt;/b&gt;                &lt;b&gt;if&lt;/b&gt; (ip != &lt;b&gt;null&lt;/b&gt; &amp;amp;&amp;amp; submask != &lt;b&gt;null&lt;/b&gt;)&lt;br /&gt;                {&lt;br /&gt;                    inPar = mo.GetMethodParameters(&lt;b&gt;"EnableStatic"&lt;/b&gt;);&lt;br /&gt;                    inPar[&lt;b&gt;"IPAddress"&lt;/b&gt;] = ip;&lt;br /&gt;                    inPar[&lt;b&gt;"SubnetMask"&lt;/b&gt;] = submask;&lt;br /&gt;                    outPar = mo.InvokeMethod(&lt;b&gt;"EnableStatic"&lt;/b&gt;, inPar, &lt;b&gt;null&lt;/b&gt;);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                &lt;b&gt;//设置网关地址&lt;br /&gt;&lt;/b&gt;                &lt;b&gt;if&lt;/b&gt; (getway != &lt;b&gt;null&lt;/b&gt;)&lt;br /&gt;                {&lt;br /&gt;                    inPar = mo.GetMethodParameters(&lt;b&gt;"SetGateways"&lt;/b&gt;);&lt;br /&gt;                    inPar[&lt;b&gt;"DefaultIPGateway"&lt;/b&gt;] = getway;&lt;br /&gt;                    outPar = mo.InvokeMethod(&lt;b&gt;"SetGateways"&lt;/b&gt;, inPar, &lt;b&gt;null&lt;/b&gt;);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                &lt;b&gt;//设置DNS地址&lt;br /&gt;&lt;/b&gt;                &lt;b&gt;if&lt;/b&gt; (dns != &lt;b&gt;null&lt;/b&gt;)&lt;br /&gt;                {&lt;br /&gt;                    inPar = mo.GetMethodParameters(&lt;b&gt;"SetDNSServerSearchOrder"&lt;/b&gt;);&lt;br /&gt;                    inPar[&lt;b&gt;"DNSServerSearchOrder"&lt;/b&gt;] = dns;&lt;br /&gt;                    outPar = mo.InvokeMethod(&lt;b&gt;"SetDNSServerSearchOrder"&lt;/b&gt;, inPar, &lt;b&gt;null&lt;/b&gt;);&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// 启用DHCP服务器&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;public&lt;/b&gt; &lt;b&gt;static&lt;/b&gt; &lt;b&gt;void&lt;/b&gt; EnableDHCP()&lt;br /&gt;        {&lt;br /&gt;            ManagementClass wmi = &lt;b&gt;new&lt;/b&gt; ManagementClass(&lt;b&gt;"Win32_NetworkAdapterConfiguration"&lt;/b&gt;);&lt;br /&gt;            ManagementObjectCollection moc = wmi.GetInstances();&lt;br /&gt;            &lt;b&gt;foreach&lt;/b&gt; (ManagementObject mo &lt;b&gt;in&lt;/b&gt; moc)&lt;br /&gt;            {&lt;br /&gt;                &lt;b&gt;//如果没有启用IP设置的网络设备则跳过&lt;br /&gt;&lt;/b&gt;                &lt;b&gt;if&lt;/b&gt; (!(&lt;b&gt;bool&lt;/b&gt;) mo[&lt;b&gt;"IPEnabled"&lt;/b&gt;])&lt;br /&gt;                    &lt;b&gt;continue&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;                &lt;b&gt;//重置DNS为空&lt;br /&gt;&lt;/b&gt;                mo.InvokeMethod(&lt;b&gt;"SetDNSServerSearchOrder"&lt;/b&gt;, &lt;b&gt;null&lt;/b&gt;);&lt;br /&gt;                &lt;b&gt;//开启DHCP&lt;br /&gt;&lt;/b&gt;                mo.InvokeMethod(&lt;b&gt;"EnableDHCP"&lt;/b&gt;, &lt;b&gt;null&lt;/b&gt;);&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;/// &amp;lt;summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// 判断是否IP地址格式&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;/summary&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;param name="ip"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br /&gt;&lt;/b&gt;        &lt;b&gt;public&lt;/b&gt; &lt;b&gt;static&lt;/b&gt; &lt;b&gt;bool&lt;/b&gt; IsIPAddress(&lt;b&gt;string&lt;/b&gt; ip)&lt;br /&gt;        {&lt;br /&gt;            &lt;b&gt;string&lt;/b&gt;[] arr = ip.Split(&lt;b&gt;'.'&lt;/b&gt;);&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; (arr.Length != 4)&lt;br /&gt;                &lt;b&gt;return&lt;/b&gt; &lt;b&gt;false&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;            &lt;b&gt;string&lt;/b&gt; pattern = &lt;b&gt;@"\d{1,3}"&lt;/b&gt;;&lt;br /&gt;            &lt;b&gt;for&lt;/b&gt; (&lt;b&gt;int&lt;/b&gt; i = 0; i &amp;lt; arr.Length; i++)&lt;br /&gt;            {&lt;br /&gt;                &lt;b&gt;string&lt;/b&gt; d = arr[i];&lt;br /&gt;                &lt;b&gt;if&lt;/b&gt; (i == 0 &amp;amp;&amp;amp; d == &lt;b&gt;"0"&lt;/b&gt;)&lt;br /&gt;                    &lt;b&gt;return&lt;/b&gt; &lt;b&gt;false&lt;/b&gt;;&lt;br /&gt;                &lt;b&gt;if&lt;/b&gt; (!Regex.IsMatch(d, pattern))&lt;br /&gt;                    &lt;b&gt;return&lt;/b&gt; &lt;b&gt;false&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;                &lt;b&gt;if&lt;/b&gt; (d != &lt;b&gt;"0"&lt;/b&gt;)&lt;br /&gt;                {&lt;br /&gt;                    d = d.TrimStart(&lt;b&gt;'0'&lt;/b&gt;);&lt;br /&gt;                    &lt;b&gt;if&lt;/b&gt; (d == &lt;b&gt;""&lt;/b&gt;)&lt;br /&gt;                        &lt;b&gt;return&lt;/b&gt; &lt;b&gt;false&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;                    &lt;b&gt;if&lt;/b&gt; (&lt;b&gt;int&lt;/b&gt;.Parse(d) &amp;gt; 255)&lt;br /&gt;                        &lt;b&gt;return&lt;/b&gt; &lt;b&gt;false&lt;/b&gt;;&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; &lt;b&gt;true&lt;/b&gt;;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-2799994888146758975?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/2799994888146758975/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=2799994888146758975&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/2799994888146758975'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/2799994888146758975'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/cwmiip.html' title='C#调用WMI更改本地网络IP设置'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-8386581095015516900</id><published>2008-01-16T17:02:00.001+08:00</published><updated>2008-01-16T17:02:01.721+08:00</updated><title type='text'>C#操作xml之xpath语法</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;/p&gt; &lt;p&gt;[原文地址: &lt;a title="http://www.cnblogs.com/hya1109/archive/2007/12/16/996535.html" href="http://www.cnblogs.com/hya1109/archive/2007/12/16/996535.html"&gt;http://www.cnblogs.com/hya1109/archive/2007/12/16/996535.html&lt;/a&gt;&amp;nbsp;] &lt;/p&gt; &lt;p&gt;以前也发过关于.net中操作XML的帖子，但不是很详细，现在我将详细介绍一下c#如何操作xml文件，正如学习操作数据库要学习SQL语言一样，在学习操作xml与语言之前，我们要先熟悉一下xml的“sql”语句xpath。由于本系列帖子的目的不在于详细介绍xpath语法所以，我借用了园子里&lt;a href="http://www.cnblogs.com/leves/"&gt;leves&lt;/a&gt;的帖子来简单介绍一下xpath语法：&lt;/p&gt; &lt;p&gt;XPath 是XML的查询语言，和SQL的角色很类似。以下面XML为例，介绍XPath 的语法。&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;&amp;lt;?xml version="1.0" encoding="ISO-8859-1"?&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;lt;catalog&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp; &amp;lt;cd country="USA"&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;Empire Burlesque&amp;lt;/title&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;artist&amp;gt;Bob Dylan&amp;lt;/artist&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;price&amp;gt;10.90&amp;lt;/price&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp; &amp;lt;/cd&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp; &amp;lt;cd country="UK"&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;Hide your heart&amp;lt;/title&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;artist&amp;gt;Bonnie Tyler&amp;lt;/artist&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;price&amp;gt;9.90&amp;lt;/price&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp; &amp;lt;/cd&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp; &amp;lt;cd country="USA"&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;title&amp;gt;Greatest Hits&amp;lt;/title&amp;gt; &lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;artist&amp;gt;Dolly Parton&amp;lt;/artist&amp;gt; &lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;lt;price&amp;gt;9.90&amp;lt;/price&amp;gt; &lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;lt;/cd&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;lt;/catalog&amp;gt;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;定位节点&lt;/strong&gt;&lt;br&gt;XML是树状结构，类似档案系统内数据夹的结构，XPath也类似档案系统的路径命名方式。不过XPath 是一种模式(Pattern)，可以选出 XML档案中，路径符合某个模式的所有节点出来。例如要选catalog底下的cd中所有price元素可以用：&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;/catalog/cd/price&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;如果XPath的开头是一个斜线（/）代表这是绝对路径。如果开头是两个斜线（//）表示文件中所有符合模式的元素都会被选出来，即使是处于树中不同的层级也会被选出来。以下的语法会选出文件中所有叫做cd的元素（在树中的任何层级都会被选出来）：&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;//cd&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;选择未知的元素&lt;/strong&gt;&lt;br&gt;使用星号（Wildcards,＊）可以选择未知的元素。下面这个语法会选出/catalog/cd 的所有子元素：&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;/catalog/cd/*&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;以下的语法会选出所有catalog的子元素中，包含有price作为子元素的元素。&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;/catalog/*/price&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;以下的语法会选出有两层父节点，叫做price的所有元素。&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;/*/*/price&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;以下的语法会选择出文件中的所有元素。&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;//*&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;要注意的是，想要存取不分层级的元素，XPath语法必须以两个斜线开头(//)，想要存取未知元素才用星号(*)，星号只能代表未知名称的元素，不能代表未知层级的元素。 &lt;br /&gt;&lt;p&gt;&lt;strong&gt;选择分支&lt;/strong&gt;&lt;br&gt;使用中括号可以选择分支。以下的语法从catalog的子元素中取出第一个叫做cd的元素。XPath的定义中没有第0元素这种东西。&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;/catalog/cd[1]&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;以下语法选择catalog中的最后一个cd元素：（XPathj并没有定义 first() 这种函式喔，用上例的 [1]就可以取出第一个元素。&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;/catalog/cd[last()]&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;以下语法选出含有price子元素的所有/catalog/cd元素。&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;/catalog/cd[price]&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;以下语法选出price元素的值等于10.90的所有/catalog/cd元素&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;/catalog/cd[price=10.90]&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;以下语法选出price元素的值等于10.90的所有/catalog/cd元素 的price元素&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;/catalog/cd[price=10.90]/price&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;选择一个以上的路径&lt;/strong&gt;&lt;br&gt;使用Or操作数(|)就可以选择一个以上的路径。例如：&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;/catalog/cd/title | catalog/cd/artist&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;选择所有title以及artist元素&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;//title | //artist&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;选择所有title以及artist以及price元素&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;//title | //artist | //price&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&lt;strong&gt;选择属性&lt;/strong&gt;&lt;br&gt;在XPath中，除了选择元素以外，也可以选择属性。属性都是以@开头。例如选择文件中所有叫做country的属性：&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;//@country&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;&lt;p&gt;选择所有含有country这个属性的cd元素：&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;//cd[@country]&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;&lt;p&gt;以下语法选择出含有属性的所有cd元素&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;//cd[@*]&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/pre&gt;&lt;br /&gt;&lt;p&gt;以下语法选择出country属性值为UK的cd元素&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;&lt;pre&gt;//cd[@country='UK']&lt;/pre&gt;&lt;br /&gt;&lt;p&gt;&amp;nbsp;只要掌握了xpath语法，理论上你就可以访问xml文件中的任意节点和任意值 &lt;br /&gt;&lt;p&gt;posted on 2007-12-16 11:55 &lt;a href="http://hya1109.cnblogs.com/"&gt;胡耀华&lt;/a&gt; 阅读(66) &lt;a href="http://www.cnblogs.com/#Post"&gt;评论(1)&lt;/a&gt; &lt;a href="http://www.cnblogs.com/hya1109/admin/EditPosts.aspx?postid=996535"&gt;编辑&lt;/a&gt; &lt;a href="http://www.cnblogs.com/#"&gt;收藏&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-8386581095015516900?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/8386581095015516900/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=8386581095015516900&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/8386581095015516900'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/8386581095015516900'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/cxmlxpath.html' title='C#操作xml之xpath语法'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-4043615132445127866</id><published>2008-01-14T17:16:00.001+08:00</published><updated>2008-01-14T17:16:34.538+08:00</updated><title type='text'>伤</title><content type='html'>&lt;p&gt;冬夜独对寒窗，&lt;/p&gt; &lt;p&gt;相思绵绵，&lt;/p&gt; &lt;p&gt;佳人肠断。&lt;/p&gt; &lt;p&gt;问天地情做何解，&lt;/p&gt; &lt;p&gt;寂寞听雪，&lt;/p&gt; &lt;p&gt;天地黯然。&lt;/p&gt; &lt;p&gt;我为飞花君似蝉，&lt;/p&gt; &lt;p&gt;我爱冷秋君恋夏；&lt;/p&gt; &lt;p&gt;清风孤唱，&lt;/p&gt; &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/8705367749555657878-4043615132445127866?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/4043615132445127866/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=4043615132445127866&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4043615132445127866'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4043615132445127866'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/blog-post_14.html' title='伤'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-9137050995703471047</id><published>2008-01-14T13:34:00.001+08:00</published><updated>2008-01-14T13:34:58.349+08:00</updated><title type='text'>年前的追忆</title><content type='html'>&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 突然有些想念母校，离开她也不过半年时光。人的意志总在变化，当初离开的时候带着绝对的梦想，“毅然决然”；如今除夕将近，除了回家见母亲的想法，也起了回母校看看的愿望。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 人有多少所谓“绝不后悔”的决定？我曾痛恨学校的教育环境，我曾不屑学校的分数、教条。现在一切都过去，生活、工作还算“满意”的时候，却发现偶尔会留恋那里的人和事。我那些可爱的伙伴，我那稚嫩的青春悸动。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 年龄越大的人，越会对过去表现的依恋；人如果没有回忆，人的一生将异常空虚。&lt;/p&gt; &lt;p&gt;我不知道今后是否会有机会回到母校，但一旦瞥见网络上关于伊的报道，情难自禁，仿佛高考过后对伊的向往，很想下一秒就出现在西安。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;无论男人、女人，生活中多少会“喜新厌旧”；学习的时候憧憬工作，工作的时候却又怀恋校园。无论做什么，无怨无悔最为紧要。好好的工作，多多的挣钱吧，时间以后肯定是会有的！&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-9137050995703471047?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/9137050995703471047/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=9137050995703471047&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/9137050995703471047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/9137050995703471047'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/blog-post.html' title='年前的追忆'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-4582922366914753935</id><published>2008-01-10T18:03:00.001+08:00</published><updated>2008-01-10T18:03:59.584+08:00</updated><title type='text'>Sql2005中对XML类型字段的运用</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;该文章转载自网络大本营：http://www.xrss.cn/Dev/DotNet/200721010251.Html &lt;p&gt;在SQL2005中增加了xml类型数据。这样，我们可以将我们应用程序中的实体对象直接保存到数据库中。下次要取的时候就可以直接将XML反序列化成实体对象。对于数据量不是很大的情况下，可以考虑使用。  &lt;p&gt;select * from Employee&lt;br&gt;where [content].exist('//Age[text()&amp;gt;9000]')=1  &lt;p&gt;此SQL语句中带有xpath的查询，可以找出employee表中content为XML类型列中子节点&amp;gt;9000的所有记录  &lt;p&gt;看一下，运用.  &lt;p&gt;using System;&lt;br&gt;using System.Collections.Generic;&lt;br&gt;using System.ComponentModel;&lt;br&gt;using System.Data;&lt;br&gt;using System.Drawing;&lt;br&gt;using System.Text;&lt;br&gt;using System.Windows.Forms;&lt;br&gt;using System.Data.SqlClient;&lt;br&gt;using System.Xml.Serialization;&lt;br&gt;using System.IO;&lt;br&gt;namespace DevTest&lt;br&gt;{&lt;br&gt;public partial class Form3 : Form&lt;br&gt;{&lt;br&gt;SqlConnection cn = new SqlConnection("server=192.168.1.100\\SqlExpress;uid=hpasc;pwd=9637004;database=filemanager");&lt;br&gt;public Form3()&lt;br&gt;{&lt;br&gt;InitializeComponent();&lt;br&gt;cn.Open();&lt;br&gt;}&lt;br&gt;private void button1_Click(object sender, EventArgs e)&lt;br&gt;{&lt;br&gt;DataTable dt = cn.GetSchema();&lt;br&gt;this.dataGridView1.DataSource = dt;&lt;br&gt;}  &lt;p&gt;private void button2_Click(object sender, EventArgs e)&lt;br&gt;{&lt;br&gt;DataTable dt = cn.GetSchema("Tables",null);&lt;br&gt;this.dataGridView1.DataSource = dt;&lt;br&gt;}  &lt;p&gt;private void button3_Click(object sender, EventArgs e)&lt;br&gt;{&lt;br&gt;//this.dataGridView1.DataSource = cn.GetSchema("IndexColumns", new string[] { "FileManager", "dbo", "Creers" });&lt;br&gt;SqlCommand cmd = new SqlCommand();&lt;br&gt;List&amp;lt;Employee&amp;gt; Emps = new List&amp;lt;Employee&amp;gt;();&lt;br&gt;cmd.CommandText = "insert into Employee values(@OID,@Name,@Age,@City,@Address,@Birthday,@Content)"&lt;br&gt;XmlSerializer ser = new XmlSerializer(typeof(Employee));&lt;br&gt;cmd.Connection = cn;&lt;br&gt;cmd.Prepare();&lt;br&gt;this.textBox1.AppendText("生成对象时间" + System.DateTime.Now.ToString());&lt;br&gt;for(int i=0;i&amp;lt;10000;i++)&lt;br&gt;{&lt;br&gt;System.IO.MemoryStream ms = new System.IO.MemoryStream();&lt;br&gt;Employee emp=new Employee();&lt;br&gt;emp.Address="emp.Address"+i.ToString();;&lt;br&gt;emp.Age=i;&lt;br&gt;emp.Name="Name"+i.ToString();&lt;br&gt;emp.OID=Guid.NewGuid();&lt;br&gt;emp.Birthday=DateTime.Now.AddHours(-i);&lt;br&gt;emp.City="City"+i.ToString();&lt;br&gt;ser.Serialize(ms,emp);&lt;br&gt;ms.Position = 0;&lt;br&gt;StreamReader sr = new StreamReader(ms);&lt;br&gt;emp.Content = sr.ReadToEnd();&lt;br&gt;sr.Close();&lt;br&gt;Emps.Add(emp);&lt;br&gt;}&lt;br&gt;this.textBox1.AppendText("\r\n结束生成对象时间" + System.DateTime.Now.ToString());&lt;br&gt;this.textBox1.AppendText("\r\n开始数据插入" + System.DateTime.Now.ToString());&lt;br&gt;foreach(Employee emp in Emps)&lt;br&gt;{&lt;br&gt;cmd.Parameters.Clear();&lt;br&gt;cmd.Parameters.Add("@OID", SqlDbType.UniqueIdentifier).Value = emp.OID;&lt;br&gt;cmd.Parameters.Add("@Name", SqlDbType.NVarChar, 50).Value = emp.Name;&lt;br&gt;cmd.Parameters.Add("@City", SqlDbType.NVarChar, 50).Value = emp.City;&lt;br&gt;cmd.Parameters.Add("@Address", SqlDbType.NVarChar, 50).Value = emp.Address;&lt;br&gt;cmd.Parameters.Add("@Age", SqlDbType.Int).Value = emp.Age;&lt;br&gt;cmd.Parameters.Add("@Birthday", SqlDbType.DateTime).Value = emp.Birthday;&lt;br&gt;cmd.Parameters.Add("@Content", SqlDbType.Xml).Value = emp.Content;&lt;br&gt;cmd.ExecuteNonQuery();&lt;br&gt;}&lt;br&gt;this.textBox1.AppendText("\r\n结否数据插入" + System.DateTime.Now.ToString());&lt;br&gt;}  &lt;p&gt;private void button4_Click(object sender, EventArgs e)&lt;br&gt;{&lt;br&gt;List&amp;lt;Employee&amp;gt; Emps = new List&amp;lt;Employee&amp;gt;();&lt;br&gt;XmlSerializer ser = new XmlSerializer(typeof(Employee));&lt;br&gt;this.textBox1.AppendText("\r\n开始取出数据对象时间" + System.DateTime.Now.ToString());&lt;br&gt;SqlCommand cmd = new SqlCommand();&lt;br&gt;cmd.Connection = cn;&lt;br&gt;cmd.CommandText = "select Content from Employee"&lt;br&gt;SqlDataAdapter da = new SqlDataAdapter();&lt;br&gt;da.SelectCommand = cmd;&lt;br&gt;DataSet ds = new DataSet();&lt;br&gt;da.Fill(ds);&lt;br&gt;foreach (DataRow dr in ds.Tables[0].Rows)&lt;br&gt;{&lt;br&gt;MemoryStream ms = new MemoryStream();&lt;br&gt;StreamWriter sr = new StreamWriter(ms);&lt;br&gt;sr.WriteLine(dr[0].ToString());&lt;br&gt;sr.Flush();&lt;br&gt;ms.Position = 0;&lt;br&gt;Employee emp=(Employee)ser.Deserialize(ms);&lt;br&gt;Emps.Add(emp);&lt;br&gt;sr.Close();&lt;br&gt;//Employee emp=(Emp)&lt;br&gt;}&lt;br&gt;this.textBox1.AppendText("\r\n结束反序列生成对象时间" + System.DateTime.Now.ToString());&lt;br&gt;this.dataGridView1.DataSource = Emps;&lt;br&gt;}&lt;br&gt;}  &lt;p&gt;[Serializable]&lt;br&gt;public class Employee&lt;br&gt;{&lt;br&gt;Guid _OID;  &lt;p&gt;public Guid OID&lt;br&gt;{&lt;br&gt;get { return _OID; }&lt;br&gt;set { _OID = value; }&lt;br&gt;}  &lt;p&gt;string _Name;  &lt;p&gt;public string Name&lt;br&gt;{&lt;br&gt;get { return _Name; }&lt;br&gt;set { _Name = value; }&lt;br&gt;}&lt;br&gt;int _Age;  &lt;p&gt;public int Age&lt;br&gt;{&lt;br&gt;get { return _Age; }&lt;br&gt;set { _Age = value; }&lt;br&gt;}&lt;br&gt;string _Address;  &lt;p&gt;public string Address&lt;br&gt;{&lt;br&gt;get { return _Address; }&lt;br&gt;set { _Address = value; }&lt;br&gt;}&lt;br&gt;DateTime _Birthday;  &lt;p&gt;public DateTime Birthday&lt;br&gt;{&lt;br&gt;get { return _Birthday; }&lt;br&gt;set { _Birthday = value; }&lt;br&gt;}&lt;br&gt;string _City;  &lt;p&gt;public string City&lt;br&gt;{&lt;br&gt;get { return _City; }&lt;br&gt;set { _City = value; }&lt;br&gt;}&lt;br&gt;string _Content;  &lt;p&gt;public string Content&lt;br&gt;{&lt;br&gt;get { return _Content; }&lt;br&gt;set { _Content = value; }&lt;br&gt;}  &lt;p&gt;}&lt;br&gt;}  &lt;p&gt;该文章转载自网络大本营：http://www.xrss.cn/Dev/DotNet/200721010251.Html&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-4582922366914753935?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/4582922366914753935/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=4582922366914753935&amp;isPopup=true' title='1 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4582922366914753935'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4582922366914753935'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/sql2005xml.html' title='Sql2005中对XML类型字段的运用'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-5383760365130370980</id><published>2008-01-10T18:02:00.001+08:00</published><updated>2008-01-10T18:02:44.619+08:00</updated><title type='text'>为gridview“删除”列添加确认对话框</title><content type='html'>&lt;p&gt;&lt;/p&gt; &lt;p&gt;原文地址：&lt;a title="http://www.cnblogs.com/doraeimo/archive/2007/01/01/609344.html" href="http://www.cnblogs.com/doraeimo/archive/2007/01/01/609344.html"&gt;http://www.cnblogs.com/doraeimo/archive/2007/01/01/609344.html&lt;/a&gt;  &lt;p&gt;如何为gridview控件里的“删除”列添加一个确认对话框？网上众说纷纭，大致见到了三种解决方案，现归纳如下：&lt;br&gt;1、继承Web.IO里的button控件，为其实现一个IPostback的接口用于回调，具体代码之复杂，只有作者自己想体会吧……&lt;br&gt;2、在gridview的ItemCreated事件中，遍历所有控件，若属于LinkButton类，且CommandName为“Delete”，就将其添加一个属性，具体做法是将遍历到的Control强制类型转化为LinkButton，然后调用其Atributes.Add方法，添加一个onclick事件内含confirm语句，即  &lt;p&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"&gt;lb.Attributes.Add("onclick",&amp;nbsp;"return&amp;nbsp;confirm('您真的要删除此行吗？')");&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"&gt;  &lt;p&gt;3、目前已知的最简洁的方法，如图，在删除按钮的那一列属性里面，把DeleteText属性设为  &lt;p&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"&gt;&amp;lt;div&amp;nbsp;id="de"&amp;nbsp;onclick="JavaScript:return&amp;nbsp;confirm('确定删除吗？')"&amp;gt;删除&amp;lt;/div&amp;gt;  &lt;p&gt;这个太强了，赞一个。&lt;br&gt;&lt;img src="http://www.cnblogs.com/images/cnblogs_com/doraeimo/onDelete.jpg" border="0"&gt;&lt;br&gt;可问题是，.net输出的html代码如下：  &lt;p&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"&gt;&amp;lt;a&amp;nbsp;href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$GridView1','Delete$0')"&amp;nbsp;style="color:#4A3C8C;"&amp;gt;&amp;lt;div&amp;nbsp;id="de"&amp;nbsp;onclick="JavaScript:return&amp;nbsp;confirm('确定删除吗？')"&amp;gt;删除&amp;lt;/div&amp;gt;&amp;lt;/a&amp;gt;  &lt;p&gt;为什么内层&amp;lt;div&amp;gt;的onclick事件所返回的bool值能影响到外层&amp;lt;a&amp;gt;标签的的语句是否被执行呢？&lt;br&gt;仔细想了想，以前用asp直接写的删除标签是这个样子的：  &lt;p&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"&gt;&amp;lt;a&amp;nbsp;href="deleteUser.asp?id=xxx"&amp;nbsp;&amp;nbsp;onclick="return&amp;nbsp;confirm('确定删除吗？')"&amp;gt;删除&amp;lt;/a&amp;gt;  &lt;p&gt;也就是说，onclick事件接受一个bool值，其决定了click事件是否被触发。若click事件没有被触发，href内含的跳转动作就不会生效。同理，之前的那段代码中，&amp;lt;div&amp;gt;在&amp;lt;a&amp;gt;中，只有先触发&amp;lt;div&amp;gt;的click事件，&amp;lt;a&amp;gt;的跳转动作才会生效。而我们在&amp;lt;div&amp;gt;的onclick事件中若选择为其赋值false，随即取消了&amp;lt;div&amp;gt;的click事件，也同时取消了&amp;lt;a&amp;gt;的跳转。 &lt;br&gt;之后，新的问题又来了。如果我们的CommandField中ButtonType是Button的话，这段代码就失效了。我想了下，可以通过将其转换为模板列的方式来解决。&lt;br&gt;先将该字段转换成模板，然后编辑这个模板列，选中用于删除的Button，将其onClientClick属性设为  &lt;p&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top"&gt;return&amp;nbsp;confirm('您确认删除要删除么？')  &lt;p&gt;即可。 &lt;br&gt;&lt;img height="602" alt="" src="http://www.cnblogs.com/images/cnblogs_com/doraeimo/aa.JPG" width="316" border="0"&gt;  &lt;p&gt;发表于 2007-01-01 00:47 &lt;a href="http://doraeimo.cnblogs.com/"&gt;助燃&lt;/a&gt; 阅读(8564) &lt;a href="http://www.cnblogs.com/#Post"&gt;评论(28)&lt;/a&gt; &lt;a href="http://www.cnblogs.com/doraeimo/admin/EditPosts.aspx?postid=609344"&gt;编辑&lt;/a&gt; &lt;a href="http://www.cnblogs.com/#"&gt;收藏&lt;/a&gt; 所属分类: &lt;a href="http://www.cnblogs.com/doraeimo/category/80692.html"&gt;Asp.net+AJAX&lt;/a&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-5383760365130370980?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/5383760365130370980/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=5383760365130370980&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/5383760365130370980'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/5383760365130370980'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2008/01/gridview.html' title='为gridview“删除”列添加确认对话框'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-1100532315091381512</id><published>2007-08-16T13:35:00.000+08:00</published><updated>2007-09-04T10:27:03.416+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><title type='text'>C#中的位操作(http://blog.ydqmx.net/user1/evil/archives/2006/1405.html)</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;[ 2006-7-13 22:05:59 | By: Evil ]&lt;br /&gt;位操作符是对数据按二进制位进行运算的操作符。c#位操作符包括：&lt;br /&gt;&lt;br /&gt;按位与 &amp; &lt;br /&gt;按位或 | &lt;br /&gt;按位取反 ~ &lt;br /&gt;左移 &lt;&lt; &lt;br /&gt;右移 &gt;&gt;&lt;br /&gt;举例说明&lt;br /&gt;using System; &lt;br /&gt;class MikeCat &lt;br /&gt;{ &lt;br /&gt;　　public static void Main() &lt;br /&gt;　　{ &lt;br /&gt;　　　　int a=6&amp;3; &lt;br /&gt;　　　　Console.WriteLine("a={0}",a); &lt;br /&gt;　　　　//6的二进制是00000110,3的二进制是00000011,按位与后等于00000010，　　即2。&lt;br /&gt;　　　　&lt;br /&gt;　　　　int b=6|3; &lt;br /&gt;　　　　Console.WriteLine("b={0}",b); &lt;br /&gt;　　　　//6的二进制是00000110,3的二进制是00000011,按位或后等于00000111，即7 &lt;br /&gt;&lt;br /&gt;　　　　int c=~6; &lt;br /&gt;　　　　Console.WriteLine("c={0}",c); &lt;br /&gt;　　　　//6的二进制是00000110,按位取反后是11111001即-7 &lt;br /&gt;&lt;br /&gt;　　　　int d=6^3; &lt;br /&gt;　　　　Console.WriteLine("d={0}",d); &lt;br /&gt;　　　　//6的二进制是00000110,3的二进制是00000011,按位异或后等于00000101，即5 &lt;br /&gt;&lt;br /&gt;　　　　int e=6&lt;&lt;3; &lt;br /&gt;　　　　Console.WriteLine("e={0}",e); &lt;br /&gt;　　　　//6的二进制是00000110,左移三位后等于00101000，即48 &lt;br /&gt;&lt;br /&gt;　　　　int f=6&gt;&gt;2; &lt;br /&gt;　　　　Console.WriteLine("f={0}",f); &lt;br /&gt;　　　　//6的二进制是00000110,右移二位等于00000001,即1 &lt;br /&gt;　　} &lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-1100532315091381512?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/1100532315091381512/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=1100532315091381512&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/1100532315091381512'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/1100532315091381512'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/08/chttpblogydqmxnetuser1evilarchives20061.html' title='C#中的位操作(http://blog.ydqmx.net/user1/evil/archives/2006/1405.html)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-6321782790834853072</id><published>2007-08-16T10:59:00.000+08:00</published><updated>2007-09-04T10:26:26.651+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='创新设计'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><title type='text'>“角色应用权限管理”中“质数”的运用</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;一、需求与分析&lt;br /&gt;在用户日益增多时，对用户进行角色（等级）分类、区别对待显得相当必要。一方面通过积分等奖励措施、鼓励用户经常性的访问，从而提高站点价值；另一方面通过应用分级，用户由角色限制访问，规避在资源发布过程中可能带来的版权等诸多风险，同时通过用户积分（虚拟钱币）消费回收，降低发布成本；等等。&lt;br /&gt;对用户进行分类，可绝不是简单的活。&lt;br /&gt;用户的角色（等级，以下均简称“角色”），类似人在社会中的身份。我，在家里，面对母亲是“儿子”，面对表妹是“表哥”；在学校，面对老师是“学生”，面对食堂是“顾客”；在社会，面对商店是“顾客”，面对美女是“帅哥”；在公司，面对总裁是“雇员”，面对下属是“老大”。共有4个应用：“家”、“学校”、“社会”、“公司”；其下又分若干子类。&lt;br /&gt;1. “儿子”成人前可以理直气壮地向妈妈要钱，但要在妈妈年老后负责赡养；&lt;br /&gt;2. “顾客”可以购买食堂、商店里面的食品或货物；&lt;br /&gt;3. “帅哥”可以和美女勾勾搭搭（美女间勾勾搭搭要受到道德约束）；&lt;br /&gt;4. “老大”可以对下属进行训话。&lt;br /&gt;以上便是几个角色和应用之间的时间处理关系。需要注意的是，各应用的角色间是有交叉的：学校食堂的“顾客”和社会商店的“顾客”，履行的职责（恪守的规则）基本相同。&lt;br /&gt;在同一个应用下的角色，也会出现简单的“级别”差异。比如：“人”和“男人”的关系，“男人”能做的，“人”都能做；但“人”能做的，“男人”不竟然都可以做（比如“怀孕”）。&lt;br /&gt;通过上面的讨论，我初步将应用按两种性质分类：区域与事件。&lt;br /&gt;“家”、“学校”、“公司”等是不同的区域，各区域有其对应的角色类型。&lt;br /&gt;“购物”、“学习”、“勾搭”等是不同的事件，各事件有其对应的角色类型。&lt;br /&gt;“区域”与“事件”，前者标识范围，后者标识操作。 &lt;br /&gt;二、设计与建模&lt;br /&gt;计算机对数的运算效率要远高于网络数据传输过程，因此，通过数的运算，压缩网络数据量是非常好的提议。此外，数的统一性，便于应用间的“语言”交互，所要注意的，是如何保证对“数”“结构”的良好建模。&lt;br /&gt;“质数”与“合数”的关系，有点像钥匙与锁的匹配，所不同的是，两种数之间是多对多的关系。但这种多对多反而带来好处：有利于资源复用的模型。&lt;br /&gt;一定数范围内，“质数”的个数一般比“合数”少，甚至少得多。&lt;br /&gt;通常的系统中，“角色”的个数一般比“应用”少，甚至少得多。&lt;br /&gt;当我把角色设想成某个“质数”时，任何“应用”在我眼里不过是一个（组）“合数”，当该“应用”对该“角色”开放时，其“合数”（组员）能被该“质数”整除。&lt;br /&gt;构建如下“角色”：&lt;br /&gt;1. 儿子（2），表哥（3）&lt;br /&gt;2. 学生（5），顾客（学校）（7），&lt;br /&gt;3. 帅哥（11），顾客（社会）（13）&lt;br /&gt;4. 雇员（17），老大（19），&lt;br /&gt;5. 顾客（7）；&lt;br /&gt;&lt;br /&gt;构建如下“应用”：&lt;br /&gt;1. 家庭应用：区域（2×3）；事件：要钱（2），欺负（3）&lt;br /&gt;2. 学校应用：区域（5×7）；事件：学习（5），购买（7）&lt;br /&gt;3. 社会应用：区域（11×7）；事件：勾搭（11），购买（7）&lt;br /&gt;4. 公司应用：区域（17×19）；事件：领工资（17），训话（19 ）&lt;br /&gt;&lt;br /&gt;当面对某“应用”进行“角色”权限判断时：&lt;br /&gt;1. “应用”申请。&lt;br /&gt;2. “角色”是否整除“区域（事件）”？是，继续；否，“应用”返回。&lt;br /&gt;3. “角色”享受“应用”中的服务。&lt;br /&gt;4. “应用”返回。&lt;br /&gt;&lt;br /&gt;我构造的模型有这样的特点：“儿子（2）”、“表哥（3）”可以在“家庭应用（区域6）”中活动，同时，儿子可以享受“要钱（2）”事件，“表哥”可以享受“欺负（3）”事件，等等。这与实际情况基本符合。而且由于质数的特点，这一算法也绝对不会出错。&lt;br /&gt;谈谈“男人”与“人”。有没有必要使得所有可被“男人”整除的“应用”，均乘以“人”而使得其也能被“人”整除？否！对于这样极其明显的包含关系的角色定义，可以用“质数”加“权”解决。定义“人”（2），定义“男人”（2^2），即“男人”（4），这样，对于所有“男人”通过的应用事件，“人”是肯定适用的。&lt;br /&gt;那么“女人”呢？怎样模拟“女人”与“男人”的平等，同时相同地归属于“人”？稍后作答。&lt;br /&gt;提两个问题：&lt;br /&gt;1. 产品部门对角色数目的要求是无止境的，从“小小神童”到“至尊水友”，中间少则跨越几十级，多则上百级！“质数”可不那么好找啊！&lt;br /&gt;2. 开发部门对应用数目的统计是吓死人的，从“首页登录”到“提示错误”，中间少则几百个事件，多则上万个！总有个“质数”的积会溢出啊！&lt;br /&gt;为了使“质数”运用得到更好的扩展性，我提议用“多维质数”。&lt;br /&gt;1. 儿子（2，1，1，1），简写[1，2]；表哥（3，1，1，1），简写[1，3]；&lt;br /&gt;2. 学生（1，2，1，1），简写[2，2]；顾客（学校）（1，3，1，1），简写[2，3]；&lt;br /&gt;3. 帅哥（1，1，2，1），简写[3，2]；顾客（社会）（1，1，3，1），简写[3，3]；&lt;br /&gt;4. 雇员（1，1，1，2），简写[4，2]；老大（1，1，1，3），简写[4，3]；&lt;br /&gt;注意：以上角色“质数矩阵”中，只能有一元为数，其他必须均为1！这样才能防止不同角色相乘的积（应用权限）相同。&lt;br /&gt;&lt;br /&gt;构建如下“应用”：&lt;br /&gt;1. 家庭应用：区域（6，1，1，1）；事件：要钱（2，1，1，1），欺负（3，1，1，1）&lt;br /&gt;2. 学校应用：区域（1，6，1，1）；事件：学习（1，2，1，1），购买（1，3，1，1）&lt;br /&gt;3. 社会应用：区域（1，1，6，1）；事件：勾搭（1，1，2，1），购买（1，1，3，1）&lt;br /&gt;4. 公司应用：区域（1，1，1，6）；事件：工资（1，1，1，2），训话（1，1，1，3）&lt;br /&gt;&lt;br /&gt;当面对某“应用”进行“角色”权限判断时：&lt;br /&gt;1. “应用”申请。&lt;br /&gt;2. “角色”是否整除“区域（事件）”（参见下一章节“实现与案例”中的整除定义）？是，继续；否，“应用”返回。&lt;br /&gt;3. “角色”享受“应用”中的服务。&lt;br /&gt;4. “应用”返回。&lt;br /&gt;&lt;br /&gt;谈谈“男人”与“女人”。定义“人”（2，1，1，1），那么“女人”（2×2，1，1，1），“男人”（2×3，1，1，1）。你看，多么和谐的男女平等，与生理学的基因理论又如此贴切！&lt;br /&gt;受质数乘积的限制，建议只使用少数质数作为基本数，而角色的扩充，通过多维矩阵实现。同时引入“排除型应用”，即该应用只记录所有被排除（限制）的角色乘积。实验证明，int型可以接受2到43内的14个质数中的最大6个质数连乘而不溢出，因此，2到43内的质数是非常好的基本数组。这14个质数是（排名不分先后）：&lt;br /&gt;2，3，5，7，11，13，17，19，23，29，31，37，41，43&lt;br /&gt;如果角色中有嵌套行为，可以通过“基因质数”实现，要注意的是，这些角色必须在统一维度。多层嵌套，还可以考虑“质数加权”。&lt;br /&gt; &lt;br /&gt;三、实现与案例&lt;br /&gt;定义1.0：质数（Prime Number）为：P1、P2、P3、P4、……&lt;br /&gt;其中，Pi=2，3，5，7，11，13，……，其中，i=1，2，3，……&lt;br /&gt;&lt;br /&gt;定义1.1：质数（Prime Number）相乘，若：Pi、Pj，&lt;br /&gt;其中，Pi，Pj=2，3，5，7，11，13，……，i，j=1，2，3，……&lt;br /&gt;则Pi×Pj=最小公倍数（Pi，Pj）&lt;br /&gt;&lt;br /&gt;定义1.2：质数（Prime Number）与数（Number）相乘，若：Pi、Nj，&lt;br /&gt;其中，Pi=2，3，5，7，11，13，……，Nj=1，2，3，……，i，j=1，2，3，……&lt;br /&gt;则Pi×Nj=最小公倍数（Pi，Nj）&lt;br /&gt;&lt;br /&gt;定义1.3：数（Number）与质数（Prime Number）相乘，若：Ni、Pj，&lt;br /&gt;其中，Ni=1，2，3，……，Pj=2，3，5，7，11，13，……，i，j=1，2，3，……&lt;br /&gt;则Ni×Pj=最小公倍数（Ni，Pj）&lt;br /&gt;&lt;br /&gt;定义2.0：角色（Role）为：R1、R2、R3、R4、R5、R5、R6、……&lt;br /&gt;其中，Ri=（……，1，1，Pj，1，1，……），简写[j，Pj]，&lt;br /&gt;其中，i，j=1，2，3，……，且j为Pj的维序号&lt;br /&gt;特殊的，约定Pj可以为非质数1，此时为“绝对超级角色”；&lt;br /&gt;约定Pj可以为非质数0，此时为“绝对受限角色”。&lt;br /&gt;&lt;br /&gt;定义2.1：角色（Role）相乘，若：Ri=（……，1，1，Pj，1，1，……），&lt;br /&gt;Rk=（……，1，1，Pj，1，1，……），则Ri×Rk=（……，1，1，Pj×Pj，1，1，……），&lt;br /&gt;其中，i，j，k=1，2，3，……&lt;br /&gt;&lt;br /&gt;定义3.0：应用（Application）为：A1、A2、A3、A4、A5、……&lt;br /&gt;其中，Ai=Rj×Rk×……×Rm，其中，i，j，k，m=1，2，3，……&lt;br /&gt;特殊的，约定Ai可以为非角色积（0，0，……，0），此时为“绝对开放应用”；&lt;br /&gt;约定Ai可以为非角色积（1，1，……，1），此时为“绝对限制应用”。&lt;br /&gt;约定Ai可以为带负号的-（……，Ni，……），此时为“排除型应用”，负号不参与运算。&lt;br /&gt;&lt;br /&gt;推论3.1：应用（Application）与角色（Role）相乘，若：Ai=（Nj，Nk，……，Nm），&lt;br /&gt;Rn=（Po，Pp，……，Pq），则Ai×Rn=（Nj×Po，Nk×Pp，……，Nm×Pq），&lt;br /&gt;其中，i，j，k，m，o，p，q=1，2，3，……&lt;br /&gt;&lt;br /&gt;推论3.2：角色（Role）与应用（Application）相乘，若：Ri=（Pj，Pk，……，Pm），&lt;br /&gt;An=（No，Np，……，Nq），则Ri×An=（Pj×No，Pk×Np，……，Pm×Nq），&lt;br /&gt;其中，i，j，k，m，o，p，q=1，2，3，……&lt;br /&gt;&lt;br /&gt;定义4.0：角色（Role）取摩应用（Application）为：Ri=（Pj，Pk，……，Pm），&lt;br /&gt;An=（No，Np，……，Nq），则Ri|An=（Pj|No，Pk|Np，……，Pm|Nq），&lt;br /&gt;其中，i，j，k，m，o，p，q=1，2，3，……&lt;br /&gt;&lt;br /&gt;定义4.1：角色（Role）整除应用（Application）为：Ri=（Pj，Pk，……，Pm），&lt;br /&gt;An=（No，Np，……，Nq），则Ri|An=（0，0，……，0），&lt;br /&gt;其中，i，j，k，m，o，p，q=1，2，3，……&lt;br /&gt;&lt;br /&gt;定义5：角色（Role）拥有应用（Application）的权限为：该角色整除该“非排除型应用”，或不可整除该“排除型应用”。&lt;br /&gt;&lt;br /&gt;案例：&lt;br /&gt;PPLive网站现有角色4个，分别为：&lt;br /&gt;1. 管理员（RAdmin）&lt;br /&gt;2. 高级用户（RHight）&lt;br /&gt;3. 一般用户（RMiddle）&lt;br /&gt;4. 受限用户（RLow）；&lt;br /&gt;&lt;br /&gt;现有应用4个，分别为：&lt;br /&gt;1. 登录（ALogin），对所有人开放&lt;br /&gt;2. 阅读文章（ARead），对RL不开放&lt;br /&gt;3. 发表文章（ANew），对RH、RA开放&lt;br /&gt;4. 修改删除文章（AEdit），对RA开放&lt;br /&gt;&lt;br /&gt;定义：&lt;br /&gt;RA（2，1），RH（3，1），&lt;br /&gt;RM（1，5），RL（1，7）；&lt;br /&gt;&lt;br /&gt;则：&lt;br /&gt;AL（6，35），AR（6，5），&lt;br /&gt;AN（6，1），AE（2，1）。&lt;br /&gt;&lt;br /&gt;其中，&lt;br /&gt;RA可定义为（1，1），&lt;br /&gt;AL等同于（0，0），&lt;br /&gt;AR等同于-（1，7）&lt;br /&gt;&lt;br /&gt;Howard（howard.queen@hotmail.com）&lt;br /&gt;2007-8-15&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-6321782790834853072?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/6321782790834853072/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=6321782790834853072&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6321782790834853072'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6321782790834853072'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/08/blog-post.html' title='“角色应用权限管理”中“质数”的运用'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-4187474645420590101</id><published>2007-05-22T09:41:00.001+08:00</published><updated>2007-09-04T14:06:03.945+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='设计模式'/><title type='text'>IEnumerable 结合 IEnumerator 的设计思想</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;最近一直在考虑“面向接口编程”的思想。接口的作用大体是为了更好的规范、扩展能力，尤其重要的，它使得一个大的部件在功能上进行有机划分；这种分割使得功能职责简洁明了，确保开发人员不易出错。然则，我一直不甚明白“*able”与“*ator”的关系；或者说，为什么不用一个单单的“*ator”,设计成配对的目的是什么？&lt;br /&gt;以下摘自http://codebetter.com/blogs/david.hayden/archive/2005/03/08/59419.aspx&lt;br /&gt;--------------------------------------------------------------------------------&lt;br /&gt;Implementing IEnumerable and IEnumerator on Your Custom Objects &lt;br /&gt;Often you want to be able to enumerate through a collection of objects using the foreach statement in C#:&lt;br /&gt;&lt;br /&gt;Using foreach in C#&lt;br /&gt;foreach (Student student in myClass)&lt;br /&gt;        Console.WriteLine(student); &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;To be able to pull that off, myClass must implement IEnumerable:&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;IEnumerable Defined&lt;br /&gt;Exposes the enumerator, which supports a simple iteration over a collection.&lt;br /&gt;&lt;br /&gt;public IEnumerator GetEnumerator(); &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;As is says above, IEnumerable just exposes another interface, called IEnumerator:&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;IEnumerator Defined&lt;br /&gt;Supports a simple iteration over a collection.  Enumerators only allow reading the data in the collection. Enumerators cannot be used to modify the underlying collection.&lt;br /&gt;&lt;br /&gt;public object Current;&lt;br /&gt;public void Reset();&lt;br /&gt;public bool MoveNext(); &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;To see this in action, let's create an example by which we can iterate through a list of students in a class using the foreach statement in C#.&lt;br /&gt;&lt;br /&gt;First, we need to create a Student Class as shown below.  At the minimum we want to override ToString() (Overriding System.Object.ToString() and IFormattable) so it says something meaningful and for kicks I decided to override Equals() and GetHashCode() (Object Identity vs. Object Equality - Overriding System.Object.Equals(Object obj)) only as an example.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Student Class&lt;br /&gt;public class Student&lt;br /&gt;{&lt;br /&gt;    #region Private Members&lt;br /&gt;&lt;br /&gt;    private readonly string _id;&lt;br /&gt;    private string _firstname;&lt;br /&gt;    private string _lastname;&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Properties&lt;br /&gt;&lt;br /&gt;    public string ID { get { return _id; } }&lt;br /&gt;&lt;br /&gt;    public string Firstname&lt;br /&gt;    {&lt;br /&gt;        get { return _firstname; }&lt;br /&gt;        set { _firstname = value; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public string Lastname&lt;br /&gt;    {&lt;br /&gt;        get { return _lastname; }&lt;br /&gt;        set { _lastname = value; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Constructors&lt;br /&gt;&lt;br /&gt;    public Student(string id, string firstname, string lastname)&lt;br /&gt;    {&lt;br /&gt;        _id = id;&lt;br /&gt;        _firstname = firstname;&lt;br /&gt;        _lastname = lastname;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Overriding System.Object&lt;br /&gt;&lt;br /&gt;    public override string ToString()&lt;br /&gt;    {&lt;br /&gt;        return String.Format("{0} {1}, ID: {2}", _firstname, _lastname, _id);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public override bool Equals(object obj)&lt;br /&gt;    {&lt;br /&gt;        if (obj == null) return false;&lt;br /&gt;        if (Object.ReferenceEquals(this,obj)) return true;&lt;br /&gt;        if (this.GetType() != obj.GetType()) return false;&lt;br /&gt;&lt;br /&gt;        Student objStudent = (Student)obj;&lt;br /&gt;        if (_id.Equals(objStudent._id)) return true;&lt;br /&gt;&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public override int GetHashCode()&lt;br /&gt;    {&lt;br /&gt;        return _id.GetHashCode();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;} &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;We now need a custom class, called ClassList, that essentially holds the students.  Forgetting IEnumerable for a moment, here is my barebones class.  The class contains an ArrayList, called _students, which is populated with 3 students in its constructor.  The list of students is private to ClassList and is currently not exposed outside of the class.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;ClassList Class with no IEnumerable&lt;br /&gt;public class ClassList&lt;br /&gt;{&lt;br /&gt;    #region Private Members&lt;br /&gt;&lt;br /&gt;    private readonly string _id;&lt;br /&gt;&lt;br /&gt;    private ArrayList _students;&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Properties&lt;br /&gt;&lt;br /&gt;    public string ID { get { return _id; } }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Constructors&lt;br /&gt;&lt;br /&gt;    public ClassList(string id)&lt;br /&gt;    {&lt;br /&gt;        _id = id;&lt;br /&gt;        &lt;br /&gt;        _students = new ArrayList();&lt;br /&gt;&lt;br /&gt;        _students.Add(new Student("12345", "John", "Smith"));&lt;br /&gt;        _students.Add(new Student("09876", "Jane", "Doe"));&lt;br /&gt;        _students.Add(new Student("76403", "Bob", "Johnson"));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;} &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;To support iteration using foreach on the class, I need to implement IEnumerable on ClassList.  Since my students are in an ArrayList, and I know ArrayList implements IEnumerable, I am going to "cheat" and pass back the IEnumerator for _students:&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Using The ArrayList's IEnumerator&lt;br /&gt;public IEnumerator GetEnumerator()&lt;br /&gt;{&lt;br /&gt;    return (_students as IEnumerable).GetEnumerator();&lt;br /&gt;} &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;This will allow me to use foreach on ClassList and here is sample code you can run to see how it works:&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Example 1: Testing The ArrayList's IEnumerator&lt;br /&gt;using System;&lt;br /&gt;using System.Collections;&lt;br /&gt;&lt;br /&gt;public class Student&lt;br /&gt;{&lt;br /&gt;    #region Private Members&lt;br /&gt;&lt;br /&gt;    private readonly string _id;&lt;br /&gt;    private string _firstname;&lt;br /&gt;    private string _lastname;&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Properties&lt;br /&gt;&lt;br /&gt;    public string ID { get { return _id; } }&lt;br /&gt;&lt;br /&gt;    public string Firstname&lt;br /&gt;    {&lt;br /&gt;        get { return _firstname; }&lt;br /&gt;        set { _firstname = value; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public string Lastname&lt;br /&gt;    {&lt;br /&gt;        get { return _lastname; }&lt;br /&gt;        set { _lastname = value; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Constructors&lt;br /&gt;&lt;br /&gt;    public Student(string id, string firstname, string lastname)&lt;br /&gt;    {&lt;br /&gt;        _id = id;&lt;br /&gt;        _firstname = firstname;&lt;br /&gt;        _lastname = lastname;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Overriding System.Object&lt;br /&gt;&lt;br /&gt;    public override string ToString()&lt;br /&gt;    {&lt;br /&gt;        return String.Format("{0} {1}, ID: {2}", _firstname, _lastname, _id);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public override bool Equals(object obj)&lt;br /&gt;    {&lt;br /&gt;        if (obj == null) return false;&lt;br /&gt;        if (Object.ReferenceEquals(this,obj)) return true;&lt;br /&gt;        if (this.GetType() != obj.GetType()) return false;&lt;br /&gt;&lt;br /&gt;        Student objStudent = (Student)obj;&lt;br /&gt;        if (_id.Equals(objStudent._id)) return true;&lt;br /&gt;&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public override int GetHashCode()&lt;br /&gt;    {&lt;br /&gt;        return _id.GetHashCode();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class ClassList : IEnumerable&lt;br /&gt;{&lt;br /&gt;    #region Private Members&lt;br /&gt;&lt;br /&gt;    private readonly string _id;&lt;br /&gt;&lt;br /&gt;    private ArrayList _students;&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Properties&lt;br /&gt;&lt;br /&gt;    public string ID { get { return _id; } }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Constructors&lt;br /&gt;&lt;br /&gt;    public ClassList(string id)&lt;br /&gt;    {&lt;br /&gt;        _id = id;&lt;br /&gt;        &lt;br /&gt;        _students = new ArrayList();&lt;br /&gt;&lt;br /&gt;        _students.Add(new Student("12345", "John", "Smith"));&lt;br /&gt;        _students.Add(new Student("09876", "Jane", "Doe"));&lt;br /&gt;        _students.Add(new Student("76403", "Bob", "Johnson"));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region IEnumerable Members&lt;br /&gt;&lt;br /&gt;    public IEnumerator GetEnumerator()&lt;br /&gt;    {&lt;br /&gt;        return (_students as IEnumerable).GetEnumerator();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;    &lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class MyClass&lt;br /&gt;{&lt;br /&gt;    public static void Main()&lt;br /&gt;    {&lt;br /&gt;        ClassList myClass = new ClassList("History 204");&lt;br /&gt;        &lt;br /&gt;        foreach (Student student in myClass)&lt;br /&gt;            Console.WriteLine(student);&lt;br /&gt;            &lt;br /&gt;        Console.ReadLine();&lt;br /&gt;    }&lt;br /&gt;} &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;If that is all the functionality you need, then passing the ArrayList's IEnumerator is the ticket.  No sense creating your own IEnumerator if you don't have to.&lt;br /&gt;&lt;br /&gt;However, we can create our own class, called ClassEnumerator, that implements IEnumerator and accomplishes the same thing as above.  The class essentially just iterates through the _students arraylist using an index.  Reset() sets the index back to -1. MoveNext() jumps ahead and returns a boolean as to whether we have hit the end.  And, the Current property gets the current student.&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;ClassEnumerator&lt;br /&gt;private class ClassEnumerator : IEnumerator&lt;br /&gt;{&lt;br /&gt;    private ClassList _classList;&lt;br /&gt;    private int _index;&lt;br /&gt;&lt;br /&gt;    public ClassEnumerator(ClassList classList)&lt;br /&gt;    {&lt;br /&gt;        _classList = classList;&lt;br /&gt;        _index = -1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #region IEnumerator Members&lt;br /&gt;&lt;br /&gt;    public void Reset()&lt;br /&gt;    {&lt;br /&gt;        _index = -1;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public object Current&lt;br /&gt;    {&lt;br /&gt;        get&lt;br /&gt;        {&lt;br /&gt;            return _classList._students[_index];&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public bool MoveNext()&lt;br /&gt;    {&lt;br /&gt;        _index++;&lt;br /&gt;        if (_index &gt;= _classList._students.Count)&lt;br /&gt;            return false;&lt;br /&gt;        else&lt;br /&gt;            return true;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;} &lt;br /&gt; &lt;br /&gt;&lt;br /&gt;We will stick ClassEnumerator within ClassList and pass it back via the IEnumerable interface. Here is the entire code listing using our custom IEnumerator:&lt;br /&gt;&lt;br /&gt; &lt;br /&gt;&lt;br /&gt;Testing ClassEnumerator&lt;br /&gt;using System;&lt;br /&gt;using System.Collections;&lt;br /&gt;&lt;br /&gt;public class Student&lt;br /&gt;{&lt;br /&gt;    #region Private Members&lt;br /&gt;&lt;br /&gt;    private readonly string _id;&lt;br /&gt;    private string _firstname;&lt;br /&gt;    private string _lastname;&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Properties&lt;br /&gt;&lt;br /&gt;    public string ID { get { return _id; } }&lt;br /&gt;&lt;br /&gt;    public string Firstname&lt;br /&gt;    {&lt;br /&gt;        get { return _firstname; }&lt;br /&gt;        set { _firstname = value; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public string Lastname&lt;br /&gt;    {&lt;br /&gt;        get { return _lastname; }&lt;br /&gt;        set { _lastname = value; }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Constructors&lt;br /&gt;&lt;br /&gt;    public Student(string id, string firstname, string lastname)&lt;br /&gt;    {&lt;br /&gt;        _id = id;&lt;br /&gt;        _firstname = firstname;&lt;br /&gt;        _lastname = lastname;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Overriding System.Object&lt;br /&gt;&lt;br /&gt;    public override string ToString()&lt;br /&gt;    {&lt;br /&gt;        return String.Format("{0} {1}, ID: {2}", _firstname, _lastname, _id);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public override bool Equals(object obj)&lt;br /&gt;    {&lt;br /&gt;        if (obj == null) return false;&lt;br /&gt;        if (Object.ReferenceEquals(this,obj)) return true;&lt;br /&gt;        if (this.GetType() != obj.GetType()) return false;&lt;br /&gt;&lt;br /&gt;        Student objStudent = (Student)obj;&lt;br /&gt;        if (_id.Equals(objStudent._id)) return true;&lt;br /&gt;&lt;br /&gt;        return false;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    public override int GetHashCode()&lt;br /&gt;    {&lt;br /&gt;        return _id.GetHashCode();&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class ClassList : IEnumerable&lt;br /&gt;{&lt;br /&gt;    #region Private Members&lt;br /&gt;&lt;br /&gt;    private readonly string _id;&lt;br /&gt;&lt;br /&gt;    private ArrayList _students;&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Properties&lt;br /&gt;&lt;br /&gt;    public string ID { get { return _id; } }&lt;br /&gt;&lt;br /&gt;    public int TotalStudents { get { return _students.Count; } }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region Constructors&lt;br /&gt;&lt;br /&gt;    public ClassList(string id)&lt;br /&gt;    {&lt;br /&gt;        _id = id;&lt;br /&gt;        &lt;br /&gt;        _students = new ArrayList();&lt;br /&gt;&lt;br /&gt;        _students.Add(new Student("12345", "John", "Smith"));&lt;br /&gt;        _students.Add(new Student("09876", "Jane", "Doe"));&lt;br /&gt;        _students.Add(new Student("76403", "Bob", "Johnson"));&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region IEnumerable Members&lt;br /&gt;&lt;br /&gt;    public IEnumerator GetEnumerator()&lt;br /&gt;    {&lt;br /&gt;        return (IEnumerator)new ClassEnumerator(this);&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    #endregion&lt;br /&gt;&lt;br /&gt;    #region ClassEnumerator&lt;br /&gt;&lt;br /&gt;    private class ClassEnumerator : IEnumerator&lt;br /&gt;    {&lt;br /&gt;        private ClassList _classList;&lt;br /&gt;        private int _index;&lt;br /&gt;&lt;br /&gt;        public ClassEnumerator(ClassList classList)&lt;br /&gt;        {&lt;br /&gt;            _classList = classList;&lt;br /&gt;            _index = -1;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #region IEnumerator Members&lt;br /&gt;&lt;br /&gt;        public void Reset()&lt;br /&gt;        {&lt;br /&gt;            _index = -1;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public object Current&lt;br /&gt;        {&lt;br /&gt;            get&lt;br /&gt;            {&lt;br /&gt;                return _classList._students[_index];&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        public bool MoveNext()&lt;br /&gt;        {&lt;br /&gt;            _index++;&lt;br /&gt;            if (_index &gt;= _classList._students.Count)&lt;br /&gt;                return false;&lt;br /&gt;            else&lt;br /&gt;                return true;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        #endregion&lt;br /&gt;    }&lt;br /&gt;    &lt;br /&gt;    #endregion&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public class MyClass&lt;br /&gt;{&lt;br /&gt;    public static void Main()&lt;br /&gt;    {&lt;br /&gt;        ClassList myClass = new ClassList("History 204");&lt;br /&gt;        &lt;br /&gt;        Console.WriteLine("Class: {0}, Total Students: {1}\n",&lt;br /&gt;            myClass.ID, myClass.TotalStudents.ToString());&lt;br /&gt;        &lt;br /&gt;        foreach (Student student in myClass)&lt;br /&gt;            Console.WriteLine(student);&lt;br /&gt;            &lt;br /&gt;        Console.ReadLine();&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;--------------------------------------------------------------------------------&lt;br /&gt;注意到，ClassList在实现IEnumerable的GetEnumerator()方法时，有两个选择：调用(cheat)字段ArrayList的GetEnumerator()，或者自行创建ClassEnumerator，再操作。这可能就是“*ator”与“*able”成对出现的原因：灵活性！&lt;br /&gt;这种灵活性体现在，对于外界有一个统一的“*able”接口提供调用，对于内部实现，可以调用(cheat)其他现成的“*ator”，或者自己实现；但“*able”作为规范是必须实现的！&lt;br /&gt;这其实是一个二次规范：“*able”作为必备实现接口，一级规范；“*ator”作为可选实现接口，二级规范。将接口的功能进行了“二次切割”，确实不同凡响。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-4187474645420590101?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/4187474645420590101/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=4187474645420590101&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4187474645420590101'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4187474645420590101'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/ienumerable-ienumerator.html' title='IEnumerable 结合 IEnumerator 的设计思想'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-3778445319417707877</id><published>2007-05-18T13:32:00.000+08:00</published><updated>2007-09-04T10:26:26.654+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='古诗词'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='诗词'/><title type='text'>挽黛玉</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;今生无缘来生见，&lt;br /&gt;携子之手爱缠绵。&lt;br /&gt;茉莉牡丹常相守，&lt;br /&gt;只恨岁月已百年。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-3778445319417707877?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/3778445319417707877/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=3778445319417707877&amp;isPopup=true' title='2 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/3778445319417707877'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/3778445319417707877'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/blog-post.html' title='挽黛玉'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-5034144879486861955</id><published>2007-05-18T13:30:00.000+08:00</published><updated>2007-05-18T13:32:30.076+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Win32'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><title type='text'>c# 配置文件操作（转载）</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;namespace System.Configuration;&lt;br /&gt;&lt;br /&gt;1. 创建配置节类&lt;br /&gt;&lt;br /&gt;必须创建继承自ConfigurationSection的对象才能进行配置数据读写操作，ConfigurationSection提供了索引器用来获取和设置配置数据，需要注意的是拥有ConfigurationProperty特性的属性才会被存储，并且名称要保持大小写完全一致，如下面的代码中，所有的"id"必须保持一样。&lt;br /&gt;&lt;br /&gt;class ConfigSectionData : ConfigurationSection&lt;br /&gt;{&lt;br /&gt;  [ConfigurationProperty("id")]&lt;br /&gt;  public int Id&lt;br /&gt;  {&lt;br /&gt;    get { return (int)this["id"]; }&lt;br /&gt;    set { this["id"] = value; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [ConfigurationProperty("time")]&lt;br /&gt;  public DateTime Time&lt;br /&gt;  {&lt;br /&gt;    get { return (DateTime)this["time"]; }&lt;br /&gt;    set { this["time"] = value; }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;2. 创建配置文件操作对象&lt;br /&gt;&lt;br /&gt;Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);&lt;br /&gt;&lt;br /&gt;ConfigSectionData data = new ConfigSectionData();&lt;br /&gt;data.Id = 1000;&lt;br /&gt;data.Time = DateTime.Now;&lt;br /&gt;&lt;br /&gt;config.Sections.Add("add", data);&lt;br /&gt;config.Save(ConfigurationSaveMode.Minimal);&lt;br /&gt;&lt;br /&gt;上面的例子是操作 app.config，在根节点(configuration)下写入名称为"add"的配置数据。&lt;br /&gt;&lt;br /&gt;&amp;lt?xml version="1.0" encoding="utf-8" ?&amp;gt&lt;br /&gt;&amp;ltconfiguration&amp;gt&lt;br /&gt;  &amp;ltconfigSections&amp;gt&lt;br /&gt;    &amp;ltsection name="add" type="ConsoleApplication1.ConfigSectionData, ... /&amp;gt&lt;br /&gt;  &amp;lt/configSections&amp;gt&lt;br /&gt;  &amp;ltadd id="1000" time="02/18/2006 21:51:06" /&amp;gt&lt;br /&gt;&amp;lt/configuration&amp;gt&lt;br /&gt;&lt;br /&gt;需要注意的 VS2005 在IDE模式下会将信息写入 *.vshost.exe.config，并且在程序关闭时覆写该文件，因此您可能看不到您写入的配置数据，只要在资源管理其中执行 *.exe 文件，您就可以在 *.exe.config 文件中看到结果了。&lt;br /&gt;&lt;br /&gt;如果我们需要操作非缺省配置文件，可以使用ExeConfigurationFileMap对象。&lt;br /&gt;&lt;br /&gt;ExeConfigurationFileMap file = new ExeConfigurationFileMap();&lt;br /&gt;file.ExeConfigFilename = "test.config";&lt;br /&gt;Configuration config = ConfigurationManager.OpenMappedExeConfiguration(file, ConfigurationUserLevel.None);&lt;br /&gt;&lt;br /&gt;ConfigSectionData data = new ConfigSectionData();&lt;br /&gt;data.Id = 1000;&lt;br /&gt;data.Time = DateTime.Now;&lt;br /&gt;&lt;br /&gt;config.Sections.Add("add", data);&lt;br /&gt;config.Save(ConfigurationSaveMode.Minimal);&lt;br /&gt;&lt;br /&gt;如果我们不希望在根节点下写入配置数据，可以使用ConfigurationSectionGroup对象。&lt;br /&gt;&lt;br /&gt;ExeConfigurationFileMap file = new ExeConfigurationFileMap();&lt;br /&gt;file.ExeConfigFilename = "test.config";&lt;br /&gt;Configuration config = ConfigurationManager.OpenMappedExeConfiguration(file, ConfigurationUserLevel.None);&lt;br /&gt;&lt;br /&gt;ConfigSectionData data = new ConfigSectionData();&lt;br /&gt;data.Id = 1000;&lt;br /&gt;data.Time = DateTime.Now;&lt;br /&gt;&lt;br /&gt;config.SectionGroups.Add("group1", new ConfigurationSectionGroup());&lt;br /&gt;config.SectionGroups["group1"].Sections.Add("add", data);&lt;br /&gt;&lt;br /&gt;config.Save(ConfigurationSaveMode.Minimal);&lt;br /&gt;&lt;br /&gt;下面就是生成的配置文件。&lt;br /&gt;&lt;br /&gt;&amp;lt?xml version="1.0" encoding="utf-8"?&amp;gt&lt;br /&gt;&amp;ltconfiguration&amp;gt&lt;br /&gt;  &amp;ltconfigSections&amp;gt&lt;br /&gt;    &amp;ltsectionGroup name="group1" type="System.Configuration.ConfigurationSectionGroup, ... &amp;gt&lt;br /&gt;      &amp;ltsection name="add" type="ConsoleApplication1.ConfigSectionData, ... /&amp;gt&lt;br /&gt;    &amp;lt/sectionGroup&amp;gt&lt;br /&gt;  &amp;lt/configSections&amp;gt&lt;br /&gt;  &amp;ltgroup1&amp;gt&lt;br /&gt;    &amp;ltadd id="1000" time="02/18/2006 22:01:02" /&amp;gt&lt;br /&gt;  &amp;lt/group1&amp;gt&lt;br /&gt;&amp;lt/configuration&amp;gt&lt;br /&gt;&lt;br /&gt;3. 读取配置文件&lt;br /&gt;&lt;br /&gt;ExeConfigurationFileMap file = new ExeConfigurationFileMap();&lt;br /&gt;file.ExeConfigFilename = "test.config";&lt;br /&gt;Configuration config = ConfigurationManager.OpenMappedExeConfiguration(file, ConfigurationUserLevel.None);&lt;br /&gt;&lt;br /&gt;ConfigSectionData data = config.SectionGroups["group1"].Sections["add"] as ConfigSectionData;&lt;br /&gt;//ConfigSectionData data = config.Sections["add"] as ConfigSectionData; // 从根节读取&lt;br /&gt;&lt;br /&gt;if (data != null)&lt;br /&gt;{&lt;br /&gt;  Console.WriteLine(data.Id);&lt;br /&gt;  Console.WriteLine(data.Time);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;4. 写配置文件&lt;br /&gt;&lt;br /&gt;在写入 ConfigurationSectionGroup 和 ConfigurationSection 前要判断同名配置是否已经存在，否则会写入失败。&lt;br /&gt;另外如果配置文件被其他Configuration对象修改，则保存会失败，并抛出异常。建议采用Singleton模式。&lt;br /&gt;&lt;br /&gt;ExeConfigurationFileMap file = new ExeConfigurationFileMap();&lt;br /&gt;file.ExeConfigFilename = "test.config";&lt;br /&gt;Configuration config = ConfigurationManager.OpenMappedExeConfiguration(file, ConfigurationUserLevel.None);&lt;br /&gt;&lt;br /&gt;ConfigSectionData data = new ConfigSectionData();&lt;br /&gt;data.Id = 2000;&lt;br /&gt;data.Time = DateTime.Now;&lt;br /&gt;&lt;br /&gt;ConfigurationSectionGroup group1 = config.SectionGroups["group1"];&lt;br /&gt;if (group1 == null) &lt;br /&gt;  config.SectionGroups.Add("group1", new ConfigurationSectionGroup());&lt;br /&gt;&lt;br /&gt;ConfigurationSection data = group1.Sections["add"] as config;&lt;br /&gt;if (add == null)&lt;br /&gt;  config.SectionGroups["group1"].Sections.Add("add", data);&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;  group1.Sections.Remove("add");&lt;br /&gt;  group1.Sections.Add("add", data);&lt;br /&gt;&lt;br /&gt;  // 或者直接修改原配置对象，前提是类型转换要成功。&lt;br /&gt;  //ConfigSectionData configData = add as ConfigSectionData;&lt;br /&gt;  //configData.Id = data.Id;&lt;br /&gt;  //configData.Time = data.Time;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;config.Save(ConfigurationSaveMode.Minimal);&lt;br /&gt;&lt;br /&gt;5. 删除配置节&lt;br /&gt;&lt;br /&gt;删除ConfigurationSectionGroup &lt;br /&gt;config.SectionGroups.Remove("group1");&lt;br /&gt;//config.SectionGroups.Clear();&lt;br /&gt;&lt;br /&gt;config.Save(ConfigurationSaveMode.Minimal);&lt;br /&gt;&lt;br /&gt;删除ConfigurationSection &lt;br /&gt;config.Sections.Remove("add1");&lt;br /&gt;//config.Sections.Clear();&lt;br /&gt;&lt;br /&gt;if (config.SectionGroups["group1"] != null)&lt;br /&gt;{&lt;br /&gt;  config.SectionGroups["group1"].Sections.Remove("add2");&lt;br /&gt;  //config.SectionGroups["group1"].Sections.Clear();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;config.Save(ConfigurationSaveMode.Minimal);&lt;br /&gt;&lt;br /&gt;6. 其他&lt;br /&gt;&lt;br /&gt;可以使用 ConfigurationManager.OpenMachineConfiguration() 来操作 Machine.config 文件。&lt;br /&gt;或者使用 System.Web.Configuration 名字空间中的 WebConfigurationManager 类来操作 ASP.net 配置文件。&lt;br /&gt;ConfigurationManager还提供了AppSettings、ConnectionStrings、GetSection()等便捷操作。&lt;br /&gt;&lt;br /&gt;7. 使用自定义类 &lt;br /&gt;&lt;br /&gt;2006-4-17 补充，回复 ggy 网友的疑问。 &lt;br /&gt;引用至 ggy&lt;br /&gt;比如ConfigSectionData里面&lt;br /&gt;除了简单类型之外，可不可以有自定义的类&lt;br /&gt;可以使用自定义类，不过需要定义一个转换器。&lt;br /&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Configuration;&lt;br /&gt;using System.Globalization;&lt;br /&gt;using System.ComponentModel;&lt;br /&gt;&lt;br /&gt;// 要写入配置文件的自定义类&lt;br /&gt;class CustomData&lt;br /&gt;{&lt;br /&gt;  public CustomData(string s)&lt;br /&gt;  {&lt;br /&gt;    this.s = s;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  private string s;&lt;br /&gt;  public string S&lt;br /&gt;  {&lt;br /&gt;    get { return s; }&lt;br /&gt;    set { s = value; }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// 自定义的转换器(演示代码省略了类型判断)&lt;br /&gt;class CustomConvert : ConfigurationConverterBase&lt;br /&gt;{&lt;br /&gt;  public override bool CanConvertFrom(ITypeDescriptorContext ctx, Type type)&lt;br /&gt;  {&lt;br /&gt;    return (type == typeof(string));&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public override object ConvertTo(ITypeDescriptorContext ctx, CultureInfo ci, object value, Type type)&lt;br /&gt;  {&lt;br /&gt;    return (value as CustomData).S;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)&lt;br /&gt;  {&lt;br /&gt;    return new CustomData((string)data);;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;class ConfigSectionData : ConfigurationSection&lt;br /&gt;{&lt;br /&gt;  [ConfigurationProperty("id")]&lt;br /&gt;  public int Id&lt;br /&gt;  {&lt;br /&gt;    get { return (int)this["id"]; }&lt;br /&gt;    set { this["id"] = value; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [ConfigurationProperty("time")]&lt;br /&gt;  public DateTime Time&lt;br /&gt;  {&lt;br /&gt;    get { return (DateTime)this["time"]; }&lt;br /&gt;    set { this["time"] = value; }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  [ConfigurationProperty("custom")]&lt;br /&gt;  [TypeConverter(typeof(CustomConvert))] // 指定转换器&lt;br /&gt;  public CustomData Custom&lt;br /&gt;  {&lt;br /&gt;    get { return (CustomData)this["custom"]; }&lt;br /&gt;    set { this["custom"] = value; }&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;  &lt;br /&gt;public class Program&lt;br /&gt;{&lt;br /&gt;  static void Main(string[] args)&lt;br /&gt;  {&lt;br /&gt;    Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);&lt;br /&gt;&lt;br /&gt;    ConfigSectionData data = new ConfigSectionData();&lt;br /&gt;    data.Id = 1000;&lt;br /&gt;    data.Time = DateTime.Now;&lt;br /&gt;    data.Custom = new CustomData("abcdefg...");&lt;br /&gt;&lt;br /&gt;    config.Sections.Add("add", data);&lt;br /&gt;    config.Save(ConfigurationSaveMode.Minimal);&lt;br /&gt;&lt;br /&gt;    // 读取测试&lt;br /&gt;    ConfigSectionData configData = (ConfigSectionData)config.Sections["add"];&lt;br /&gt;    Console.WriteLine(configData.Custom.S);&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;保存后的配置文件 &lt;br /&gt;&amp;lt?xml version="1.0" encoding="utf-8" ?&amp;gt&lt;br /&gt;&amp;ltconfiguration&amp;gt&lt;br /&gt;  &amp;ltconfigSections&amp;gt&lt;br /&gt;    &amp;ltsection name="add" type="..." /&amp;gt&lt;br /&gt;  &amp;lt/configSections&amp;gt&lt;br /&gt;  &amp;ltadd id="1000" time="04/17/2006 22:06:58" custom="abcdefg..." /&amp;gt&lt;br /&gt;&amp;lt/configuration&amp;gt&lt;br /&gt;&lt;br /&gt;更详细的信息可以看 MSDN 中关于 System.Configuration.ConfigurationConverterBase 的说明。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-5034144879486861955?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/5034144879486861955/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=5034144879486861955&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/5034144879486861955'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/5034144879486861955'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/c.html' title='c# 配置文件操作（转载）'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-567522620610482259</id><published>2007-05-11T09:10:00.000+08:00</published><updated>2007-05-11T09:12:18.794+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Win32'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><title type='text'>c#写系统日志(http://www.113317.com/blog/article.asp?id=508)</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.Collections.Generic;&lt;br /&gt;using System.Text;&lt;br /&gt;using System.Diagnostics;&lt;br /&gt;&lt;br /&gt;namespace Log&lt;br /&gt;{&lt;br /&gt;    class LogWirter&lt;br /&gt;    {&lt;br /&gt;        /// &lt;summary&gt;&lt;br /&gt;        /// 事件源名称&lt;br /&gt;        /// &lt;/summary&gt;&lt;br /&gt;        private string eventSourceName;&lt;br /&gt;        EventLogEntryType eventLogType;&lt;br /&gt;        public LogWirter()&lt;br /&gt;        {&lt;br /&gt;            eventSourceName = "test";&lt;br /&gt;            eventLogType = EventLogEntryType.Error;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &lt;summary&gt;&lt;br /&gt;        /// 消息事件源名称&lt;br /&gt;        /// &lt;/summary&gt;&lt;br /&gt;        public string EventSourceName&lt;br /&gt;        {&lt;br /&gt;            set { eventSourceName = value; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &lt;summary&gt;&lt;br /&gt;        /// 消息事件类型&lt;br /&gt;        /// &lt;/summary&gt;&lt;br /&gt;        public EventLogEntryType EventLogType&lt;br /&gt;        {&lt;br /&gt;            set { eventLogType = value; }&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        /// &lt;summary&gt;&lt;br /&gt;        /// 写入系统日志&lt;br /&gt;        /// &lt;/summary&gt;&lt;br /&gt;        /// &lt;param name="message"&gt;事件内容&lt;/param&gt;&lt;br /&gt;        public void LogEvent(string message)&lt;br /&gt;        {&lt;br /&gt;            if (!EventLog.SourceExists(eventSourceName))&lt;br /&gt;            {&lt;br /&gt;                EventLog.CreateEventSource(eventSourceName, "Application");&lt;br /&gt;            }&lt;br /&gt;            EventLog.WriteEntry(eventSourceName, message, EventLogEntryType.Error);&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-567522620610482259?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/567522620610482259/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=567522620610482259&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/567522620610482259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/567522620610482259'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/chttpwww113317comblogarticleaspid508.html' title='c#写系统日志(http://www.113317.com/blog/article.asp?id=508)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-7695846925416996811</id><published>2007-05-11T08:55:00.000+08:00</published><updated>2007-05-11T08:57:49.649+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Windows Service'/><title type='text'>用C#创建Windows Service (http://www.cnblogs.com/guanjinke/archive/2006/12/01/578399.html)</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;现在的&lt;/span&gt;&lt;span&gt;&lt;a title="" href="http://www.cnblogs.com/guanjinke/admin/guanjinke.cnblogs.com"&gt;.NET&lt;/a&gt;&lt;/span&gt;&lt;span&gt;框架已经为&lt;/span&gt;&lt;span&gt;Windows service&lt;/span&gt;&lt;span&gt;的开发提供足够强大的支持&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;你只需要关注&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;所要实现的逻辑&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;而完全不用关心&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;底层是如何实现的&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;相比以前用&lt;/span&gt;&lt;span&gt;MFC&lt;/span&gt;&lt;span&gt;来说&lt;/span&gt;&lt;span&gt;,&lt;/span&gt;&lt;span&gt;真是质的飞跃啊。闲话少谈，看看如何实现一个最基本的&lt;/span&gt;&lt;span&gt;windows service&lt;/span&gt;&lt;span&gt;，以及如何来调试&lt;/span&gt;&lt;span&gt;windows service&lt;/span&gt;&lt;span&gt;。&lt;br&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;span&gt;打开&lt;/span&gt;&lt;span&gt;VS 2005&lt;/span&gt;&lt;span&gt;，点击&lt;/span&gt;&lt;span&gt;File-&amp;gt;New-&amp;gt;Project&amp;#8230;.,&lt;/span&gt;&lt;span&gt;在创建工程向导中选择&lt;/span&gt;&lt;span&gt;Windows service&lt;/span&gt;&lt;span&gt;模板，如下图所示：&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;img height=500 alt="" src="http://photo.bababian.com/20061130/e1ba9e4317da4b791ff9f8e30a084d2f_500.jpg" width=729 border=0&gt;&lt;/img span&gt; &lt;br&gt;&lt;br /&gt;&lt;p&gt;&lt;span&gt;在工程名输入框中，输入&lt;/span&gt;&lt;span lang=EN-US&gt;TestService&lt;/span&gt;&lt;span&gt;然后点击&lt;/span&gt;&lt;span lang=EN-US&gt;OK&lt;/span&gt;&lt;span&gt;。&lt;/span&gt;&lt;span lang=EN-US&gt;VS&lt;/span&gt;&lt;span&gt;为我们生成了最基本的代码，我们将&lt;/span&gt;&lt;span lang=EN-US&gt;Service&lt;/span&gt;&lt;span&gt;的名称改为我们期望的名称，在&lt;/span&gt;&lt;span lang=EN-US&gt;solution explorer&lt;/span&gt;&lt;span&gt;中右键点击&lt;/span&gt;&lt;span lang=EN-US&gt;vs&lt;/span&gt;&lt;span&gt;自动生成的&lt;/span&gt;&lt;span lang=EN-US&gt;service&lt;/span&gt;&lt;span&gt;文件&amp;#8220;&lt;/span&gt;&lt;span lang=EN-US&gt;Service1.cs&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span lang=EN-US&gt;,&lt;/span&gt;&lt;span&gt;在弹出的菜单中选择&lt;/span&gt;&lt;span lang=EN-US&gt;Rename&lt;/span&gt;&lt;span&gt;，输入&amp;#8220;&lt;/span&gt;&lt;span lang=EN-US&gt;MyFirstService&lt;/span&gt;&lt;span&gt;&amp;#8221;，然后切换到设计视图，也就是在&lt;/span&gt;&lt;span lang=EN-US&gt;solution explorer&lt;/span&gt;&lt;span&gt;中双击&lt;/span&gt;&lt;span lang=EN-US&gt;MyfirstService.cs&lt;/span&gt;&lt;span&gt;，在&lt;/span&gt;&lt;span lang=EN-US&gt;Property Explorer&lt;/span&gt;&lt;span&gt;中将&lt;/span&gt;&lt;span lang=EN-US&gt;ServiceName&lt;/span&gt;&lt;span&gt;属性改为&lt;/span&gt;&lt;span lang=EN-US&gt;MyFirstService,&lt;/span&gt;&lt;span&gt;这时一个可运行的&lt;/span&gt;&lt;span lang=EN-US&gt;windows service&lt;/span&gt;&lt;span&gt;已经创建成功。我们添加一些代码来测试一下这个&lt;/span&gt;&lt;span lang=EN-US&gt;service&lt;/span&gt;&lt;span&gt;，最简单的测试方式就是向&lt;/span&gt;&lt;span lang=EN-US&gt;windows event log&lt;/span&gt;&lt;span&gt;里来添加一些消息以显示我们的&lt;/span&gt;&lt;span lang=EN-US&gt;Service&lt;/span&gt;&lt;span&gt;的状态。&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span&gt;我们需要一个&lt;/span&gt;&lt;span&gt;EventLog&lt;/span&gt;&lt;span&gt;组件向&lt;/span&gt;&lt;span&gt;windows log&lt;/span&gt;&lt;span&gt;中添加信息，在&lt;/span&gt;&lt;span&gt;solution explorer&lt;/span&gt;&lt;span&gt;中双击&lt;/span&gt;&lt;span&gt;MyfirstSerice&lt;/span&gt;&lt;span&gt;文件切换到设计视图，将工具箱中的&lt;/span&gt;&lt;span&gt;EventLog&lt;/span&gt;&lt;span&gt;组件拖到设计视图中，我们保留&lt;/span&gt;&lt;span&gt;EventLog&lt;/span&gt;&lt;span&gt;组件的默认名称&lt;/span&gt;&lt;span&gt;eventLog1&lt;/span&gt;&lt;span&gt;。选中&lt;/span&gt;&lt;span&gt;eventLog1&lt;/span&gt;&lt;span&gt;，在&lt;/span&gt;&lt;span&gt;property explorer&lt;/span&gt;&lt;span&gt;中将&lt;/span&gt;&lt;span&gt;Log&lt;/span&gt;&lt;span&gt;属性选为&lt;/span&gt;&lt;span&gt;Application&lt;/span&gt;&lt;span&gt;，在&lt;/span&gt;&lt;span&gt;Source&lt;/span&gt;&lt;span&gt;属性中输入&amp;#8220;&lt;/span&gt;&lt;span&gt;MyFirstService&lt;/span&gt;&lt;span&gt;&amp;#8221;。接下来，我们在设计视图的空白处，右键点击，并选择&lt;/span&gt;&lt;span&gt;View Code&lt;/span&gt;&lt;span&gt;切换到代码视图，在&lt;/span&gt;&lt;span&gt;OnStart&lt;/span&gt;&lt;span&gt;和&lt;/span&gt;&lt;span&gt;OnStop&lt;/span&gt;&lt;span&gt;方法里输入代码实现日志写入，代码如下：&lt;/span&gt;&lt;/span&gt;&lt;span lang=EN-US&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;span id=Codehighlighter1_193_737_Open_Text&gt;&lt;span id=Codehighlighter1_253_735_Open_Text&gt;&lt;span id=Codehighlighter1_295_340_Open_Text&gt;&lt;span id=Codehighlighter1_406_525_Open_Text&gt;&lt;span id=Codehighlighter1_577_729_Open_Text&gt;&lt;span&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top&gt;&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;br /&gt;&lt;div style="BORDER-RIGHT: #cccccc 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #cccccc 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #cccccc 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #cccccc 1px solid; BACKGROUND-COLOR: #eeeeee"&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top&gt;&lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;System;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top&gt;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;System.Collections.Generic;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top&gt;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;System.ComponentModel;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top&gt;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;System.Data;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top&gt;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;System.Diagnostics;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top&gt;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;System.ServiceProcess;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top&gt;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;using&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;System.Text;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top&gt;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top&gt;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;namespace&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;TestService&lt;br&gt;&lt;img id=Codehighlighter1_193_737_Open_Image onclick="this.style.display='none'; Codehighlighter1_193_737_Open_Text.style.display='none'; Codehighlighter1_193_737_Closed_Image.style.display='inline'; Codehighlighter1_193_737_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top&gt;&lt;img id=Codehighlighter1_193_737_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_193_737_Closed_Text.style.display='none'; Codehighlighter1_193_737_Open_Image.style.display='inline'; Codehighlighter1_193_737_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top&gt;&lt;/span&gt;&lt;span id=Codehighlighter1_193_737_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/Images/dot.gif"&gt;&lt;/span&gt;&lt;span id=Codehighlighter1_193_737_Open_Text&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;partial&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;class&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;MyFirstService&amp;nbsp;:&amp;nbsp;ServiceBase&lt;br&gt;&lt;img id=Codehighlighter1_253_735_Open_Image onclick="this.style.display='none'; Codehighlighter1_253_735_Open_Text.style.display='none'; Codehighlighter1_253_735_Closed_Image.style.display='inline'; Codehighlighter1_253_735_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top&gt;&lt;img id=Codehighlighter1_253_735_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_253_735_Closed_Text.style.display='none'; Codehighlighter1_253_735_Open_Image.style.display='inline'; Codehighlighter1_253_735_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span id=Codehighlighter1_253_735_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/Images/dot.gif"&gt;&lt;/span&gt;&lt;span id=Codehighlighter1_253_735_Open_Text&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;MyFirstService()&lt;br&gt;&lt;img id=Codehighlighter1_295_340_Open_Image onclick="this.style.display='none'; Codehighlighter1_295_340_Open_Text.style.display='none'; Codehighlighter1_295_340_Closed_Image.style.display='inline'; Codehighlighter1_295_340_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top&gt;&lt;img id=Codehighlighter1_295_340_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_295_340_Closed_Text.style.display='none'; Codehighlighter1_295_340_Open_Image.style.display='inline'; Codehighlighter1_295_340_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span id=Codehighlighter1_295_340_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/Images/dot.gif"&gt;&lt;/span&gt;&lt;span id=Codehighlighter1_295_340_Open_Text&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top&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;InitializeComponent();&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top&gt;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;protected&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;override&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;OnStart(&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;[]&amp;nbsp;args)&lt;br&gt;&lt;img id=Codehighlighter1_406_525_Open_Image onclick="this.style.display='none'; Codehighlighter1_406_525_Open_Text.style.display='none'; Codehighlighter1_406_525_Closed_Image.style.display='inline'; Codehighlighter1_406_525_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top&gt;&lt;img id=Codehighlighter1_406_525_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_406_525_Closed_Text.style.display='none'; Codehighlighter1_406_525_Open_Image.style.display='inline'; Codehighlighter1_406_525_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span id=Codehighlighter1_406_525_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/Images/dot.gif"&gt;&lt;/span&gt;&lt;span id=Codehighlighter1_406_525_Open_Text&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top&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;/span&gt;&lt;span style="COLOR: #008000"&gt;//&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;&amp;nbsp;TODO:&amp;nbsp;Add&amp;nbsp;code&amp;nbsp;here&amp;nbsp;to&amp;nbsp;start&amp;nbsp;your&amp;nbsp;service.&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&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;eventLog1.WriteEntry(&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;"&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;Service&amp;nbsp;start&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;"&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;);&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top&gt;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;protected&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;override&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;OnStop()&lt;br&gt;&lt;img id=Codehighlighter1_577_729_Open_Image onclick="this.style.display='none'; Codehighlighter1_577_729_Open_Text.style.display='none'; Codehighlighter1_577_729_Closed_Image.style.display='inline'; Codehighlighter1_577_729_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top&gt;&lt;img id=Codehighlighter1_577_729_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_577_729_Closed_Text.style.display='none'; Codehighlighter1_577_729_Open_Image.style.display='inline'; Codehighlighter1_577_729_Open_Text.style.display='inline';" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span id=Codehighlighter1_577_729_Closed_Text style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/Images/dot.gif"&gt;&lt;/span&gt;&lt;span id=Codehighlighter1_577_729_Open_Text&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top&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;/span&gt;&lt;span style="COLOR: #008000"&gt;//&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;&amp;nbsp;TODO:&amp;nbsp;Add&amp;nbsp;code&amp;nbsp;here&amp;nbsp;to&amp;nbsp;perform&amp;nbsp;any&amp;nbsp;tear-down&amp;nbsp;necessary&amp;nbsp;to&amp;nbsp;stop&amp;nbsp;your&amp;nbsp;service.&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&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;eventLog1.WriteEntry(&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;"&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;Service&amp;nbsp;stop&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;"&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;);&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br&gt;&lt;img src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top&gt;&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;要运行这个&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;我们还要做下边的几个步骤：&lt;br&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;1.&lt;/span&gt;&lt;span&gt;为我们的&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;span&gt;添加&lt;/span&gt;&lt;span&gt;Installer&lt;/span&gt;&lt;span&gt;，右键点击设计视图，选择&lt;/span&gt;&lt;span&gt;Add Installer&lt;/span&gt;&lt;span&gt;，&lt;/span&gt;&lt;span&gt;VS&lt;/span&gt;&lt;span&gt;将会为我们添加&lt;/span&gt;&lt;span&gt;ProjectInstaller.cs&lt;/span&gt;&lt;span&gt;，并在&lt;/span&gt;&lt;span&gt;ProjectInstaller&lt;/span&gt;&lt;span&gt;中添加组件&lt;/span&gt;&lt;span&gt;serviceInstaller1&lt;/span&gt;&lt;span&gt;和&lt;/span&gt;&lt;span&gt;serviceProcessInstaller1&lt;/span&gt;&lt;span&gt;，现在我们来修改他们的属性来控制&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;span&gt;的安装和启动选项。在&lt;/span&gt;&lt;span&gt;ProjectInstaller&lt;/span&gt;&lt;span&gt;得设计视图中选中&lt;/span&gt;&lt;span&gt;serviceProcessInstaller1&lt;/span&gt;&lt;span&gt;，将它得&lt;/span&gt;&lt;span&gt;Account&lt;/span&gt;&lt;span&gt;属性选为&lt;/span&gt;&lt;span&gt;LocalSystem&lt;/span&gt;&lt;span&gt;，这样以这个帐号服务启动。如果你希望系统启动时自动启动服务得话，将&lt;/span&gt;&lt;span&gt;serviceInstaller1&lt;/span&gt;&lt;span&gt;的&lt;/span&gt;&lt;span&gt;StartType&lt;/span&gt;&lt;span&gt;的属性选为&lt;/span&gt;&lt;span&gt;Automatic&lt;/span&gt;&lt;span&gt;，如果手动启动的话，选为&lt;/span&gt;&lt;span&gt;manaul&lt;/span&gt;&lt;span&gt;。&lt;br&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;2.&lt;/span&gt;&lt;span&gt;安装&lt;/span&gt;&lt;span&gt;service&lt;/span&gt;&lt;span&gt;，我们要用到&lt;/span&gt;&lt;span&gt;IntallUtil.exe&lt;/span&gt;&lt;span&gt;这个程序，这个程序位于&lt;/span&gt;&lt;span&gt;C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727&lt;/span&gt;&lt;span&gt;。点击开始菜单，选择&amp;#8220;运行&amp;#8221;，在运行对话框中输入&lt;/span&gt;&lt;span&gt;cmd&lt;/span&gt;&lt;span&gt;，进入到命令行窗口，输入&lt;/span&gt;&lt;span&gt;cd :\WINDOWS\Microsoft.NET\Framework\v2.0.50727,&lt;/span&gt;&lt;span&gt;进入到这个目录，然后输入&lt;/span&gt;&lt;span&gt;installutil F:\Programs\C#\TestService\TestService\bin\Debug\testserveice.exe, installutil&lt;/span&gt;&lt;span&gt;后边的内容就是我们的工程生成的可执行程序的路径，情根据需要修改。&lt;br&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;如果你给&lt;/span&gt;&lt;span&gt;ServiceInstaller1&lt;/span&gt;&lt;span&gt;的&lt;/span&gt;&lt;span&gt;StartType&lt;/span&gt;&lt;span&gt;设为&lt;/span&gt;&lt;span&gt;Automatic&lt;/span&gt;&lt;span&gt;的话，安装完服务，服务已经运行起来了，如果&lt;/span&gt;&lt;span&gt;StartType&lt;/span&gt;&lt;span&gt;是&lt;/span&gt;&lt;span&gt;Manual&lt;/span&gt;&lt;span&gt;的话，你需要手动启动。现在我们进入&amp;#8220;服务&amp;#8221;，要打开&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;服务&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;，请单击&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;开始&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;，指向&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;设置&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;，然后单击&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;控制面板&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;。依次单击&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;性能和维护&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;、&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;管理工具&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;，然后双击&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;服务&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;。在里边你应该能够看到我们制作的&lt;/span&gt;&lt;span&gt;Service MyFirstService&lt;/span&gt;&lt;span&gt;。在这里边，我们可以启动，关闭服务，还可以设置服务的启动类型。然后，我们看看服务有没有正确的写入日志，我们需要进入到事件查看器，要打开&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;事件查看器&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;，请单击&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;开始&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;，指向&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;设置&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;，然后单击&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;控制面板&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;。单击&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;性能和维护&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;，单击&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;管理工具&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;，然后双击&lt;/span&gt;&lt;span&gt;&amp;#8220;&lt;/span&gt;&lt;span&gt;事件查看器&lt;/span&gt;&lt;span&gt;&amp;#8221;&lt;/span&gt;&lt;span&gt;。如下图所示，我们的消息已经成功的写到了系统日志里了。&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;img height=500 alt="" src="http://photo.bababian.com/20061130/735EED78CAA907E9B33BFE2C3E8D720C_500.jpg" width=729 border=0&gt;&lt;br&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;如果你不需要这个&lt;/span&gt;&lt;span&gt;Service&lt;/span&gt;&lt;span&gt;了，仍然使用&lt;/span&gt;&lt;span&gt;InstallUtil&lt;/span&gt;&lt;span&gt;这个程序来卸载，不过在&lt;/span&gt;&lt;span&gt;InstallUtil&lt;/span&gt;&lt;span&gt;后跟参数&lt;/span&gt;&lt;span&gt; &lt;span&gt;&amp;#8211;u,&lt;/span&gt;&lt;span&gt;比如&lt;/span&gt;&lt;span&gt;installutil &amp;#8211;u F:\Programs\C#\TestService\TestService\bin\Debug\testserveice.exe&lt;/span&gt;&lt;span&gt;。&lt;br&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Service&lt;/span&gt;&lt;span&gt;的调试方法与普通的程序调试方法是不一样的。我来介绍一下。&lt;br&gt;&lt;span lang=EN-US&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;1．&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span lang=EN-US&gt;Build&lt;/span&gt;&lt;span&gt;你的项目&lt;br&gt;&lt;/span&gt;&lt;span lang=EN-US&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;2．&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;设置断点，因为我们的&lt;/span&gt;&lt;span lang=EN-US&gt;Service&lt;/span&gt;&lt;span&gt;非常的简单，没有什么执行逻辑，所以设置断点没有任何意义，大家可以自己写一些代码来实践。一般来说，我们服务里需要用到一个另外的线程来执行任务，你需要在线程的执行代码中来设置断点。&lt;br&gt;&amp;nbsp;&lt;/span&gt;&lt;span lang=EN-US&gt;&lt;span&gt;3．&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;安装&lt;/span&gt;&lt;span lang=EN-US&gt;service&lt;/span&gt;&lt;span&gt;，我们前边有介绍如何安装。&lt;br&gt;&lt;/span&gt;&lt;span lang=EN-US&gt;&lt;span&gt;&amp;nbsp; 4．&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;如果你的&lt;/span&gt;&lt;span lang=EN-US&gt;Service&lt;/span&gt;&lt;span&gt;启动类型是手动（&lt;/span&gt;&lt;span lang=EN-US&gt;Manual&lt;/span&gt;&lt;span&gt;），你需要到&amp;#8220;服务&amp;#8221;里启动你的&lt;/span&gt;&lt;span lang=EN-US&gt;Service&lt;/span&gt;&lt;span&gt;。一般来说，如果你的&lt;/span&gt;&lt;span lang=EN-US&gt;service&lt;/span&gt;&lt;span&gt;在开发阶段，我推荐你将&lt;/span&gt;&lt;span lang=EN-US&gt;Service&lt;/span&gt;&lt;span&gt;的启动类型设置为&lt;/span&gt;&lt;span lang=EN-US&gt;Manual&lt;/span&gt;&lt;span&gt;，这样便于调试，因为如果&lt;/span&gt;&lt;span lang=EN-US&gt;service&lt;/span&gt;&lt;span&gt;在运行过程中，你将无法&lt;/span&gt;&lt;span lang=EN-US&gt;build&lt;/span&gt;&lt;span&gt;工程。&lt;/span&gt;&lt;span lang=EN-US&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;&amp;nbsp; 5．&lt;span&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;在&lt;/span&gt;&lt;span lang=EN-US&gt;VS&lt;/span&gt;&lt;span&gt;中，从菜单中选择&lt;/span&gt;&lt;span lang=EN-US&gt;Debug-&amp;gt;Attach Process&amp;#8230;.,&lt;/span&gt;&lt;span&gt;将会出现下图：&lt;br&gt;&lt;img height=500 alt="" src="http://photo.bababian.com/20061130/6E225DB26E4DF10CD128B01F9143E3CA_500.jpg" width=729 border=0&gt;&lt;br&gt;里边列出了正在运行的进程，如果你找不到自己的&lt;/span&gt;&lt;span lang=EN-US&gt;service&lt;/span&gt;&lt;span&gt;，请选中&lt;/span&gt;&lt;span lang=EN-US&gt;Show processes from all users&lt;/span&gt;&lt;span&gt;。在&lt;/span&gt;&lt;span lang=EN-US&gt;Available processes&lt;/span&gt;&lt;span&gt;列表中选中我们的&lt;/span&gt;&lt;span lang=EN-US&gt;service&lt;/span&gt;&lt;span&gt;所在的进程&lt;/span&gt;&lt;span lang=EN-US&gt;TestService&lt;/span&gt;&lt;span&gt;，然后点击&lt;/span&gt;&lt;span lang=EN-US&gt;Attach&lt;/span&gt;&lt;span&gt;按钮，如果你设置的断点合理的话，那么，程序就会停在断点处，接下来你就可以进行调试了。&lt;/span&gt;&lt;/p&gt;&lt;br /&gt;&lt;p&gt;&lt;/span&gt;&amp;nbsp;&lt;/p&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-7695846925416996811?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/7695846925416996811/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=7695846925416996811&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/7695846925416996811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/7695846925416996811'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/cwindows-service-httpwwwcnblogscomguanj.html' title='用C#创建Windows Service (http://www.cnblogs.com/guanjinke/archive/2006/12/01/578399.html)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-6101741221916824691</id><published>2007-05-10T09:42:00.000+08:00</published><updated>2007-05-10T09:57:17.570+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Remoting'/><title type='text'>.Net Remoting配置文件的用法</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;How&amp;nbspto&amp;nbspuse&amp;nbsp.Net&amp;nbspRemoting&amp;nbspConfiguration&amp;nbspfiles&lt;br /&gt;&lt;br /&gt;.NET&amp;nbspRemoting&amp;nbspconfiguration&amp;nbspfiles&amp;nbspallow&amp;nbspyou&amp;nbspto&amp;nbspspecify&amp;nbspparameters&amp;nbspfor&amp;nbspmost&amp;nbspaspects&amp;nbspof&amp;nbspthe&amp;nbspremoting&amp;nbspframework.&amp;nbspThese&amp;nbspfiles&amp;nbspcan&amp;nbspdefine&amp;nbsptasks&amp;nbspas&amp;nbspsimple&amp;nbspas&amp;nbspregistering&amp;nbspa&amp;nbspchannel&amp;nbspand&amp;nbspspecifying&amp;nbspa&amp;nbspType&amp;nbspas&amp;nbspa&amp;nbspserver-activated&amp;nbspobject,&amp;nbspor&amp;nbspcan&amp;nbspbe&amp;nbspas&amp;nbspcomplex&amp;nbspas&amp;nbspdefining&amp;nbspa&amp;nbspwhole&amp;nbspchain&amp;nbspof&amp;nbspIMessageSinks&amp;nbspwith&amp;nbspcustom&amp;nbspproperties.&lt;br /&gt;&lt;br /&gt;通过.Net&amp;nbspRemoting配置文件可以为Remote&amp;nbspObjects设定许多参数，如Channel、SAO服务端激活对象类型（Singleton/SingleCall）等等，方便以后在不用修改代码或重新编译的情况下，改变Remote&amp;nbspObjects的行为。&lt;br /&gt;&lt;br /&gt;1，如下是Server端典型的Remoting配置文件：&lt;br /&gt;&amp;lt;?xml&amp;nbspversion="1.0"&amp;nbspencoding="utf-8"&amp;nbsp?&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;lt;system.runtime.remoting&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;application&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;channels&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;channel&amp;nbspref="http"/&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/channels&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;service&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;wellknown&amp;nbspmode="Singleton"&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&amp;nbsp&amp;nbsp&amp;nbsptype="ComponentHost.CustomerManager,&amp;nbspComponentHost"&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&amp;nbsp&amp;nbsp&amp;nbspobjectUri="CustomerManager.soap"&amp;nbsp/&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/service&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/application&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/system.runtime.remoting&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&amp;nbsp&lt;br /&gt;&lt;br /&gt;（1）当Remote&amp;nbspObjects部署在Console/Windows&amp;nbspForm、Windows&amp;nbspServices下时（上面的配置文件channel需要设置port属性），相应Server端声明Remote&amp;nbspObjects的代码可以简化为：&lt;br /&gt;string&amp;nbspfilename&amp;nbsp=&amp;nbsp"server.exe.config";&lt;br /&gt;RemotingConfiguration.Configure(filename);&amp;nbsp&lt;br /&gt;&lt;br /&gt;（2）如果Remote&amp;nbspObjects部署在IIS时，根本就不需要任何代码声明。但是需要将上述配置文件命名为：web.config，并且将Remote&amp;nbspObjects的DLL文件安置在web&amp;nbspapplication的BIN文件夹。&amp;nbsp&lt;br /&gt;一般在实际应用中，基本上将Remote&amp;nbspObjects部署在IIS环境中，好处是（I）不需要编写额外的代码；（II）只要启动机器，远程对象就启动了。不需要你半夜三更跑到公司去登录，然后启动发生故障的远程服务；（III）容易与IIS认证服务进行集成；（IV）可能还有更多优点，我现在没有想到。&amp;nbsp&lt;br /&gt;&lt;br /&gt;（3）如果需要声明多个远程对象，只需要在&amp;lt;service&amp;gt;与&amp;lt;/service&amp;gt;之间添加相应的Remote&amp;nbspObjects配置信息即可。&lt;br /&gt;&lt;br /&gt;（4）另外需要注意type属性为：&amp;lt;namespace&amp;gt;.&amp;lt;class&amp;gt;,&amp;nbsp&amp;lt;assembly&amp;gt;&amp;nbsp&lt;br /&gt;&lt;br /&gt;2，如下是Client端典型的配置文件：&lt;br /&gt;&amp;lt;?xml&amp;nbspversion="1.0"&amp;nbspencoding="utf-8"&amp;nbsp?&amp;gt;&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;lt;system.runtime.remoting&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;application&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;client&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;wellknown&amp;nbsptype="ComponentHost.CustomerManager,&amp;nbspRemotingTest"&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&amp;nbsp&amp;nbsp&amp;nbspurl="http://localhost/ComponentHost/CustomerManager.soap"&amp;nbsp/&amp;gt;&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;lt;/client&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/application&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;lt;/system.runtime.remoting&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&amp;nbsp&lt;br /&gt;&lt;br /&gt;要注意type属性的设定：&amp;lt;namespace&amp;gt;.&amp;lt;class&amp;gt;,&amp;nbsp&amp;lt;assembly&amp;gt;&lt;br /&gt;&lt;br /&gt;如果Client通过SoapSuds产生Remote&amp;nbspObjects的元数据assembly，或者是Shared&amp;nbspAssembly（如Interface或Abstract&amp;nbspClass），这里&amp;lt;assembly&amp;gt;则为上述assembly的名称。&lt;br /&gt;&lt;br /&gt;如果是通过SoapSuds产生Source&amp;nbspcode，则&amp;lt;assembly&amp;gt;为Client应用程序名（无exe后缀）。&amp;nbsp&lt;br /&gt;&lt;br /&gt;同时，Client端application调用Remote&amp;nbspObjects时，可以省掉：注册通道、Activator.GetObject()/RemotingConfiguration.RegisterActivatedServiceType()等代码，取而代之的代码为：&lt;br /&gt;string&amp;nbspfilename&amp;nbsp=&amp;nbsp“clientApplication.exe.config”;&lt;br /&gt;RemotingConfiguration.Configure(filename);&lt;br /&gt;&lt;br /&gt;下面通过new来创建Remote&amp;nbspObject实例。&amp;nbsp&lt;br /&gt;&lt;br /&gt;3，标准的.Net&amp;nbspRemoting&amp;nbspConfiguration配置文件&lt;br /&gt;&lt;br /&gt;MSDN中有.Net&amp;nbspRemoting&amp;nbspConfiguration&amp;nbspfile中全部元素/属性的完整的详细说明，需要的时候再查阅了。一般情况下，知道下面这些属性就够用了。&lt;br /&gt;&amp;lt;configuration&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;system.runtime.remoting&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;application&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;lifetime&amp;nbsp/&amp;gt;&amp;nbsp――&amp;nbsp配置Remote&amp;nbspObjects生存期的信息&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;channels&amp;nbsp/&amp;gt;&amp;nbsp――&amp;nbsp配置与远程对象进行通信的信道&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;service&amp;nbsp/&amp;gt;&amp;nbsp&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;client&amp;nbsp/&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/application&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/system.runtime.remoting&amp;gt;&lt;br /&gt;&amp;lt;/configuration&amp;gt;&lt;br /&gt;&lt;br /&gt;简单说明：&lt;br /&gt;（1）&amp;lt;service&amp;gt;&amp;nbsp――&amp;nbsp仅在Server端配置&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;service&amp;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;lt;wellknown&amp;nbsp/&amp;gt;&amp;nbsp――&amp;nbsp配置要发布的SAO（已知）对象的信息&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;activated&amp;nbsp/&amp;gt;&amp;nbsp――&amp;nbsp配置要发布的CAO客户端激活对象的信息&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/service&amp;gt;&amp;nbsp&lt;br /&gt;&lt;br /&gt;（2）&amp;lt;client&amp;gt;&amp;nbsp――&amp;nbsp仅在Client端配置，与Server端&amp;lt;service&amp;gt;对应&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;client&amp;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&amp;lt;wellknown&amp;nbsp/&amp;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&amp;lt;activated&amp;nbsp/&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/client&amp;gt;&lt;br /&gt;&lt;br /&gt;When&amp;nbspusing&amp;nbspCAOs,&amp;nbspthe&amp;nbsp&amp;lt;client&amp;gt;&amp;nbspproperty&amp;nbsphas&amp;nbspto&amp;nbspspecify&amp;nbspthe&amp;nbspURI&amp;nbspto&amp;nbspthe&amp;nbspserver&amp;nbspfor&amp;nbspall&amp;nbspunderlying&amp;nbsp&amp;lt;activated&amp;gt;&amp;nbspentries.&lt;br /&gt;&lt;br /&gt;Note：When&amp;nbspusing&amp;nbspCAOs&amp;nbspfrom&amp;nbspmore&amp;nbspthan&amp;nbspone&amp;nbspserver,&amp;nbspyou&amp;nbsphave&amp;nbspto&amp;nbspcreate&amp;nbspseveral&amp;nbsp&amp;lt;client&amp;gt;&amp;nbspproperties&amp;nbspin&amp;nbspyour&amp;nbspconfiguration&amp;nbspfile.&lt;br /&gt;&lt;br /&gt;当调用CAO远程对象时，必须设定&amp;lt;client&amp;gt;的url属性。如果CAO来自不同的Server，则需要在配置文件中定义多个&amp;lt;client&amp;gt;。如下所示：&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;client&amp;nbspurl="http://localhost/MyServer&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;activated&amp;nbsptype="Server.MyRemote,&amp;nbspClient"&amp;nbsp/&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/client&amp;gt;&lt;br /&gt;&lt;br /&gt;4，定制Client/Server&amp;nbspChannel元素&lt;br /&gt;&lt;br /&gt;（1）Client&amp;nbspSide&lt;br /&gt;&amp;lt;channel&amp;nbspref="http"&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;clientProviders&amp;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;lt;formatter&amp;nbspref="binary"&amp;nbsp/&amp;gt;&amp;nbsp&amp;nbsp&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/clientProviders&amp;gt;&lt;br /&gt;&amp;lt;/channel&amp;gt;&lt;br /&gt;&lt;br /&gt;其中，formatter&amp;nbspref=”binary”&amp;nbspor&amp;nbsp“soap”。formatter&amp;nbspref指要在通道上发送的消息格式，在此示例中为二进制，以增强性能。&amp;nbsp&lt;br /&gt;&lt;br /&gt;（2）Server&amp;nbspSide&lt;br /&gt;&amp;lt;channel&amp;nbspref="http"&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;serverProviders&amp;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;lt;provider&amp;nbspref="wsdl"&amp;nbsp/&amp;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;lt;formatter&amp;nbspref="binary"&amp;nbsptypeFileterLevel="Full"&amp;nbsp/&amp;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;lt;formatter&amp;nbspref="soap"&amp;nbsptypeFileterLevel="Full"&amp;nbsp/&amp;gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp&amp;lt;/serverProviders&amp;gt;&lt;br /&gt;&amp;lt;/channels&amp;gt;&amp;nbsp&amp;nbsp&amp;nbsp&lt;br /&gt;&lt;br /&gt;typeFilterLevel表示当前自动反序列化级别，支持的值包括&amp;nbspLow（默认值）和&amp;nbspFull。&lt;br /&gt;&lt;br /&gt;Reference:&lt;br /&gt;1.&amp;nbspIngo&amp;nbspRammer,&amp;nbspAdvanced&amp;nbsp.Net&amp;nbspRemoting.&lt;br /&gt;2.&amp;nbspMSDN&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-6101741221916824691?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/6101741221916824691/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=6101741221916824691&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6101741221916824691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6101741221916824691'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/net-remoting.html' title='.Net Remoting配置文件的用法'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-8879838629416667824</id><published>2007-05-09T09:15:00.000+08:00</published><updated>2007-05-10T09:57:42.890+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Windows Service'/><title type='text'>使用C#控制远程计算机的服务（http://www.cnblogs.com/onekey/archive/2004/08/25/36513.aspx）</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp在.net中提供了一些类来显示和控制Windows系统上的服务，并可以实现对远程计算机服务服务的访问，如System.ServiceProcess命名空间下面的ServiceController 类，System.Management下面的一些WMI操作的类。虽然用ServiceController可以很方便的实现对服务的控制，而且很直观、简洁和容易理解。但是我认为他的功能同通过WMI来操作服务相比，那可能就有些单一了，并且对多个服务的操作可能就比较麻烦，也无法列出系统中的所有服务的具体数据。这里要讲的就是如何使用System.Management组件来操作远程和本地计算机上的服务。&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbspWMI作为Windows 2000操作系统的一部分提供了可伸缩的,可扩展的管理架构.公共信息模型（CIM）是由分布式管理任务标准协会（DMTF）设计的一种可扩展的、面向对象的架构，用于管理系统、网络、应用程序、数据库和设备。Windows管理规范也称作CIM for Windows，提供了统一的访问管理信息的方式。如果需要获取详细的WMI信息请读者查阅MSDN。System.Management组件提供对大量管理信息和管理事件集合的访问，这些信息和事件是与根据 Windows 管理规范 (WMI) 结构对系统、设备和应用程序设置检测点有关的。&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp但是上面并不是我们最关心的，下面才是我们需要谈的话题。&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp毫无疑问，我们要引用System.Management.Dll程序集，并要使用System.Management命名空间下的类，如ManagementClass,ManagementObject等。下面用一个名为Win32ServiceManager的类把服务的一些相关操作包装了一下，代码如下：&lt;br /&gt;using System;&lt;br /&gt;using System.Management;&lt;br /&gt;namespace ZZ.Wmi{&lt;br /&gt;     public class Win32ServiceManager{&lt;br /&gt;         private string strPath;&lt;br /&gt;         private ManagementClass managementClass;&lt;br /&gt;         public Win32ServiceManager():this(".",null,null){&lt;br /&gt;         }&lt;br /&gt;         public Win32ServiceManager(string host,string userName,string password){&lt;br /&gt;              this.strPath = "\\\\"+host+"\\root\\cimv2:Win32_Service";&lt;br /&gt;              this.managementClass = new ManagementClass(strPath);&lt;br /&gt;               if(userName!=null&amp;&amp;userName.Length&gt;0){&lt;br /&gt;                   ConnectionOptions connectionOptions = new ConnectionOptions();&lt;br /&gt;                   connectionOptions.Username = userName;&lt;br /&gt;                   connectionOptions.Password = password;&lt;br /&gt;                   ManagementScope managementScope = new ManagementScope( "\\\\" +host+ "\\root\\cimv2",connectionOptions) ;&lt;br /&gt;                   this.managementClass.Scope = managementScope;&lt;br /&gt;              }&lt;br /&gt;         } &lt;br /&gt;         // 验证是否能连接到远程计算机&lt;br /&gt;         public static bool RemoteConnectValidate(string host,string userName,string password){&lt;br /&gt;              ConnectionOptions connectionOptions = new ConnectionOptions();&lt;br /&gt;              connectionOptions.Username = userName;&lt;br /&gt;              connectionOptions.Password = password;&lt;br /&gt;              ManagementScope managementScope = new ManagementScope( "\\\\" +host+ "\\root\\cimv2",connectionOptions) ;&lt;br /&gt;              try{&lt;br /&gt;                   managementScope.Connect();&lt;br /&gt;              }&lt;br /&gt;              catch{&lt;br /&gt;              }&lt;br /&gt;              return managementScope.IsConnected;&lt;br /&gt;         }&lt;br /&gt;         // 获取指定服务属性的值&lt;br /&gt;         public object GetServiceValue(string serviceName,string propertyName){&lt;br /&gt;              ManagementObject mo = this.managementClass.CreateInstance();&lt;br /&gt;              mo.Path = new ManagementPath(this.strPath+".Name=\""+serviceName+"\"");&lt;br /&gt;              return mo[propertyName];&lt;br /&gt;         }&lt;br /&gt;         // 获取所连接的计算机的所有服务数据&lt;br /&gt;         public string [,] GetServiceList(){&lt;br /&gt;              string [,] services = new string [this.managementClass.GetInstances().Count,4];&lt;br /&gt;              int i = 0;&lt;br /&gt;              foreach(ManagementObject mo in this.managementClass.GetInstances())&lt;br /&gt;              {&lt;br /&gt;                   services[i,0] = (string)mo["Name"];&lt;br /&gt;                   services[i,1] = (string)mo["DisplayName"];&lt;br /&gt;                   services[i,2] = (string)mo["State"];&lt;br /&gt;                   services[i,3] = (string)mo["StartMode"];&lt;br /&gt;                   i++;&lt;br /&gt;              }&lt;br /&gt;              return services;&lt;br /&gt;         }&lt;br /&gt;         // 获取所连接的计算机的指定服务数据&lt;br /&gt;         public string [,] GetServiceList(string serverName){&lt;br /&gt;              return GetServiceList(new string []{serverName});&lt;br /&gt;         }&lt;br /&gt;         // 获取所连接的计算机的的指定服务数据&lt;br /&gt;         public string [,] GetServiceList(string [] serverNames){&lt;br /&gt;              string [,] services = new string [serverNames.Length,4];&lt;br /&gt;              ManagementObject mo = this.managementClass.CreateInstance();&lt;br /&gt;              for(int i = 0;i&lt;serverNames.Length;i++)&lt;br /&gt;              {&lt;br /&gt;                   mo.Path = new ManagementPath(this.strPath+".Name=\""+serverNames[i]+"\"");&lt;br /&gt;                   services[i,0] = (string)mo["Name"];&lt;br /&gt;                   services[i,1] = (string)mo["DisplayName"];&lt;br /&gt;                   services[i,2] = (string)mo["State"];&lt;br /&gt;                   services[i,3] = (string)mo["StartMode"];&lt;br /&gt;              }&lt;br /&gt;              return services;&lt;br /&gt;         }&lt;br /&gt;         // 停止指定的服务&lt;br /&gt;         public string StartService(string serviceName){&lt;br /&gt;              string strRst = null;&lt;br /&gt;              ManagementObject mo = this.managementClass.CreateInstance();&lt;br /&gt;              mo.Path = new ManagementPath(this.strPath+".Name=\""+serviceName+"\"");&lt;br /&gt;              try&lt;br /&gt;              {&lt;br /&gt;                   if((string)mo["State"]=="Stopped")//!(bool)mo["AcceptStop"]&lt;br /&gt;                       mo.InvokeMethod("StartService",null);&lt;br /&gt;              }&lt;br /&gt;              catch(ManagementException e)&lt;br /&gt;              {&lt;br /&gt;                   strRst =e.Message; &lt;br /&gt;              }&lt;br /&gt;              return strRst;&lt;br /&gt;         }&lt;br /&gt;         // 暂停指定的服务&lt;br /&gt;         public string PauseService(string serviceName){&lt;br /&gt;              string strRst = null;&lt;br /&gt;              ManagementObject mo = this.managementClass.CreateInstance();&lt;br /&gt;              mo.Path = new ManagementPath(this.strPath+".Name=\""+serviceName+"\"");&lt;br /&gt;              try&lt;br /&gt;              {&lt;br /&gt;                   //判断是否可以暂停&lt;br /&gt;                   if((bool)mo["acceptPause"]&amp;&amp;(string)mo["State"]=="Running")&lt;br /&gt;                       mo.InvokeMethod("PauseService",null);&lt;br /&gt;              }&lt;br /&gt;              catch(ManagementException e)&lt;br /&gt;              {&lt;br /&gt;                   strRst =e.Message; &lt;br /&gt;              }&lt;br /&gt;              return strRst;&lt;br /&gt;         }&lt;br /&gt;         // 恢复指定的服务&lt;br /&gt;         public string ResumeService(string serviceName){&lt;br /&gt;              string strRst = null;&lt;br /&gt;              ManagementObject mo = this.managementClass.CreateInstance();&lt;br /&gt;              mo.Path = new ManagementPath(this.strPath+".Name=\""+serviceName+"\"");&lt;br /&gt;              try&lt;br /&gt;              {&lt;br /&gt;                   //判断是否可以恢复&lt;br /&gt;                   if((bool)mo["acceptPause"]&amp;&amp;(string)mo["State"]=="Paused")&lt;br /&gt;                       mo.InvokeMethod("ResumeService",null);&lt;br /&gt;              }&lt;br /&gt;              catch(ManagementException e)&lt;br /&gt;              {&lt;br /&gt;                   strRst =e.Message; &lt;br /&gt;              }&lt;br /&gt;              return strRst;&lt;br /&gt;         }&lt;br /&gt;         // 停止指定的服务&lt;br /&gt;         public string StopService(string serviceName){&lt;br /&gt;              string strRst = null;&lt;br /&gt;              ManagementObject mo = this.managementClass.CreateInstance();&lt;br /&gt;              mo.Path = new ManagementPath(this.strPath+".Name=\""+serviceName+"\"");&lt;br /&gt;              try&lt;br /&gt;              {&lt;br /&gt;                   //判断是否可以停止&lt;br /&gt;                   if((bool)mo["AcceptStop"])//(string)mo["State"]=="Running"&lt;br /&gt;                       mo.InvokeMethod("StopService",null);&lt;br /&gt;              }&lt;br /&gt;              catch(ManagementException e)&lt;br /&gt;              {&lt;br /&gt;                   strRst =e.Message; &lt;br /&gt;              }&lt;br /&gt;              return strRst;&lt;br /&gt;         }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp在Win32ServiceManager中通过RemoteConnectValidate静态方法来测试连接成功与否；另外提供了GetServiceValue方法和GetServiceList方法以及它的重载来获取服务信息；后面的四个方法就是对服务的状态控制了。&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp下面建立一个简单的窗口来使用它。&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp大致的界面如下：&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;通过vs.net 2003可以很快做出上面的窗体，下面列出了一些增加的代码：&lt;br /&gt;using ZZ.Wmi;&lt;br /&gt;namespace ZZForm{&lt;br /&gt;     public class Form1 : System.Windows.Forms.Form{&lt;br /&gt;         //……&lt;br /&gt;         private Win32ServiceManager serviceManager;&lt;br /&gt;         public Form1(){&lt;br /&gt;              InitializeComponent();&lt;br /&gt;              this.serviceManager = null;&lt;br /&gt;         }&lt;br /&gt;         //……&lt;br /&gt;         [STAThread]&lt;br /&gt;         static void Main() {&lt;br /&gt;              Application.Run(new Form1());&lt;br /&gt;         }&lt;br /&gt;         //修改服务状态&lt;br /&gt;         private void buttonChangeState_Click(object sender, System.EventArgs e){&lt;br /&gt;              switch(((Button)sender).Text){&lt;br /&gt;                   case "启动":&lt;br /&gt;                       string startRst = this.serviceManager.StartService(this.listViewService.SelectedItems[0].SubItems[0].Text);&lt;br /&gt;                       if(startRst==null)&lt;br /&gt;                            MessageBox.Show("操作成功,请点击获取刷新按钮刷新结果!");&lt;br /&gt;                       else&lt;br /&gt;                            MessageBox.Show(startRst);&lt;br /&gt;                       break;&lt;br /&gt;                   case "暂停":&lt;br /&gt;                       string startPause = this.serviceManager.PauseService(this.listViewService.SelectedItems[0].SubItems[0].Text);&lt;br /&gt;                       if(startPause==null)&lt;br /&gt;                            MessageBox.Show("操作成功,请点击获取刷新按钮刷新结果!");&lt;br /&gt;                       else&lt;br /&gt;                            MessageBox.Show(startPause);&lt;br /&gt;                       break;&lt;br /&gt;                   case "继续":&lt;br /&gt;                       string startResume = this.serviceManager.ResumeService(this.listViewService.SelectedItems[0].SubItems[0].Text);&lt;br /&gt;                       if(startResume==null)&lt;br /&gt;                            MessageBox.Show("操作成功,请点击获取刷新按钮刷新结果!");&lt;br /&gt;                       else&lt;br /&gt;                            MessageBox.Show(startResume);&lt;br /&gt;                       break;&lt;br /&gt;                   case "停止":&lt;br /&gt;                       string startStop = this.serviceManager.StopService(this.listViewService.SelectedItems[0].SubItems[0].Text);&lt;br /&gt;                       if(startStop==null)&lt;br /&gt;                            MessageBox.Show("操作成功,请点击获取刷新按钮刷新结果!");&lt;br /&gt;                       else&lt;br /&gt;                            MessageBox.Show(startStop);&lt;br /&gt;                       break;&lt;br /&gt;              }&lt;br /&gt;         }&lt;br /&gt; &lt;br /&gt;         //获取和刷新数据&lt;br /&gt;         private void buttonLoadRefresh_Click(object sender, System.EventArgs e){&lt;br /&gt;              if(this.textBoxHost.Text.Trim().Length&gt;0){&lt;br /&gt;                   if(this.textBoxHost.Text.Trim()=="."){&lt;br /&gt;                       this.serviceManager = new Win32ServiceManager();&lt;br /&gt;                   }&lt;br /&gt;                   else{&lt;br /&gt;                        if(Win32ServiceManager.RemoteConnectValidate(this.textBoxHost.Text.Trim(),this.textBoxName.Text.Trim(),this.textBoxPassword.Text.Trim())){&lt;br /&gt;                            this.serviceManager = new Win32ServiceManager(this.textBoxHost.Text.Trim(),this.textBoxName.Text.Trim(),this.textBoxPassword.Text.Trim());&lt;br /&gt;                       }&lt;br /&gt;                       else{&lt;br /&gt;                            MessageBox.Show("连接到远程计算机验证错误.");&lt;br /&gt;                            return;&lt;br /&gt;                       }&lt;br /&gt;                   }&lt;br /&gt;                   string [,] services = serviceManager.GetServiceList();&lt;br /&gt;                   this.listViewService.BeginUpdate();&lt;br /&gt;                   this.listViewService.Items.Clear();&lt;br /&gt;                   for(int i=0;i&amp;lt;services.GetLength(0);i++){&lt;br /&gt;                       ListViewItem item = new ListViewItem(new string[]{services[i,0],services[i,1],services[i,2],services[i,3]});&lt;br /&gt;                       this.listViewService.Items.Add(item);&lt;br /&gt;                   }&lt;br /&gt;                   this.listViewService.EndUpdate();&lt;br /&gt;              }&lt;br /&gt;              else&lt;br /&gt;                   MessageBox.Show("请输入计算机名或IP地址");&lt;br /&gt;         }&lt;br /&gt;    }&lt;br /&gt;}&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp说明，其实一个服务的属性和方法除了上面这几个还有很多，我们可以通过实例化ManagementClass类，使用它的Properties属性和Methods属性列出所有的属性和方法。上面的Win32ServiceManager中生成的每个服务实例都是ManagementObejct类型的，其实还有一种强类型的类，可以通过编程和工具来生成。&lt;br /&gt;&amp;nbsp&amp;nbsp&amp;nbsp&amp;nbsp总结，通过引用System.Management命名空间，上面简单的实现了通过访问\root\cimv2:Win32_Service名称空间对服务进行显示和操作。此外，我们还可以通过访问其他名称空间来访问计算机的一些硬件信息，软件信息以及网络等，有兴趣的读者可以研究一下。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-8879838629416667824?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/8879838629416667824/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=8879838629416667824&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/8879838629416667824'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/8879838629416667824'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/httpbeautyhill.html' title='使用C#控制远程计算机的服务（http://www.cnblogs.com/onekey/archive/2004/08/25/36513.aspx）'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-995523317755481480</id><published>2007-05-09T08:55:00.000+08:00</published><updated>2007-05-10T09:57:42.891+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Windows Service'/><title type='text'>控制系统服务[Windows Services](http://www.rainsts.net/article.asp?id=76)</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;可以使用System.ServiceProcess.ServiceController类控制Windows Services。&lt;br /&gt;CUI项目需要添加System.ServiceProcess引用。&lt;br /&gt;&lt;br /&gt;注意服务名称和显示名称是不同的，我们调用时使用的是服务名称。在服务名称单击右键，其属性窗口中可看到详细信息。&lt;br /&gt;如自动更新服务，“Automatic Updates”是显示名称，其服务名称是：wuauserv。&lt;br /&gt;&lt;br /&gt;1. 获取全部服务及其状态&lt;br /&gt;ServiceController[] scs = ServiceController.GetServices();&lt;br /&gt;foreach (ServiceController sc in scs)&lt;br /&gt;{&lt;br /&gt;  Console.WriteLine("{0}({1}); Status:{2}", sc.DisplayName, sc.ServiceName, sc.Status);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;2. 检查服务是否已经安装&lt;br /&gt;bool exists = false;&lt;br /&gt;ServiceController[] scs = ServiceController.GetServices();&lt;br /&gt;foreach (ServiceController sc in scs)&lt;br /&gt;{&lt;br /&gt;  if (string.Compare(sc.ServiceName, "MSSQLSERVER", true) == 0)&lt;br /&gt;  {&lt;br /&gt;    exists = true;&lt;br /&gt;    break;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;3. 检查服务状态&lt;br /&gt;ServiceController sc = new ServiceController("MSSQLSERVER");&lt;br /&gt;if (sc.Status == ServiceControllerStatus.Stopped)&lt;br /&gt;  Console.WriteLine("Stopped");&lt;br /&gt;&lt;br /&gt;4. 启动或停止服务 (可能还要用到CanStop等属性)&lt;br /&gt;ServiceController sc = new ServiceController("MSSQLSERVER");&lt;br /&gt;if (sc.Status == ServiceControllerStatus.Stopped)&lt;br /&gt;{&lt;br /&gt;  sc.Start();&lt;br /&gt;  sc.WaitForStatus(ServiceControllerStatus.Running);&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;  sc.Stop();&lt;br /&gt;  sc.WaitForStatus(ServiceControllerStatus.Stopped);&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-995523317755481480?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/995523317755481480/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=995523317755481480&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/995523317755481480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/995523317755481480'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/windows-serviceshttpwwwrainstsnetarticl.html' title='控制系统服务[Windows Services](http://www.rainsts.net/article.asp?id=76)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-9208487721119076932</id><published>2007-05-08T13:15:00.000+08:00</published><updated>2007-05-10T09:57:42.892+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Windows Service'/><title type='text'>调用API注册和注销Windows Service (http://blog.csdn.net/Mittermeyer/archive/2004/01/04/11653.aspx)</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;0、写在前面&lt;br /&gt;    DotNET平台下的类库封装的相当完善，普通的应用完全可以利用类库完成所有的工作。对于Windows Service的支持也是一样，只需要继承DotNET下提供的ServiceBase就可以创建Windows的Service，调用ServiceControl类的方法就可以控制Service的启动和关闭，非常容易。&lt;br /&gt;    然而生成了一个Service类型的应用程序之后，必须在SCM（Service Control Manager）中注册，才能够被当作一个Service被系统调用。但是对于Service的注册和注销却比较麻烦，DotNET的确也提供了对应的类ServiceInstaller和ServiceProcessInstaller，但是只能够和Installer的安装过程集成使用，不能够单独在普通应用程序中调用，也就是说为了安装一个Service用作测试，我不得不创建一个安装包。&lt;br /&gt;    怎样利用API向SCM注册以及注销一个Service呢，下面就简单的介绍一下。&lt;br /&gt; &lt;br /&gt;1、实现概述&lt;br /&gt;    打开Control Panel中Service的管理工具，可以看到本机所有已注册的Service，选择一个Service的属性会发现一个Service有很多设置项：名称、描述、类型、运行帐号等。所有这些都可以通过调用API函数来设定。&lt;br /&gt;    在Service的API中，每一个服务的实例通过句柄来表示，而需要服务的句柄之前必须要先要的到SCM的句柄（Handle），所以所有的调用都是通过OpenSCManager开始，成功的调用OpenSCManager后将获得一个SCM的句柄。如果是注册Service，那么利用SCM句柄调用CreateService来创建一个新的服务；如果是注销Service，则调用OpenService函数，获得一个已经存在的Service的句柄，然后利用这个服务句柄调用DeleteService注销服务。最后通过CloseServiceHandle关闭Service的句柄和SCM的句柄。&lt;br /&gt;    过程很简单，在CSharp下比较麻烦的地方就是API的声明，下面会一一提到。&lt;br /&gt; &lt;br /&gt;2、注册Service&lt;br /&gt;    前面已经提到注册Service一共用到了三个API，OpenSCManager、CreateService和CloseServiceHandle。使用之前先介绍一下这些API的声明。&lt;br /&gt;  [DllImport("advapi32.dll")]&lt;br /&gt;  public static extern System.IntPtr OpenSCManager(&lt;br /&gt;    System.String lpMachineName,&lt;br /&gt;    System.String lpDatabaseName,&lt;br /&gt;    System.UInt32 dwDesiredAccess&lt;br /&gt;   );&lt;br /&gt;  [DllImport("advapi32.dll",EntryPoint = "CreateServiceA")]&lt;br /&gt;  public static extern System.IntPtr CreateService(&lt;br /&gt;    System.IntPtr hSCManager,&lt;br /&gt;    System.String lpServiceName,&lt;br /&gt;    System.String lpDisplayName,&lt;br /&gt;    System.UInt32 dwDesiredAccess,&lt;br /&gt;    System.UInt32 dwServiceType,&lt;br /&gt;    System.UInt32 dwStartType,&lt;br /&gt;    System.UInt32 dwErrorControl,&lt;br /&gt;    System.String lpBinaryPathName,&lt;br /&gt;    System.String lpLoadOrderGroup,&lt;br /&gt;    System.IntPtr lpdwTagId,&lt;br /&gt;    System.String lpDependencies,&lt;br /&gt;    System.String lpServiceStartName,&lt;br /&gt;    System.String lpPassword&lt;br /&gt;   );&lt;br /&gt;  [DllImport("advapi32.dll")]&lt;br /&gt;  public static extern System.Boolean CloseServiceHandle(&lt;br /&gt;    System.IntPtr hSCObject&lt;br /&gt;   );&lt;br /&gt;    这个了关于Service的API都是在Advapi32.dll中实现的，函数的原型可以自行查找头文件，在Winsvc和Winbase中。&lt;br /&gt;    熟悉Windows编程的话一定会了解，句柄类型就是一个32位的整型，在DotNET下用IntPtr来声明，DWORD对应UINT32，LPCSTR对应String类型，唯一需要强调的是CreateService这个函数的lpdwTagId，是一个DWORD*，这里声明也IntPtr，因为在调用中绝大多数情况下传递NULL值，如果用out UINT32，无法传递NULL值。&lt;br /&gt;    仔细看CreateService中声明可以发现，这个函数真的可以做很多事情，其中包括Service的名称（lpServiceName，服务的标识，调用OpenSerive等函数时用到）、显示名（lpDisplayName，就是我们在Service的管理工具中看到的名称）、服务类型（dwServiceType，指定服务的运行方式：独立进程、共享进程、驱动程序还是交互式登录模式等等）、启动类型（dwStartType，自动、手动还是禁止等等）、服务失败的严重性（dwErrorControl）、实现服务代码的二进制文件的路径（lpBinaryPathName）、加载顺序组的名称（lpLoadOrderGroup）、接受Tag标志码（lpdwTagId）、依赖服务的名称组（lpDependencies）、启动服务的帐号（lpServiceStartName，如果为NULL，表示使用LocalSystem）、启动服务帐号的口令（lpPassword）。如果调用成功，那么将返回一个非0的句柄，表示服务注册成功。&lt;br /&gt;    看了上面的一系列属性说明，大家也许发现还少了一样，就是在Service的管理工具中最长最醒目的一栏Description，Description的设置需要调用另一个API，如下：&lt;br /&gt;  public static extern System.Boolean ChangeServiceConfig2(&lt;br /&gt;    System.IntPtr hService,&lt;br /&gt;    System.UInt32 dwInfoLevel,&lt;br /&gt;    ref System.String lpInfo&lt;br /&gt;   );&lt;br /&gt;    其中lpInfo的声明原型是一个LPVOID，如果设置Description属性的话指向的是一个结构：&lt;br /&gt; typedef struct _SERVICE_DESCRIPTION {&lt;br /&gt;   LPTSTR lpDescription;&lt;br /&gt; } SERVICE_DESCRIPTION, *LPSERVICE_DESCRIPTION;&lt;br /&gt;    这个结构里面包含了一个字符指针，也就是说需要在函数调用时传递一个指向字符指针的指针，偷懒起见，ref System.String就足够了，无需再定义结构了，呵呵！&lt;br /&gt;    完整的例子如下，常量定义见本文最后：&lt;br /&gt;  private static System.Boolean RegistService()&lt;br /&gt;  {&lt;br /&gt;   System.Boolean  fRet = false;&lt;br /&gt;   System.IntPtr  hServiceManager = IntPtr.Zero,hService = IntPtr.Zero;&lt;br /&gt;   System.String  sServicePath = null,sDesc = null;&lt;br /&gt; &lt;br /&gt;   sServicePath = Application.StartupPath + @"\sampleservice.exe";&lt;br /&gt;   hServiceManager = OpenSCManager(Environment.MachineName,null,SC_MANAGER_ALL_ACCESS);&lt;br /&gt;   if (hServiceManager != IntPtr.Zero)&lt;br /&gt;   {&lt;br /&gt;    hService = CreateService(hServiceManager,"sampleservice","Sample Service",SERVICE_ALL_ACCESS,&lt;br /&gt;     SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,SERVICE_AUTO_START,SERVICE_ERROR_NORMAL,&lt;br /&gt;     sServicePath,null,IntPtr.Zero,null,null,null);&lt;br /&gt;    if (hService != IntPtr.Zero)&lt;br /&gt;    {&lt;br /&gt;     sDesc = "This is a sample service.";&lt;br /&gt;     fRet = ChangeServiceConfig2(hService,SERVICE_CONFIG_DESCRIPTION,ref sDesc);&lt;br /&gt;     CloseServiceHandle(hService);&lt;br /&gt;     hService = IntPtr.Zero;&lt;br /&gt;    }&lt;br /&gt;    CloseServiceHandle(hServiceManager);&lt;br /&gt;    hServiceManager = IntPtr.Zero;&lt;br /&gt;   }&lt;br /&gt;   return fRet;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;3、注销Service&lt;br /&gt;    相对于注册，注销就简单很多了，用到了OpenSCManager、OpenService、DeleteService和CloseServiceHandle四个API，另两个API的声明如下：&lt;br /&gt;  [DllImport("advapi32.dll")]&lt;br /&gt;  public static extern System.IntPtr OpenService(&lt;br /&gt;    System.IntPtr hSCManager,&lt;br /&gt;    System.String lpServiceName,&lt;br /&gt;    System.UInt32 dwDesiredAccess&lt;br /&gt;   );&lt;br /&gt;  [DllImport("advapi32.dll")]&lt;br /&gt;  public static extern System.Boolean DeleteService(&lt;br /&gt;    System.IntPtr hService&lt;br /&gt;   );&lt;br /&gt;    比较简单没什么可多说的看一个完整的例子：&lt;br /&gt;  private static System.Boolean UnRegistService()&lt;br /&gt;  {&lt;br /&gt;   System.Boolean  fRet = false;&lt;br /&gt;   System.IntPtr  hServiceManager = IntPtr.Zero,hService = IntPtr.Zero;&lt;br /&gt; &lt;br /&gt;   hServiceManager = OpenSCManager(Environment.MachineName,null,SC_MANAGER_ALL_ACCESS);&lt;br /&gt;   if (hServiceManager != IntPtr.Zero)&lt;br /&gt;   {&lt;br /&gt;    hService = OpenService(hServiceManager,"sampleservice",SERVICE_ALL_ACCESS);&lt;br /&gt;    if (hService != IntPtr.Zero)&lt;br /&gt;    {&lt;br /&gt;     fRet = DeleteService(hService);&lt;br /&gt;     CloseServiceHandle(hService);&lt;br /&gt;     hService = IntPtr.Zero;&lt;br /&gt;    }&lt;br /&gt;    CloseServiceHandle(hServiceManager);&lt;br /&gt;    hServiceManager = IntPtr.Zero;&lt;br /&gt;   }&lt;br /&gt;   return fRet;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;4、最后&lt;br /&gt;    可以在实现Service的工程中增加一下额外的处理，Main函数中判断一下调用参数，如果是“-I”，则表示注册Service，如果是“-U”表示注销Service，反之则作为Service正常运行。&lt;br /&gt; &lt;br /&gt;5、API和常量的声明&lt;br /&gt;    本文所用到的所有API和常量如下：&lt;br /&gt;  // declare APIs for service&lt;br /&gt;  [DllImport("advapi32.dll")]&lt;br /&gt;  public static extern System.IntPtr OpenSCManager(&lt;br /&gt;    System.String lpMachineName,&lt;br /&gt;    System.String lpDatabaseName,&lt;br /&gt;    System.UInt32 dwDesiredAccess&lt;br /&gt;   );&lt;br /&gt;  [DllImport("advapi32.dll",EntryPoint = "CreateServiceA")]&lt;br /&gt;  public static extern System.IntPtr CreateService(&lt;br /&gt;    System.IntPtr hSCManager,&lt;br /&gt;    System.String lpServiceName,&lt;br /&gt;    System.String lpDisplayName,&lt;br /&gt;    System.UInt32 dwDesiredAccess,&lt;br /&gt;    System.UInt32 dwServiceType,&lt;br /&gt;    System.UInt32 dwStartType,&lt;br /&gt;    System.UInt32 dwErrorControl,&lt;br /&gt;    System.String lpBinaryPathName,&lt;br /&gt;    System.String lpLoadOrderGroup,&lt;br /&gt;    System.IntPtr lpdwTagId,&lt;br /&gt;    System.String lpDependencies,&lt;br /&gt;    System.String lpServiceStartName,&lt;br /&gt;    System.String lpPassword&lt;br /&gt;   );&lt;br /&gt;  [DllImport("advapi32.dll")]&lt;br /&gt;  public static extern System.IntPtr OpenService(&lt;br /&gt;    System.IntPtr hSCManager,&lt;br /&gt;    System.String lpServiceName,&lt;br /&gt;    System.UInt32 dwDesiredAccess&lt;br /&gt;   );&lt;br /&gt;  [DllImport("advapi32.dll")]&lt;br /&gt;  public static extern System.Boolean DeleteService(&lt;br /&gt;    System.IntPtr hService&lt;br /&gt;   );&lt;br /&gt;  [DllImport("advapi32.dll")]&lt;br /&gt;  public static extern System.Boolean CloseServiceHandle(&lt;br /&gt;    System.IntPtr hSCObject&lt;br /&gt;   );&lt;br /&gt;  [DllImport("advapi32.dll")]&lt;br /&gt;  public static extern System.Boolean ChangeServiceConfig2(&lt;br /&gt;    System.IntPtr hService,&lt;br /&gt;    System.UInt32 dwInfoLevel,&lt;br /&gt;    ref System.String lpInfo&lt;br /&gt;   );&lt;br /&gt; &lt;br /&gt;  public const System.UInt32 STANDARD_RIGHTS_REQUIRED = 0xF0000;&lt;br /&gt;  // Service Control Manager object specific access types&lt;br /&gt;  public const System.UInt32 SC_MANAGER_CONNECT = 0x0001;&lt;br /&gt;  public const System.UInt32 SC_MANAGER_CREATE_SERVICE = 0x0002;&lt;br /&gt;  public const System.UInt32 SC_MANAGER_ENUMERATE_SERVICE = 0x0004;&lt;br /&gt;  public const System.UInt32 SC_MANAGER_LOCK = 0x0008;&lt;br /&gt;  public const System.UInt32 SC_MANAGER_QUERY_LOCK_STATUS = 0x0010;&lt;br /&gt;  public const System.UInt32 SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020;&lt;br /&gt;  public const System.UInt32 SC_MANAGER_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | &lt;br /&gt;    SC_MANAGER_CONNECT            | &lt;br /&gt;    SC_MANAGER_CREATE_SERVICE     | &lt;br /&gt;    SC_MANAGER_ENUMERATE_SERVICE  | &lt;br /&gt;    SC_MANAGER_LOCK               | &lt;br /&gt;    SC_MANAGER_QUERY_LOCK_STATUS  | &lt;br /&gt;    SC_MANAGER_MODIFY_BOOT_CONFIG;&lt;br /&gt;  // Service object specific access type&lt;br /&gt;  public const System.UInt32 SERVICE_QUERY_CONFIG = 0x0001;&lt;br /&gt;  public const System.UInt32 SERVICE_CHANGE_CONFIG = 0x0002;&lt;br /&gt;  public const System.UInt32 SERVICE_QUERY_STATUS = 0x0004;&lt;br /&gt;  public const System.UInt32 SERVICE_ENUMERATE_DEPENDENTS = 0x0008;&lt;br /&gt;  public const System.UInt32 SERVICE_START = 0x0010;&lt;br /&gt;  public const System.UInt32 SERVICE_STOP = 0x0020;&lt;br /&gt;  public const System.UInt32 SERVICE_PAUSE_CONTINUE = 0x0040;&lt;br /&gt;  public const System.UInt32 SERVICE_INTERROGATE = 0x0080;&lt;br /&gt;  public const System.UInt32 SERVICE_USER_DEFINED_CONTROL = 0x0100;&lt;br /&gt;  public const System.UInt32 SERVICE_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED     | &lt;br /&gt;    SERVICE_QUERY_CONFIG         | &lt;br /&gt;    SERVICE_CHANGE_CONFIG        | &lt;br /&gt;    SERVICE_QUERY_STATUS         | &lt;br /&gt;    SERVICE_ENUMERATE_DEPENDENTS | &lt;br /&gt;    SERVICE_START                | &lt;br /&gt;    SERVICE_STOP                 | &lt;br /&gt;    SERVICE_PAUSE_CONTINUE       | &lt;br /&gt;    SERVICE_INTERROGATE          | &lt;br /&gt;    SERVICE_USER_DEFINED_CONTROL;&lt;br /&gt;  // service type&lt;br /&gt;  public const System.UInt32 SERVICE_KERNEL_DRIVER = 0x00000001;&lt;br /&gt;  public const System.UInt32 SERVICE_FILE_SYSTEM_DRIVER = 0x00000002;&lt;br /&gt;  public const System.UInt32 SERVICE_ADAPTER = 0x00000004;&lt;br /&gt;  public const System.UInt32 SERVICE_RECOGNIZER_DRIVER = 0x00000008;&lt;br /&gt;  public const System.UInt32 SERVICE_DRIVER = SERVICE_KERNEL_DRIVER | &lt;br /&gt;    SERVICE_FILE_SYSTEM_DRIVER | &lt;br /&gt;    SERVICE_RECOGNIZER_DRIVER;&lt;br /&gt;  public const System.UInt32 SERVICE_WIN32_OWN_PROCESS = 0x00000010;&lt;br /&gt;  public const System.UInt32 SERVICE_WIN32_SHARE_PROCESS = 0x00000020;&lt;br /&gt;  public const System.UInt32 SERVICE_WIN32 = SERVICE_WIN32_OWN_PROCESS | &lt;br /&gt;    SERVICE_WIN32_SHARE_PROCESS;&lt;br /&gt;  public const System.UInt32 SERVICE_INTERACTIVE_PROCESS = 0x00000100;&lt;br /&gt;  public const System.UInt32 SERVICE_TYPE_ALL = SERVICE_WIN32  | &lt;br /&gt;    SERVICE_ADAPTER | &lt;br /&gt;    SERVICE_DRIVER  | &lt;br /&gt;    SERVICE_INTERACTIVE_PROCESS;&lt;br /&gt;  // Start Type&lt;br /&gt;  public const System.UInt32 SERVICE_BOOT_START = 0x00000000;&lt;br /&gt;  public const System.UInt32 SERVICE_SYSTEM_START = 0x00000001;&lt;br /&gt;  public const System.UInt32 SERVICE_AUTO_START = 0x00000002;&lt;br /&gt;  public const System.UInt32 SERVICE_DEMAND_START = 0x00000003;&lt;br /&gt;  public const System.UInt32 SERVICE_DISABLED = 0x00000004;&lt;br /&gt;  // Error control type&lt;br /&gt;  public const System.UInt32 SERVICE_ERROR_IGNORE = 0x00000000;&lt;br /&gt;  public const System.UInt32 SERVICE_ERROR_NORMAL = 0x00000001;&lt;br /&gt;  public const System.UInt32 SERVICE_ERROR_SEVERE = 0x00000002;&lt;br /&gt;  public const System.UInt32 SERVICE_ERROR_CRITICAL = 0x00000003;&lt;br /&gt;  // Info levels for ChangeServiceConfig2 and QueryServiceConfig2&lt;br /&gt;  public const System.UInt32 SERVICE_CONFIG_DESCRIPTION = 1;&lt;br /&gt;  public const System.UInt32 SERVICE_CONFIG_FAILURE_ACTIONS = 2;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-9208487721119076932?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/9208487721119076932/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=9208487721119076932&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/9208487721119076932'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/9208487721119076932'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/apiwindows-service-httpblogcsdnnetmitte.html' title='调用API注册和注销Windows Service (http://blog.csdn.net/Mittermeyer/archive/2004/01/04/11653.aspx)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-6518432461108691681</id><published>2007-05-08T10:28:00.000+08:00</published><updated>2007-05-10T09:57:42.892+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Windows Service'/><title type='text'>C# windows service承載遠程對象(http://www.cnblogs.com/snowlove67/archive/2006/03/22/356089.html)</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;參考文章:https://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/BuildSucApp/BSAAsecmodsecmod29.mspx?mfr=true&lt;br /&gt; &lt;br /&gt;1.首先寫接口定義遠程對象需要操作的方法，這個接口定義在單獨的類庫,供windowsservice引用和遠程客戶端引用.&lt;br /&gt;public interface IRemoteObjectMethod&lt;br /&gt;{&lt;br /&gt;   void DoSth();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;2.然後建立windows service 工程,添加實現遠程對象接口的類.&lt;br /&gt;public class RemoteObject : MarshalByRefObject, IRemoteObjectMethod&lt;br /&gt;{&lt;br /&gt;    public RemoteObject(){}&lt;br /&gt; // 添加方法的具體實現&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;3.添加註冊遠程對象配置節到app.config.&lt;br /&gt;如下:&lt;br /&gt;&amp;lt;system.runtime.remoting&amp;gt;&lt;br /&gt; &amp;lt;application name="ServerToClientService"&amp;gt;&lt;br /&gt;  &amp;lt;service&amp;gt;&lt;br /&gt;   &amp;lt;wellknow type="DownLoaderService.MarshalDownSyncObject, DownLoaderService" objectUri="DownSyncObject" mode="singlecall"/&amp;gt;&lt;br /&gt;  &amp;lt;/service&amp;gt; &lt;br /&gt;  &amp;lt;channels&amp;gt;&lt;br /&gt;   &amp;lt;channel ref="tcp" port="6767"&amp;gt;&lt;br /&gt;    &amp;lt;serverProviders&amp;gt;&lt;br /&gt;     &amp;lt;formatter ref="binary"/&amp;gt;  &lt;br /&gt;    &amp;lt;/serverProviders&amp;gt;  &lt;br /&gt;   &amp;lt;/channel&amp;gt;&lt;br /&gt;  &amp;lt;/channels&amp;gt;      &lt;br /&gt; &amp;lt;/application&amp;gt; &lt;br /&gt;&amp;lt;/system.runtime.remoting&amp;gt;&lt;br /&gt;&lt;br /&gt;4.在windows service的開始方法裏面添加註冊遠程對象的代碼.&lt;br /&gt;protected override void OnStart(string[] args)&lt;br /&gt;  {&lt;br /&gt;      RemotingConfiguration.Configure   (AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;5.安裝windows服務.這個就不必詳細寫了.&lt;br /&gt;&lt;br /&gt;至此，windows service的部分已經完成,接下來的都是在遠程客戶機上的操作.&lt;br /&gt;&lt;br /&gt;6.添加獲取遠程對象的類和配置文件.&lt;br /&gt; public class RemoteObjectFactory&lt;br /&gt; {     &lt;br /&gt;      // 承載遠程對象的服務名稱&lt;br /&gt;      private static string svc_Name = ConfigurationSettings.AppSettings["ServiceName"];&lt;br /&gt;      // 遠程服務所在的ip地址&lt;br /&gt;      private static string svc_ipAddress = ConfigurationSettings.AppSettings["ServiceIP"];&lt;br /&gt;      // 遠程對象註冊時的端口號&lt;br /&gt;      private static int svc_port = int.Parse(ConfigurationSettings.AppSettings["ServicePort"]);&lt;br /&gt;      // 遠程對象的標識&lt;br /&gt;      private static string svc_objectUri = ConfigurationSettings.AppSettings["ObjectUri"];&lt;br /&gt;      // 遠程連接通道的類型&lt;br /&gt;      private static string channelType = ConfigurationSettings.AppSettings["ChannelType"];&lt;br /&gt;&lt;br /&gt;      &lt;br /&gt;      public static IRemoteObjectMethod GetServerSyncObject()&lt;br /&gt;      {&lt;br /&gt;         string url = channelType + "://"  + svc_ipAddress + ":" + svc_port.ToString() + "/"  + svc_Name + "/"   + svc_objectUri;&lt;br /&gt;         IRemoteObjectMethod obj = (IRemoteObjectMethod)Activator.GetObject   (typeof (IRemoteObjectMethod), url);&lt;br /&gt;         if (obj == null)&lt;br /&gt;         {   &lt;br /&gt;                throw new Exception("Service not exists or Remoteobject not exists!");&lt;br /&gt;         }&lt;br /&gt;         return obj;&lt;br /&gt;     }&lt;br /&gt; }&lt;br /&gt;創建遠程對象獲取的方法，並在app.config添加相應的配置項.&lt;br /&gt;&lt;br /&gt;7.遠程客戶端調用&lt;br /&gt;IRemoteObjectMethod remoteObject = RemoteObjectFactory.GetServerSyncObject();&lt;br /&gt;remoteObject.DoSth();&lt;br /&gt;&lt;br /&gt;這樣似乎可以比較輕鬆的實現遠程方法的調用:)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-6518432461108691681?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/6518432461108691681/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=6518432461108691681&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6518432461108691681'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6518432461108691681'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/c-windows-servicehttpwwwcnblogscomsnowl.html' title='C# windows service承載遠程對象(http://www.cnblogs.com/snowlove67/archive/2006/03/22/356089.html)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-4103840429919405449</id><published>2007-05-08T09:41:00.000+08:00</published><updated>2007-05-10T09:57:42.894+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Windows Service'/><title type='text'>用Visual C#创建Windows服务程序(http://book.chinaz.com/net/asp.net1/dot42.htm)</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;&lt;strong&gt;一．Windows服务介绍：&lt;/strong&gt;&lt;br /&gt;Windows服务以前被称作NT服务，是一些运行在Windows NT、Windows 2000和Windows XP等操作系统下用户环境以外的程序。在以前，编写Windows服务程序需要程序员很强的C或C++功底。然而现在在Visual&lt;br /&gt;Studio.Net下，你可以运用C++或Visual C#或Visual Basic.Net很轻松的创建一个Windows服务程序。同样，你还可以运用其他任何与CLR相容的语言来创建Windows服务程序。本文就向大家介绍如何运用Visual&lt;br /&gt;C#来一步一步创建一个文件监视的Windows服务程序，然后介绍如何安装、测试和调试该Windows服务程序。 &lt;br /&gt;&lt;br /&gt;在介绍如何创建Windows服务程序以前，我先向大家介绍一些有关Windows服务的背景知识。一个Windows服务程序是在Windows操作系统下能完成特定功能的可执行的应用程序。Windows服务程序虽然是可执行的，但是它不像一般的可执行文件通过双击就能开始运行了，它必须有特定的启动方式。这些启动方式包括了自动启动和手动启动两种。对于自动启动的Windows服务程序，它们在Windows启动或是重启之后用户登录之前就开始执行了。只要你将相应的Windows服务程序注册到服务控制管理器（Service Control Manager）中，并将其启动类别设为自动启动就行了。而对于手动启动的Windows服务程序，你可以通过命令行工具的NET START 命令来启动它，或是通过控制面板中管理工具下的服务一项来启动相应的Windows服务程序（见图1）。&lt;br /&gt;&lt;br /&gt;同样，一个Windows服务程序也不能像一般的应用程序那样被终止。因为Windows服务程序一般是没有用户界面的，所以你也要通过命令行工具或是下面图中的工具来停止它，或是在系统关闭时使得Windows服务程序自动停止。因为Windows服务程序没有用户界面，所以基于用户界面的API函数对其是没有多大的意义。为了能使一个Windows服务程序能够正常并有效的在系统环境下工作，程序员必须实现一系列的方法来完成其服务功能。Windows服务程序的应用范围很广，典型的Windows服务程序包含了硬件控制、应用程序监视、系统级应用、诊断、报告、Web和文件系统服务等功能。&lt;br /&gt;&lt;img src="http://book.chinaz.com/net/asp.net1/pics15/image001.jpg"/&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;二．创建Windows服务程序：&lt;/strong&gt;&lt;br /&gt;在介绍如何创建Windows服务程序以前，我先向大家介绍一下.Net框架下与Windows服务相关的命名空间和其中的类库。.Net框架大大地简化了Windows服务程序的创建和控制过程，这要归功于其命名空间中的功能强大的类库。和Windows服务程序相关的命名空间涉及到以下两个：System.ServiceProcess和System.Diagnostics。&lt;br /&gt;&lt;br /&gt;要创建一个最基本的Windows服务程序，我们只需要运用.Net框架下的System.ServiceProcess命名空间以及其中的四个类：ServiceBase、ServiceInstaller、ServiceProcessInstaller以及ServiceController，其体系结构可见图2。&lt;br /&gt;&lt;img src="http://book.chinaz.com/net/asp.net1/pics15/image002.gif"/&gt;&lt;br /&gt;&lt;br /&gt;其中ServiceBase类定义了一些可被其子类重载的函数，通过这些重载的函数，服务控制管理器就可以控制该Windows服务程序了。这些函数包括：OnStart（）、OnStop（）、OnPause（）以及OnContinue（）等四个。而且ServiceBase类的子类还可以重载OnCustomCommand（）函数来完成一些特定的操作。通过重载以上的一些函数，我们就完成了一个Windows服务程序的基本框架，这些函数的重载方法如下：&lt;br /&gt;protected override void OnStart(string[] args){&lt;br /&gt;}&lt;br /&gt;protected override void OnStop(){&lt;br /&gt;}&lt;br /&gt;protected override void OnPause(){&lt;br /&gt;}&lt;br /&gt;protected override void OnContinue(){&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;ServiceBase类还为我们提供了一些属性，而这些属性是任何Widnows服务程序所必须的。其中的ServiceName属性指定了Windows服务的名称，通过该名称系统就可以调用Windows服务了，同时其它应用程序也可以通过该名称来调用它的服务。而CanPauseAndContinue和CanStop属性顾名思义就是允许暂停并恢复和允许停止的意思。&lt;br /&gt;&lt;br /&gt;要使得一个Windows服务程序能够正常运行，我们需要像创建一般应用程序那样为它创建一个程序的入口点。在Windows服务程序中，我们也是在Main（）函数中完成这个操作的。首先我们在Main（）函数中创建一个Windows服务的实例，该实例应该是ServiceBase类的某个子类的对象，然后我们调用由基类ServiceBase类定义的一个Run（）方法。然而Run（）方法并不就开始了Windows服务程序，我们必须通过前面提到的服务控制管理器调用特定的控制功能来完成Windows服务程序的启动，也就是要等到该对象的OnStart（）方法被调用时服务才真正开始运行。如果你想在一个Windows服务程序中同时启动多个服务，那么只要在Main（）函数中定义多个ServiceBae类的子类的实例对象就可以了，方法就是创建一个ServiceBase类的数组对象，使得其中的每个对象对应于某个我们已预先定义好的服务。&lt;br /&gt;static void Main(string[] args){&lt;br /&gt;System.ServiceProcess.ServiceBase[] MyServices;&lt;br /&gt;MyServices = new System.ServiceProcess.ServiceBase[] { new Service1(), new Service2() };&lt;br /&gt;System.ServiceProcess.ServiceBase.Run(MyServices);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;三．添加文件监视服务&lt;/strong&gt;&lt;br /&gt;了解了Windows服务的基本体系结构和创建方法后，我们就可以试着往服务中添加一些实际的功能了。下面我将向大家介绍一个能监视本地文件系统的文件监视服务－FileMonitorService。该服务能根据预先设定的本地目录路径监视其中的文件包括子文件夹中的任何变化：文件创建、文件删除、文件改名、文件修改。同时，该服务还为每种变化创建了一个相对应的计数器，计数器的作用就是反映该种变化的频度。&lt;br /&gt;首先，我们打开Visual Studio.Net，新建一个Visual C#的Windows服务的项目，如图3所示： &lt;br /&gt;&lt;img src="http://book.chinaz.com/net/asp.net1/pics15/image003.gif"/&gt;&lt;br /&gt;在重载Windows服务的OnStart（）函数之前，我们先给其类添加一些计数器对象，这些计数器分别对应了文件的创建、删除、改名以及修改等变化。一旦指定目录中的文件发生以上的某种变化，与其相对应的计数器就会自动加1。所有的这些计数器都是定义为PerformanceCounter类型的变量的，该类是包含在System.Diagnostics命名空间中的。&lt;br /&gt;private System.Diagnostics.PerformanceCounter fileCreateCounter;&lt;br /&gt;private System.Diagnostics.PerformanceCounter fileDeleteCounter;&lt;br /&gt;private System.Diagnostics.PerformanceCounter fileRenameCounter;&lt;br /&gt;private System.Diagnostics.PerformanceCounter fileChangeCounter;&lt;br /&gt;&lt;br /&gt;InitializeComponent（）方法中创建以上定义的各个计数器对象并确定其相关属性。同时我们将该Windows服务的名称设置为“FileMonitorService”，设定其即是允许暂停并恢复的又是允许停止的。&lt;br /&gt;private void InitializeComponent(){&lt;br /&gt;this.components = new System.ComponentModel.Container();                     this.fileChangeCounter = new System.Diagnostics.PerformanceCounter();&lt;br /&gt;this.fileDeleteCounter = new System.Diagnostics.PerformanceCounter();&lt;br /&gt;this.fileRenameCounter = new System.Diagnostics.PerformanceCounter();&lt;br /&gt;this.fileCreateCounter = new System.Diagnostics.PerformanceCounter();&lt;br /&gt;fileChangeCounter.CategoryName = "File Monitor Service";&lt;br /&gt;fileDeleteCounter.CategoryName = "File Monitor Service";&lt;br /&gt;fileRenameCounter.CategoryName = "File Monitor Service";&lt;br /&gt;fileCreateCounter.CategoryName = "File Monitor Service";&lt;br /&gt;fileChangeCounter.CounterName = "Files Changed";&lt;br /&gt;fileDeleteCounter.CounterName = "Files Deleted";&lt;br /&gt;fileRenameCounter.CounterName = "Files Renamed";&lt;br /&gt;fileCreateCounter.CounterName = "Files Created";&lt;br /&gt;this.ServiceName = "FileMonitorService";&lt;br /&gt;this.CanPauseAndContinue = true;&lt;br /&gt;this.CanStop = true;&lt;br /&gt;servicePaused = false;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;接着就是重载OnStart（）函数和OnStop（）函数，OnStart（）函数完成了一些必要的初始化工作。在.Net框架下，文件的监视功能可以由FileSystemWatcher类来完成，该类是包含在System.IO命名空间下的。该Windows服务所要完成的功能包括了监视文件的创建、删除、改名和修改等变化，而FileSystemWatcher类包含所有了对应于这些变化的处理函数。&lt;br /&gt;protected override void OnStart(string[] args){ &lt;br /&gt;FileSystemWatcher curWatcher = new FileSystemWatcher();&lt;br /&gt;curWatcher.BeginInit();&lt;br /&gt;curWatcher.IncludeSubdirectories = true;&lt;br /&gt;curWatcher.Path = System.Configuration.ConfigurationSettings.AppSettings["FileMonitorDirectory"];&lt;br /&gt;curWatcher.Changed += new FileSystemEventHandler(OnFileChanged);&lt;br /&gt;curWatcher.Created += new FileSystemEventHandler(OnFileCreated);&lt;br /&gt;curWatcher.Deleted += new FileSystemEventHandler(OnFileDeleted);&lt;br /&gt;curWatcher.Renamed += new RenamedEventHandler(OnFileRenamed);&lt;br /&gt;curWatcher.EnableRaisingEvents = true;&lt;br /&gt;curWatcher.EndInit();&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;注意其中被监视的目录是存放在一个应用程序配置文件中的，该文件是一个XML类型的文件。这种做法的好处就是我们不必重新编译并发布该Windows服务而只要直接修改其配置文件就可以达到更改所要监视的目录的功能了。 &lt;br /&gt;&lt;br /&gt;当该Windows服务启动后，一旦被监视的目录中的文件发生某种变化，与其相对应的计数器的值便会相应的增加，方法很简单，只要调用计数器对象的IncrementBy（）即可。 &lt;br /&gt;private void OnFileChanged(Object source, FileSystemEventArgs e){&lt;br /&gt;if( servicePaused == false ){&lt;br /&gt;fileChangeCounter.IncrementBy(1);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;private void OnFileRenamed(Object source, RenamedEventArgs e){&lt;br /&gt;if( servicePaused == false ){&lt;br /&gt;fileRenameCounter.IncrementBy(1);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;private void OnFileCreated(Object source, FileSystemEventArgs e){&lt;br /&gt;if( servicePaused == false ){&lt;br /&gt;fileCreateCounter.IncrementBy(1);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;private void OnFileDeleted(Object source, FileSystemEventArgs e){&lt;br /&gt;if( servicePaused == false ){&lt;br /&gt;fileDeleteCounter.IncrementBy(1);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;OnStop（）函数即是停止Windows服务的，在该Windows服务中，服务一旦停止，所有的计数器的值都应归零，但是计数器并不提供一个Reset（）方法，所以我们只好将计数器中的值减去当前值来达到这个目的。&lt;br /&gt;protected override void OnStop(){&lt;br /&gt;if( fileChangeCounter.RawValue != 0 ){&lt;br /&gt;fileChangeCounter.IncrementBy(-fileChangeCounter.RawValue);&lt;br /&gt;}&lt;br /&gt;if( fileDeleteCounter.RawValue != 0 ){&lt;br /&gt;fileDeleteCounter.IncrementBy(-fileDeleteCounter.RawValue);&lt;br /&gt;}&lt;br /&gt;if( fileRenameCounter.RawValue != 0 ){&lt;br /&gt;fileRenameCounter.IncrementBy(-fileRenameCounter.RawValue); &lt;br /&gt;}&lt;br /&gt;if( fileCreateCounter.RawValue != 0 ){&lt;br /&gt;fileCreateCounter.IncrementBy(-fileCreateCounter.RawValue);&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;同时，因为我们的Windows服务是允许暂停并恢复的，所以我们还得重载OnPause（）函数和OnContinue（）函数，方法很简单，只要设定前面定义的布尔值servicePaused即可。&lt;br /&gt;protected override void OnPause(){&lt;br /&gt;servicePaused = true;&lt;br /&gt;}&lt;br /&gt;protected override void OnContinue(){&lt;br /&gt;servicePaused = false;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;这样，该Windows服务的主体部分已经完成了，不过它并不有用，我们还必须为其添加安装文件。安装文件为Windows服务的正确安装做好了工作，它包括了一个Windows服务的安装类，该类是重System.Configuration.Install.Installer继承过来的。安装类中包括了Windows服务运行所需的帐号信息，用户名、密码信息以及Windows服务的名称，启动方式等信息。&lt;br /&gt;[RunInstaller(true)]&lt;br /&gt;public class Installer1 : System.Configuration.Install.Installer{&lt;br /&gt;/// &lt;summary&gt;&lt;br /&gt;/// 必需的设计器变量。&lt;br /&gt;/// &lt;/summary&gt;&lt;br /&gt;private System.ComponentModel.Container components = null;&lt;br /&gt;private System.ServiceProcess.ServiceProcessInstaller spInstaller;&lt;br /&gt;private System.ServiceProcess.ServiceInstaller sInstaller;&lt;br /&gt;public Installer1(){&lt;br /&gt;// 该调用是设计器所必需的。&lt;br /&gt;InitializeComponent();&lt;br /&gt;// TODO: 在 InitComponent 调用后添加任何初始化&lt;br /&gt;}&lt;br /&gt;#region Component Designer generated code&lt;br /&gt;/// &lt;summary&gt;&lt;br /&gt;/// 设计器支持所需的方法 - 不要使用代码编辑器修改&lt;br /&gt;/// 此方法的内容。&lt;br /&gt;/// &lt;/summary&gt;&lt;br /&gt;private void InitializeComponent(){&lt;br /&gt;components = new System.ComponentModel.Container();&lt;br /&gt;// 创建ServiceProcessInstaller对象和ServiceInstaller对象&lt;br /&gt;this.spInstaller = new System.ServiceProcess.ServiceProcessInstaller();&lt;br /&gt;this.sInstaller = new System.ServiceProcess.ServiceInstaller();&lt;br /&gt;// 设定ServiceProcessInstaller对象的帐号、用户名和密码等信息&lt;br /&gt;this.spInstaller.Account = System.ServiceProcess.ServiceAccount.LocalSystem;&lt;br /&gt;this.spInstaller.Username = null;&lt;br /&gt;this.spInstaller.Password = null;&lt;br /&gt;// 设定服务名称&lt;br /&gt;this.sInstaller.ServiceName = "FileMonitorService";&lt;br /&gt;// 设定服务的启动方式&lt;br /&gt;this.sInstaller.StartType = System.ServiceProcess.ServiceStartMode.Automatic;&lt;br /&gt;this.Installers.AddRange(new System.Configuration.Install.Installer[]{this.spInstaller, this.sInstaller });&lt;br /&gt;}&lt;br /&gt;#endregion&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;同样，因为该Windows服务中运用到了计数器对象，我们也要为其添加相应的安装文件，安装文件的内容和作用与前面的类似。限于篇幅，这里就不给出相应的代码了，有兴趣的读者可以参考文后附带的源代码文件。&lt;br /&gt;到此为止，整个Windows服务已经构建完毕，不过Windows服务程序和一般的应用程序不同，它不能直接调试运行。如果你直接在IDE下试图调试运行之，就会报出如图4所示提示。&lt;br /&gt;&lt;img src="http://book.chinaz.com/net/asp.net1/pics15/image004.gif"/&gt;&lt;br /&gt;&lt;br /&gt;根据其中提示，我们知道安装Windows服务需要用到一个名为InstallUtil.exe的命令行工具。而运用该工具安装Windows服务的方法是非常简单的，安装该Windows服务的命令如下：&lt;br /&gt;installutil FileMonitorService.exe&lt;br /&gt;&lt;br /&gt;而要卸载该Windows服务，你只要输入如下的命令即可： &lt;br /&gt;installutil /u FileMonitorService.exe&lt;br /&gt;&lt;br /&gt;Windows服务安装成功后，它便会出现在服务控制管理器中，如图5所示。&lt;br /&gt;&lt;img src="http://book.chinaz.com/net/asp.net1/pics15/image005.gif"/&gt;&lt;br /&gt;&lt;br /&gt;这样，该文件监视的Windows服务就完成了，一旦我们对被监视的目录中的文件进行操作，相应的计数器就会运作，起到监视文件变化的作用。不过这个功能对于一般的用户而言没多大意义，然而你可以在此基础上添加新的功能，比如构建一个后台的文件处理系统，一旦被监视的目录中的文件发生某种变化，Windows服务便对其进行特定的操作，而最终用户就不必去关心后台处理程序是如何实现的了。&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;四．总结&lt;/strong&gt;&lt;br /&gt;本文向大家介绍了Windows服务的一些基本概念和构建一般的Windows服务所需的方法，同时还向大家展示了一个具有文件监视功能的Windows服务程序。通过本文，读者应该能体会到构建Windows服务并不是想象中的那么复杂，这主要还得归功于.Net框架为我们所作的大量努力。同时，希望大家能在本文给出的实例的基础上构建更加完善和更加强大的Windows服务程序。最后希望本文对大家能有不少帮助。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-4103840429919405449?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/4103840429919405449/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=4103840429919405449&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4103840429919405449'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/4103840429919405449'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/visual-cwindowshttpbookchinazcomnetaspn.html' title='用Visual C#创建Windows服务程序(http://book.chinaz.com/net/asp.net1/dot42.htm)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-5059610200669851568</id><published>2007-05-08T09:04:00.000+08:00</published><updated>2007-05-10T09:57:42.895+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Windows Service'/><title type='text'>用C#创建Windows服务[Windows Services] (write's blog)</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;Windows服务在Visual Studio 以前的版本中叫NT服务，在VS.net启用了新的名称。用Visual C# 创建Windows服务不是一件困难的事，本文就将指导你一步一步创建一个Windows服务并使用它。这个服务在启动和停止时，向一个文本文件中写入一些文字信息。&lt;br /&gt;&lt;br /&gt;第一步：创建服务框架 &lt;br /&gt;要创建一个新的 Windows 服务，可以从Visual C# 工程中选取 Windows 服务（Windows Service）选项，给工程一个新文件名，然后点击 确定。 &lt;br /&gt;你可以看到，向导向工程文件中增加WebService1.cs类：&lt;br /&gt;如下图来设置属性:&lt;br /&gt;其中各属性的含意是:&lt;br /&gt;ü         Autolog                 是否自动写入系统的日志文件&lt;br /&gt;ü         CanHandlePowerEvent     服务时候接受电源事件&lt;br /&gt;ü         CanPauseAndContinue          服务是否接受暂停或继续运行的请求&lt;br /&gt;ü         CanShutdown 服务是否在运行它的计算机关闭时收到通知，以便能够调用 OnShutDown 过程&lt;br /&gt;ü         CanStop                              服务是否接受停止运行的请求&lt;br /&gt;ü         ServiceName                       服务名&lt;br /&gt;&lt;br /&gt;第二步：向服务中增加功能 &lt;br /&gt;在 .cs代码文件中我们可以看到，有两个被忽略的函数 OnStart和OnStop。 &lt;br /&gt;OnStart函数在启动服务时执行，OnStop函数在停止服务时执行。在这里，当启动和停止服务时，向一个文本文件中写入一些文字信息，代码如下:&lt;br /&gt;protected override void OnStart(string[] args){&lt;br /&gt;FileStream fs = new FileStream(@"d:\mcWindowsService.txt" , FileMode.OpenOrCreate, FileAccess.Write); &lt;br /&gt;StreamWriter m_streamWriter = new StreamWriter(fs); &lt;br /&gt;m_streamWriter.BaseStream.Seek(0, SeekOrigin.End); &lt;br /&gt;m_streamWriter.WriteLine("mcWindowsService:Service Started"+DateTime.Now.ToString()+"\n"); &lt;br /&gt;m_streamWriter.Flush();&lt;br /&gt;m_streamWriter.Close();&lt;br /&gt;fs.Close();&lt;br /&gt;}&lt;br /&gt;protected override void OnStop(){&lt;br /&gt;FileStream fs = new FileStream(@"d:\mcWindowsService.txt" , FileMode.OpenOrCreate, FileAccess.Write); &lt;br /&gt;StreamWriter m_streamWriter = new StreamWriter(fs); &lt;br /&gt;m_streamWriter.BaseStream.Seek(0, SeekOrigin.End); &lt;br /&gt;m_streamWriter.WriteLine(" mcWindowsService: Service Stopped "+DateTime.Now.ToString()+"\n"); &lt;br /&gt;m_streamWriter.Flush();&lt;br /&gt;m_streamWriter.Close();&lt;br /&gt;fs.Close();&lt;br /&gt;} &lt;br /&gt;&lt;br /&gt;第三步: 将安装程序添加到服务应用程序 &lt;br /&gt;Visual Studio.NET 随附有安装组件，可用来安装与服务应用程序相关联的资源。安装组件在正在安装到的系统上注册一项单个的服务，并使服务控制管理器知道该服务的存在。&lt;br /&gt;要正确安装服务，并不需要在安装程序中进行任何特殊编码。但是，如果需要向安装进程添加特殊功能，则可能偶尔需要修改安装程序的内容。&lt;br /&gt;将安装程序添加到服务应用程序的步骤是:&lt;br /&gt;1：在解决方案中，访问要向其中添加安装组件的服务的Design视图。&lt;br /&gt;2：在属性窗口中，单击添加安装程序链接。这时项目中就添加了一个新类 ProjectInstaller 和两个安装组件 ServiceProcessInstaller 和 ServiceInstaller，并且服务的属性值被复制到组件。 &lt;br /&gt;3：若要确定如何启动服务，请单击 ServiceInstaller 组件并将 StartType 属性设置为适当的值。&lt;br /&gt;ü         Manual      服务安装后，必须手动启动。&lt;br /&gt;ü         Automatic    每次计算机重新启动时，服务都会自动启动。&lt;br /&gt;ü         Disabled     服务无法启动。&lt;br /&gt;4：将serviceProcessInstaller类的Account属性改为 LocalSystem&lt;br /&gt;这样，不论是以哪个用户登录的系统，服务总会启动。 &lt;br /&gt;&lt;br /&gt;第四步：生成服务程序&lt;br /&gt;通过从生成菜单中选择生成来生成项目。&lt;br /&gt;注意   不要通过按 F5 键来运行项目——不能以这种方式运行服务项目。&lt;br /&gt;&lt;br /&gt;第五步：安装服务&lt;br /&gt;访问项目中的已编译可执行文件所在的目录。 &lt;br /&gt;用项目的输出作为参数，从命令行运行 InstallUtil.exe。在命令行中输入下列代码： &lt;br /&gt;installutil yourproject.exe&lt;br /&gt;卸载服务 &lt;br /&gt;用项目的输出作为参数，从命令行运行 InstallUtil.exe。 &lt;br /&gt;installutil /u yourproject.exe &lt;br /&gt; &lt;br /&gt;至此，整个服务已经编写，编译，安装完成，你可以在控制面板的管理工具的服务中，看到你编写的服务。&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-5059610200669851568?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/5059610200669851568/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=5059610200669851568&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/5059610200669851568'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/5059610200669851568'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/05/cwindowswindows-services.html' title='用C#创建Windows服务[Windows Services] (write&apos;s blog)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-775553447659971931</id><published>2007-04-29T12:38:00.000+08:00</published><updated>2007-05-10T09:57:17.570+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Remoting'/><title type='text'>客户端订阅服务器事件配置文件（作者：琴雨潇箫）</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;Server配置文件Server.config： &lt;br /&gt;&amp;lt;configuration&amp;gt; &lt;br /&gt;&amp;lt;System.Runtime.Remoting&amp;gt; &lt;br /&gt;&amp;lt;application&amp;gt; &lt;br /&gt;&amp;lt;channels&amp;gt; &lt;br /&gt;&amp;lt;channel ref="http" port="8086"&amp;gt; &lt;br /&gt;&amp;lt;serverProviders&amp;gt; &lt;br /&gt;&amp;lt;formatter ref="binary" /&amp;gt; &lt;br /&gt;&amp;lt;/serverProviders&amp;gt; &lt;br /&gt;&amp;lt;clientProviders&amp;gt; &lt;br /&gt;&amp;lt;formatter ref="binary" /&amp;gt; &lt;br /&gt;&amp;lt;/clientProviders&amp;gt; &lt;br /&gt;&amp;lt;/channel&amp;gt; &lt;br /&gt;&amp;lt;/channels&amp;gt; &lt;br /&gt;&amp;lt;service&amp;gt; &lt;br /&gt;&amp;lt;wellknown type="Share.Announcer, Share" objectUri="Announcer" mode="Singleton" /&amp;gt; &lt;br /&gt;&amp;lt;/service&amp;gt; &lt;br /&gt;&amp;lt;/application&amp;gt; &lt;br /&gt;&amp;lt;/System.Runtime.Remoting&amp;gt; &lt;br /&gt;&amp;lt;/configuration&amp;gt; &lt;br /&gt;&lt;br /&gt;服务器端StartServer方法代码： &lt;br /&gt;RemotingConfiguration.Configure( "Server.config" ); &lt;br /&gt;_Announcer = new Share.Announcer(); &lt;br /&gt;_Announcer.Messenger += new BroadcastHandler( ShowMessage ); &lt;br /&gt;RemotingServices.Marshal( _Announcer, "Announcer" ); &lt;br /&gt;&lt;br /&gt;Client配置文件Client.config： &lt;br /&gt;&amp;lt;configuration&amp;gt; &lt;br /&gt;&amp;lt;System.Runtime.Remoting&amp;gt; &lt;br /&gt;&amp;lt;application&amp;gt; &lt;br /&gt;&amp;lt;channels&amp;gt; &lt;br /&gt;&amp;lt;channel port="0" ref="http"&amp;gt; &lt;br /&gt;&amp;lt;clientProviders&amp;gt; &lt;br /&gt;&amp;lt;formatter ref="binary" /&amp;gt; &lt;br /&gt;&amp;lt;/clientProviders&amp;gt; &lt;br /&gt;&amp;lt;serverProviders&amp;gt; &lt;br /&gt;&amp;lt;formatter ref="binary" /&amp;gt; &lt;br /&gt;&amp;lt;/serverProviders&amp;gt; &lt;br /&gt;&amp;lt;/channel&amp;gt; &lt;br /&gt;&amp;lt;/channels&amp;gt; &lt;br /&gt;&amp;lt;client&amp;gt; &lt;br /&gt;&amp;lt;wellknown type="Share.Announcer, Share" url="http://localhost:8086/Announcer" /&amp;gt; &lt;br /&gt;&amp;lt;/client&amp;gt; &lt;br /&gt;&amp;lt;/application&amp;gt; &lt;br /&gt;&amp;lt;/System.Runtime.Remoting&amp;gt; &lt;br /&gt;&amp;lt;/configuration&amp;gt; &lt;br /&gt;&lt;br /&gt;客户端StartClient方法代码： RemotingConfiguration.Configure( "Client.config" ); &lt;br /&gt;_IBroadcast = ( Share.IBroadcast )new Share.Announcer(); &lt;br /&gt;Share.EventWrapper wrapper = new Share.EventWrapper(); &lt;br /&gt;wrapper.WrapperBroadcast += new Share.BroadcastHandler( ShowMessage ); &lt;br /&gt;_IBroadcast.Broadcast += new Share.BroadcastHandler( wrapper.SendBroadcast );&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-775553447659971931?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/775553447659971931/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=775553447659971931&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/775553447659971931'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/775553447659971931'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/04/blog-post_29.html' title='客户端订阅服务器事件配置文件（作者：琴雨潇箫）'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-6081109716195233128</id><published>2007-04-29T10:33:00.000+08:00</published><updated>2007-05-10T09:57:17.571+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Remoting'/><title type='text'>Microsoft .Net Remoting系列专题之三：Remoting事件处理全接触（Bruce Zhang's Blog）</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;&lt;a id="viewpost1_TitleUrl" href="http://www.cnblogs.com/wayfarer/articles/75213.html"&gt;Microsoft .Net Remoting系列专题之三：Remoting事件处理全接触&lt;/a&gt;&lt;br /&gt;&lt;div class="postText"&gt;&lt;p&gt;&lt;font face="楷体_GB2312"&gt;我写的.Net Remoting系列专题：&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;a id="viewpost1_TitleUrl" href="/wayfarer/archive/2004/07/30/28723.html"&gt;&lt;font color="#000080"&gt;Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇&lt;/font&gt;&lt;/a&gt;&lt;a id="viewpost1_TitleUrl" href="/wayfarer/archive/2004/08/05/30437.html"&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;a id="viewpost1_TitleUrl" href="/wayfarer/archive/2004/08/05/30437.html"&gt;&lt;font color="#000080"&gt;Microsoft .Net Remoting系列专题之二：Marshal、Disconnect与生命周期以及跟踪服务&lt;/font&gt;&lt;/a&gt;&lt;a id="viewpost1_TitleUrl" href="/wayfarer/articles/75213.html"&gt;&lt;/a&gt;&lt;/p&gt;&lt;a id="viewpost1_TitleUrl" href="/wayfarer/archive/2004/07/30/28723.html"&gt;&lt;font color="#000080"&gt;&lt;/font&gt;&lt;/a&gt; &lt;p&gt;前言：在Remoting中处理事件其实并不复杂，但其中有些技巧需要你去挖掘出来。正是这些技巧，仿佛森严的壁垒，让许多人望而生畏，或者是不知所谓，最后放弃了事件在Remoting的使用。关于这个主题，在网上也有很多讨论，相关的技术文章也不少，遗憾的是，很多文章概述的都不太全面。我在研究Remoting的时候，也对事件处理发生了兴趣。经过参考相关的书籍、文档，并经过反复的试验，深信自己能够把这个问题阐述清楚了。&lt;br /&gt;本文对于Remoting和事件的基础知识不再介绍，有兴趣的可以看我的系列文章，或查阅相关的技术文档。&lt;/p&gt; &lt;p&gt;本文示例代码下载：&lt;/p&gt; &lt;p&gt;&lt;A href="http://www.cnblogs.com/Files/wayfarer/Remoting事件(客户端发传真).rar"&gt;Remoting事件(客户端发传真)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;A href="http://www.cnblogs.com/Files/wayfarer/Remoting事件(服务端广播).rar"&gt;Remoting事件(服务端广播)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;A href="http://www.cnblogs.com/Files/wayfarer/Remoting事件(服务端广播改进).rar"&gt;Remoting事件(服务端广播改进)&lt;/a&gt;&lt;/p&gt; &lt;p&gt;应用Remoting技术的分布式处理程序，通常包括三部分：远程对象、服务端、客户端。因此从事件的方向上看，就应该有三种形式：&lt;br /&gt;1、服务端订阅客户端事件&lt;br /&gt;2、客户端订阅服务端事件&lt;br /&gt;3、客户端订阅客户端事件&lt;/p&gt; &lt;p&gt;服务端订阅客户端事件，即由客户端发送消息，服务端捕捉该消息，然后响应该事件，相当于下级向上级发传真。反过来，客户端订阅服务端事件，则是由服务端发送消息，此时，所有客户端均捕获该消息，激发事件，相当于是一个系统广播。而客户端订阅客户端事件呢？就类似于聊天了。由某个客户端发出消息，其他客户端捕获该消息，激发事件。可惜的是，我并没有找到私聊的解决办法。当客户端发出消息后，只要订阅了该事件的，都会获得该信息。&lt;/p&gt; &lt;p&gt;然而不管是哪一种方式，究其实质，真正包含事件的还是远程对象。原理很简单，我们想一想，在Remoting中，客户端和服务端传递的内容是什么呢？毋庸置疑，是远程对象。因此，我们传递的事件消息，自然是被远程对象所包裹。这就像EMS快递，远程对象是运送信件的汽车，而事件消息就是汽车所装载的信件。至于事件传递的方向，只是发送者和订阅者的角色发生了改变而已。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;一、&amp;nbsp;服务端订阅客户端事件&lt;/strong&gt;&lt;br /&gt;服务端订阅客户端事件，相对比较简单。我们就以发传真为例。首先，我们必须具备传真机和要传真的文件，这就好比我们的远程对象。而且这个传真机上必须具备“发送”的操作按钮。这就好比是远程对象中的一个委托。当客户发送传真时，就需要在客户端上激活一个发送消息的方法，这就好比我们按了“发送”按钮。消息发送到服务端后，触发事件，这个事件正是服务端订阅的。服务端获得该事件消息后，再处理相关业务。这就好比接收传真的人员，当传真收到后，会听到接通的声音，此时选择“接收”后，该消息就被捕获了。&lt;/p&gt; &lt;p&gt;现在，我们就来模拟这个流程。首先定义远程对象，这个对象处理的应该是一个发送传真的业务：&lt;br /&gt;首先是远程对象的公共接口（Common.dll）：&lt;br /&gt;public delegate void FaxEventHandler(string fax);&lt;br /&gt;public interface IFaxBusiness&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; void SendFax(string fax);&lt;br /&gt;}&lt;br /&gt;注意，在公共接口程序集中，定义了一个公共委托。&lt;/p&gt; &lt;p&gt;然后我们定义具体处理传真业务的远程对象类（FaxBusiness.dll），在这个类中，先要添加对公共接口程序集的引用：&lt;br /&gt;public class FaxBusiness:MarshalByRefObject,IFaxBusiness&lt;br /&gt;{&amp;nbsp;&lt;br /&gt;&amp;nbsp;public static event FaxEventHandler FaxSendedEvent;&lt;/p&gt; &lt;p&gt;&amp;nbsp;#region&lt;/p&gt; &lt;p&gt;&amp;nbsp;public void SendFax(string fax)&lt;br /&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;if (FaxSendedEvent != null)&lt;br /&gt;&amp;nbsp;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;FaxSendedEvent(fax);&lt;br /&gt;&amp;nbsp;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;}&lt;/p&gt; &lt;p&gt;&amp;nbsp;#endregion&lt;/p&gt; &lt;p&gt;&amp;nbsp;public override object InitializeLifetimeService()&lt;br /&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;return null;&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;}&lt;br /&gt;这个远程对象中，事件的类型就是我们在公共程序集Common.dll中定义的委托类型。SendFax实现了接口IFaxBusiness中的方法。这个方法的签名和定义的委托一致，它调用了事件FaxSendedEvent。&lt;br /&gt;特殊的地方是我们定义的远程对象最好是重写MarshalByRefObject类的InitializeLifetimeService()方法。返回null值表明这个远程对象的生命周期为无限大。为什么要重写该方法呢？道理不言自明，如果生命周期不进行限制的话，一旦远程对象的生命周期结束，事件就无法激活了。&lt;br /&gt;接下来就是分别实现客户端和服务端了。服务端是一个Windows应用程序，界面如下：&lt;/p&gt; &lt;p&gt;&lt;img height="300" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re01.gif" width="300" border="0" /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;我们在加载窗体的时候，注册通道和远程对象：&lt;br /&gt;private void ServerForm_Load(object sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;HttpChannel channel = new HttpChannel(8080);&lt;br /&gt;&amp;nbsp;ChannelServices.RegisterChannel(channel);&lt;/p&gt; &lt;p&gt;&amp;nbsp;RemotingConfiguration.RegisterWellKnownServiceType(&lt;br /&gt;&amp;nbsp;&amp;nbsp;typeof(FaxBusiness),"FaxBusiness.soap",WellKnownObjectMode.Singleton);&lt;br /&gt;&amp;nbsp;FaxBusiness.FaxSendedEvent += new FaxEventHandler(OnFaxSended);&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;我们采用的是SingleTon模式，注册了一个远程对象。注意看，这段代码和一般的Remoting服务端有什么区别？对了，它多了一行注册事件的代码：&lt;br /&gt;FaxBusiness.FaxSendedEvent += new FaxEventHandler(OnFaxSended);&lt;br /&gt;这行代码，就好比我们服务端的传真机，一直切换为“自动”模式。它会一直监听着来自客户端的传真信息，一旦传真信息从客户端发过来了，则响应事件方法，即OnFaxSended方法：&lt;br /&gt;public void OnFaxSended(string fax)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;txtFax.Text += fax;&lt;br /&gt;&amp;nbsp;txtFax.Text += System.Environment.NewLine;&lt;br /&gt;}&lt;br /&gt;这个方法很简单，就是把客户端发过来的Fax显示到txtFax文本框控件上。&lt;/p&gt; &lt;p&gt;而客户端呢？仍然是一个Windows应用程序。代码非常简单，首先为了简便其见，我们仍然让它在装载窗体的时候，激活远程对象：&lt;br /&gt;private void ClientForm_Load(object sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;HttpChannel channel = new HttpChannel(0);&lt;br /&gt;&amp;nbsp;ChannelServices.RegisterChannel(channel);&lt;/p&gt; &lt;p&gt;&amp;nbsp;faxBus = (IFaxBusiness)Activator.GetObject(typeof(IFaxBusiness),&lt;br /&gt;&amp;nbsp;&amp;nbsp;"&lt;a href="http://localhost:8080/FaxBusiness.soap"&gt;http://localhost:8080/FaxBusiness.soap&lt;/a&gt;");&lt;br /&gt;}&lt;br /&gt;呵呵，可以说客户端激活对象的方法和普通的Remoting客户端应用程序没有什么不同。该写传真了！我们在窗体上放一个文本框对象，改其Multiline属性为true。再放一个按钮，负责发送传真：&lt;br /&gt;private void btnSend_Click(object sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;if (txtFax.Text != String.Empty)&lt;br /&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;string fax = "来自" + GetIpAddress() + "客户端的传真:" &lt;br /&gt;+ System.Environment.NewLine;&lt;br /&gt;&amp;nbsp;&amp;nbsp;fax += txtFax.Text;&lt;br /&gt;&amp;nbsp;&amp;nbsp;faxBus.SendFax(fax);&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;&amp;nbsp;else&lt;br /&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;MessageBox.Show("请输入传真内容!");&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;private string GetIpAddress()&lt;br /&gt;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;IPHostEntry ipHE = Dns.GetHostByName(Dns.GetHostName());&lt;br /&gt;&amp;nbsp;return ipHE.AddressList[0].ToString();&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;在这个按钮单击事件中，只需要调用远程对象faxBus的SendFax()方法就OK了，非常简单。可是慢着，为什么你的代码有这么多行啊？其实，没有什么奇怪的，我只是想到发传真的客户可能会很多。为了避免服务端人员犯糊涂，搞不清楚是谁发的，所以要求在传真上加上各自的签名，也就是客户端的IP地址了。既然要获得计算机的IP地址，请一定要记得加上对DNS的命名空间引用：&lt;br /&gt;using System.Net;&lt;/p&gt; &lt;p&gt;因为我们严格按照分布式处理程序的部署方式，所以在客户端只需要添加公共程序集(Common.dll)的引用就可以了。而在服务端呢，则必须添加公共程序集和远程对象程序集两者的引用。&lt;/p&gt; &lt;p&gt;OK，程序完成，我们来看看这个简陋的传真机：&lt;br /&gt;客户端：&lt;/p&gt; &lt;p&gt;&lt;img height="300" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re02.gif" width="300" border="0" /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;嘿嘿，做梦都想放假啊。好的，传真写好了，发送吧！再看看服务端，great，老板已经收到我的请假条传真了！&lt;/p&gt; &lt;p&gt;&lt;img height="300" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re03.gif" width="300" border="0" /&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;二、&amp;nbsp;客户端订阅服务端事件&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;嘿嘿，吃甘蔗要先吃甜的一段，做事情我也喜欢先做容易的。现在，好日子过去了，该吃点苦头了。我们先回忆一下刚才的实现方法，再来思考怎么实现客户端订阅服务端事件？&lt;/p&gt; &lt;p&gt;在前一节，事件被放到远程对象中，客户端激活对象后，就可以发送消息了。而在服务端，只需要订阅该事件就可以。现在思路应该反过来，由客户端订阅事件，服务端发送消息。就这么简单吗？先不要高兴得太早。我们想一想，发送消息的任务是谁来完成的？是远程对象。而远程对象是什么时候创建的呢？我们仔细思考Remoting的几种激活方式，不管是服务端激活，还是客户端激活，他们的工作原理都是：客户端决定了服务器创建远程对象实例的时机，例如调用了远程对象的方法。而服务端所作的工作则是注册该远程对象。&lt;/p&gt; &lt;p&gt;回忆这三种激活方式在服务端的代码：&lt;br /&gt;SingleCall激活方式：&lt;br /&gt;RemotingConfiguration.RegisterWellKnownServiceType(&lt;br /&gt;&amp;nbsp;&amp;nbsp;typeof(BroadCastObj),"BroadCastMessage.soap",&lt;br /&gt;&amp;nbsp;&amp;nbsp;WellKnownObjectMode.Singlecall);&lt;br /&gt;SingleTon激活方式：&lt;br /&gt;RemotingConfiguration.RegisterWellKnownServiceType(&lt;br /&gt;&amp;nbsp;&amp;nbsp;typeof(BroadCastObj),"BroadCastMessage.soap",&lt;br /&gt;&amp;nbsp;&amp;nbsp;WellKnownObjectMode.Singleton);&lt;br /&gt;客户端激活方式：&lt;br /&gt;RemotingConfiguration.ApplicationName = “BroadCastMessage.soap”&lt;br /&gt;RemotingConfiguration.RegisterActivatedServiceType(typeof(BroadCastObj));&lt;/p&gt; &lt;p&gt;请注意Register这个词语，它表达的含义就是注册。也就是说，在服务端并没有显示的创建远程对象实例。没有该实例，又如何广播消息呢？&lt;/p&gt; &lt;p&gt;或许有人会想，在注册远程对象之后，显式实例该对象不就可以了吗？也就是说，在注册后加上这一段代码：&lt;br /&gt;BroadCastObj obj = new BroadCastObj();&lt;/p&gt; &lt;p&gt;然而，我们要明白一个事实：就是服务端和客户端是处于两个不同的应用程序域中。因此在Remoting中，客户端获得的远程对象实际是服务端注册对象的代理。如果我们在注册后，人工去创建一个实例，而非Remoting在激活后自动创建的对象，那么客户端获得的对象与服务端人工创建的实例是两个迥然不同的对象。客户端获得的代理对象并没有指向你刚才创建的obj实例。所以obj发送的消息，客户端根本无法捕捉。&lt;/p&gt; &lt;p&gt;那么，我们只有望洋兴叹，束手无策了吗？别着急，别忘了在服务器注册对象方法中，还有一种方法，即Marshal方法啊。还记得Marshal的实现方式吗？&lt;br /&gt;BroadCastObj Obj = new BroadCastObj();&lt;br /&gt;ObjRef objRef = RemotingServices.Marshal(Obj,"BroadCastMessage.soap");&lt;/p&gt; &lt;p&gt;这个方法与前不一样。前面的三种方式，远程对象是根据客户端调用的方式，来自动创建的。而Marshal方法呢？则显式地创建了远程对象实例，然后将其Marshal到通道中，形成ObjRef指向对象的代理。只要生命周期没有结束，这个对象就一直存在。而此时客户端获得的对象，正是创建的Obj实例的代理。&lt;/p&gt; &lt;p&gt;OK，这个问题解决了，我们来看看具体实现。&lt;br /&gt;公共程序集和远程对象与前相似，就不再赘述，只附上代码：&lt;br /&gt;公共程序集：&lt;br /&gt;public delegate void BroadCastEventHandler(string info);&amp;nbsp;&lt;/p&gt; &lt;p&gt;public interface IBroadCast&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;event BroadCastEventHandler BroadCastEvent;&lt;br /&gt;&amp;nbsp;void BroadCastingInfo(string info);&lt;br /&gt;}&lt;br /&gt;远程对象类：&lt;br /&gt;public event BroadCastEventHandler BroadCastEvent;&lt;/p&gt; &lt;p&gt;#region IBroadCast 成员&lt;/p&gt; &lt;p&gt;//[OneWay]&lt;br /&gt;public void BroadCastingInfo(string info)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;if (BroadCastEvent != null)&lt;br /&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;BroadCastEvent(info);&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;#endregion&lt;/p&gt; &lt;p&gt;public override object InitializeLifetimeService()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;return null;&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;下面，该实现服务端了。在实现之前，我还想罗嗦几句。在第一节中，我们实现了服务端订阅客户端事件。由于订阅事件是在服务端发生的，因此事件本身并未被传送。被序列化的仅仅是传递的消息，即Fax而已。现在，方向发生了改变，传送消息的是服务端，客户端订阅了事件。但这个事件是放在远程对象中的，因此事件必须被序列化。而在.Net Framework1.1中，微软对序列化的安全级别进行了限制。有关委托和事件的序列化、反序列化默认是禁止的，所以我们应该将TypeFilterLevel的属性值设置为Full枚举值。因此在服务端注册通道的方式就发生了改变：&lt;br /&gt;private void StartServer()&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;BinaryServerFormatterSinkProvider serverProvider = new &lt;br /&gt;&amp;nbsp;&amp;nbsp;BinaryServerFormatterSinkProvider();&lt;br /&gt;&amp;nbsp;BinaryClientFormatterSinkProvider clientProvider = new &lt;br /&gt;&amp;nbsp;&amp;nbsp;BinaryClientFormatterSinkProvider();&lt;br /&gt;&amp;nbsp;serverProvider.TypeFilterLevel = TypeFilterLevel.Full;&lt;/p&gt; &lt;p&gt;&amp;nbsp;IDictionary props = new Hashtable();&lt;br /&gt;&amp;nbsp;props["port"] = 8080;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; HttpChannel channel = new HttpChannel(props,clientProvider,serverProvider);&lt;br /&gt;&amp;nbsp;ChannelServices.RegisterChannel(channel);&lt;/p&gt; &lt;p&gt;&amp;nbsp;Obj = new BroadCastObj();&lt;br /&gt;&amp;nbsp;ObjRef objRef = RemotingServices.Marshal(Obj,"BroadCastMessage.soap");&amp;nbsp;&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;注意语句serverProvider.TypeFilterLevel = TypeFilterLevel.Full；此语句即设置序列化安全级别的。要使用TypeFilterLevel属性，必须申明命名空间：&lt;br /&gt;using System.Runtime.Serialization.Formatters;&lt;/p&gt; &lt;p&gt;而后面两条语句就是注册远程对象。由于在我的广播程序中，发送广播消息是放在另一个窗口中，因此我将该远程对象声明为公共静态对象：&lt;br /&gt;public static BroadCastObj Obj = null;&lt;/p&gt; &lt;p&gt;然后在调用窗口事件中加入：&lt;br /&gt;private void ServerForm_Load(object sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;StartServer();&lt;br /&gt;&amp;nbsp;lbMonitor.Items.Add("Server started!");&lt;br /&gt;}&lt;br /&gt;来看看界面，首先启动服务端主窗口：&lt;/p&gt; &lt;p&gt;&lt;img height="312" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re04.gif" width="304" border="0" /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;我放了一个ListBox控件来显示一些信息，例如显示服务器启动了。而BroadCast按钮就是广播消息的，单击该按钮，会弹出一个对话框：&lt;/p&gt; &lt;p&gt;&lt;img height="176" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re05.gif" width="320" border="0" /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;BraodCast按钮的代码：&lt;br /&gt;private void btnBC_Click(object sender, System.EventArgs e)&lt;br /&gt;{&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;BroadCastForm bcForm = new BroadCastForm();&lt;br /&gt;&amp;nbsp;bcForm.StartPosition = FormStartPosition.CenterParent;&lt;br /&gt;&amp;nbsp;bcForm.ShowDialog();&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;在对话框中，最主要的就是Send按钮：&lt;br /&gt;if (txtInfo.Text != string.Empty)&lt;br /&gt;{ &amp;nbsp;&lt;br /&gt;&amp;nbsp;ServerForm.Obj.BroadCastingInfo(txtInfo.Text);&lt;br /&gt;}&lt;br /&gt;else&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;MessageBox.Show("请输入信息！");&lt;br /&gt;}&lt;br /&gt;但是很简单，就是调用远程对象的发送消息方法而已。&lt;/p&gt; &lt;p&gt;现在该实现客户端了。我们可以参照前面的例子，只是把服务端改为客户端而已。另外考虑到序列化安全级别的问题，所以代码会是这样：&lt;br /&gt;private void ClientForm_Load(object sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;BinaryServerFormatterSinkProvider serverProvider = new &lt;br /&gt;&amp;nbsp;&amp;nbsp;BinaryServerFormatterSinkProvider();&lt;br /&gt;&amp;nbsp;BinaryClientFormatterSinkProvider clientProvider = new &lt;br /&gt;&amp;nbsp;&amp;nbsp;BinaryClientFormatterSinkProvider();&lt;br /&gt;&amp;nbsp;serverProvider.TypeFilterLevel = TypeFilterLevel.Full;&lt;/p&gt; &lt;p&gt;&amp;nbsp;IDictionary props = new Hashtable();&lt;br /&gt;&amp;nbsp;props["port"] = 0;&lt;br /&gt;&amp;nbsp;HttpChannel channel = new HttpChannel(props,clientProvider,serverProvider);&lt;br /&gt;&amp;nbsp;ChannelServices.RegisterChannel(channel);&lt;/p&gt; &lt;p&gt;&amp;nbsp;watch = (IBroadCast)Activator.GetObject(&lt;br /&gt;&amp;nbsp;&amp;nbsp;typeof(IBroadCast),"&lt;a href="http://localhost:8080/BroadCastMessage.soap"&gt;http://localhost:8080/BroadCastMessage.soap&lt;/a&gt;");&amp;nbsp;&lt;br /&gt;&amp;nbsp;watch.BroadCastEvent += new BroadCastEventHandler(BroadCastingMessage);&lt;br /&gt;}&lt;br /&gt;注意客户端通道的端口号应设置为0，这表示客户端自动选择可用的端口号。如果要设置为指定的端口号，则必须保证与服务端通道的端口号不相同。&lt;br /&gt;然后是，BroadCastEventHandler委托的方法：&lt;br /&gt;public void BroadCastingMessage(string message)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;txtMessage.Text += "I got it:" + message;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp;txtMessage.Text += System.Environment.NewLine;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;}&lt;br /&gt;客户端界面如图：&lt;/p&gt; &lt;p&gt;&lt;img height="312" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re06.gif" width="344" border="0" /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;好，下面让我们满怀期盼，来运行这段程序。首先启动服务端应用程序，然后启动客户端。哎呀，糟糕，居然出现了错误信息！&lt;/p&gt; &lt;p&gt;&lt;img height="166" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re07.gif" width="437" border="0" /&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;“人之不如意事，十常居八九。”不用沮丧，让我们分析原因。首先看看错误信息，它报告我们没有找到Client程序集。然而事实上，Client程序集当然是有的。那么再来调试一下，是哪一步出现的问题呢？设置好断点，进行逐语句跟踪。前面注册通道一切正常，当运行到watch.BroadCastEvent += new BroadCastEventHandler(BroadCastingMessage)语句时，错误出现了！&lt;/p&gt; &lt;p&gt;也就是说，远程对象的创建是成功的，但在订阅事件的时候失败了。原因是什么呢？原来，客户端的委托是通过序列化后获得的，在订阅事件的时候，委托试图装载包含与签名相同的方法的程序集，也就是BroadCastingMessage方法所在的程序集Client。然而这个装载的过程发生在服务端，而在服务端，并没有Client程序集存在，自然就发生了上面的异常。&lt;/p&gt; &lt;p&gt;原因清楚了，怎么解决？首先BroadCastingMessage方法肯定是在客户端中，所以不可避免，委托装载Client程序集的过程也必须在客户端完成。而服务端事件又是由远程对象来捕获的，因此，在客户端注册的也就必须是远程对象事件了。一个要求必须在客户端，一个又要求必须在服务端，事情出现了自相矛盾的地方。&lt;/p&gt; &lt;p&gt;那么，让我们先想想这样一个例子。假设我们要交换x和y的值，该这样完成？很简单，引入一个中间变量就可以了。&lt;br /&gt;int x=1,y=2,z;&lt;br /&gt;z = x;&lt;br /&gt;x = y;&lt;br /&gt;y = z;&lt;br /&gt;这个游戏相信大家都会玩吧，那么好的，我们也需要引入这样一个“中间”对象。这个中间对象和原来的远程对象在事件处理方面，代码完全一致：&lt;br /&gt;public class EventWrapper:MarshalByRefObject&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;public event BroadCastEventHandler LocalBroadCastEvent;&lt;/p&gt; &lt;p&gt;&amp;nbsp;//[OneWay]&lt;br /&gt;&amp;nbsp;public void BroadCasting(string message)&lt;br /&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;LocalBroadCastEvent(message);&lt;br /&gt;&amp;nbsp;}&lt;/p&gt; &lt;p&gt;&amp;nbsp;public override object InitializeLifetimeService()&lt;br /&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;return null;&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;不过不同之处在于：这个Wrapper类必须在客户端和服务端上都要部署，所以，这个类应该放在公共程序集Common.dll中。&lt;/p&gt; &lt;p&gt;现在再来修改原来的客户端代码：&lt;br /&gt;watch = (IBroadCast)Activator.GetObject(&lt;br /&gt;&amp;nbsp;&amp;nbsp;typeof(IBroadCast),"&lt;a href="http://localhost:8080/BroadCastMessage.soap"&gt;http://localhost:8080/BroadCastMessage.soap&lt;/a&gt;");&amp;nbsp;&lt;br /&gt;watch.BroadCastEvent += new BroadCastEventHandler(BroadCastingMessage);&lt;br /&gt;修改为：&lt;br /&gt;watch = (IBroadCast)Activator.GetObject(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;typeof(IBroadCast),"&lt;a href="http://localhost:8080/BroadCastMessage.soap"&gt;http://localhost:8080/BroadCastMessage.soap&lt;/a&gt;");&lt;br /&gt;EventWrapper wrapper = new EventWrapper();&amp;nbsp;&lt;br /&gt;wrapper.LocalBroadCastEvent += new BroadCastEventHandler(BroadCastingMessage);&lt;br /&gt;watch.BroadCastEvent += new BroadCastEventHandler(wrapper.BroadCasting);&lt;/p&gt; &lt;p&gt;为什么这样做就可以了呢？也许画一幅图就很容易说明，可惜我的艺术天分实在很糟糕，我希望以后可以改进这一点。还是用文字来说明吧。&lt;/p&gt; &lt;p&gt;前面说，委托要装载client程序集。现在我们把远程对象委托装载的权利移交给EventWrapper。因为这个类对象是放在客户端的，所以它要装载client程序集丝毫没有问题。语句：&lt;br /&gt;EventWrapper wrapper = new EventWrapper();&amp;nbsp;&lt;br /&gt;wrapper.LocalBroadCastEvent += new BroadCastEventHandler(BroadCastingMessage);&lt;br /&gt;实现了这个功能。&lt;/p&gt; &lt;p&gt;不过此时虽然订阅了事件，但事件还是客户端的，没有与服务端联系起来。而服务端的事件是放到远程对象中的，所以，还要订阅事件，这个任务由远程对象watch来完成。但此时它订阅的不再是BroadCastingMessage了，而是EventWrapper的触发事件方法BroadCasting。那么此时委托同样要装载程序集，但此时装载的就是BroadCasting所在的程序集了。由于装载发生的地点是在服务端。呵呵，高兴的是，BroadCasting所在的程序集正是公共程序集（前面已说过，EventWrapper应放到公共程序集Common.dll中），而公共程序集在服务端和客户端都已经部署了。自然就不会出现找不到程序集的问题了。&lt;/p&gt; &lt;p&gt;注意：EventWrapper因为要重写InitializeLifetimeService()方法，所以仍然要继承MarshalByRefObject类。&lt;/p&gt; &lt;p&gt;现在再来运行程序。首先运行服务端；然后运行客户端，OK，客户端窗体出现了：&lt;/p&gt; &lt;p&gt;&lt;img height="312" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re06.gif" width="344" border="0" /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;然后我们在服务端单击“BroadCast”按钮，发送广播消息：&lt;/p&gt; &lt;p&gt;&lt;img height="176" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re08.gif" width="320" border="0" /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;单击“Send”发送，再来看看客户端，会是怎样？Fine，I got it!&lt;/p&gt; &lt;p&gt;&lt;img height="312" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re09.gif" width="344" border="0" /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;怎么样，很酷吧！你也可以同时打开多个客户端，它们都将收到这个广播信息。如果你觉得这个广播声音太吵，那就请你在客户端取消广播吧。在Cancle按钮中：&lt;br /&gt;private void btnCancle_Click(object sender, System.EventArgs e)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;watch.BroadCastEvent -= new BroadCastEventHandler(wrapper.BroadCasting);&lt;br /&gt;&amp;nbsp;MessageBox.Show("取消订阅广播成功!");&lt;br /&gt;}&lt;br /&gt;当然这个时候wrapper对象应该被申明为private对象了：&lt;br /&gt;private EventWrapper wrapper = null;&lt;/p&gt; &lt;p&gt;&lt;img height="100" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re10.gif" width="128" border="0" /&gt;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;取消后，你试着再广播一下，恭喜你，你不会听到噪音了！&lt;/p&gt; &lt;p&gt;&lt;strong&gt;三、&amp;nbsp;客户端订阅客户端事件&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;有了前面的基础，再来看客户端订阅客户端事件，就简单多了。而本文写到这里，我也很累了，你也被我啰嗦得不耐烦了。你心里在喊，“饶了我吧！”其实，我又何尝不是如此。所以我只提供一个思路，有兴趣的朋友，可以自己写一个程序。&lt;/p&gt; &lt;p&gt;其实方法很简单，和第二种情况类似。发送信息的客户端，只需要获得远程对象后，发送消息就可以了。而接收信息的客户端，负责订阅该事件。由于事件都是放到远程对象中，因此订阅的方法和第二种情况没有什么区别！&lt;/p&gt; &lt;p&gt;特殊的情况是，我们可以用第三种情况来代替第二种。只要你把发送信息的客户端放到服务端就可以了。当然需要做一些额外的工作，有兴趣的朋友可以去实现一下。在我的示例程序中，已经用这种方法模拟实现了服务端的广播，大家可以去看看。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;四、&amp;nbsp;一点补充&lt;br /&gt;&lt;/strong&gt;&lt;br /&gt;我在前面的事件处理中，使用的都是默认的EventArgs。如果要定义自己的EventArgs，就不相同了。因为该信息是传值序列化，因此必须加上[Serializable]，且必须放到公共程序集中，部署到服务端和客户端。例如：&lt;br /&gt;[Serializable]&lt;br /&gt;public class BroadcastEventArgs:EventArgs&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;private string msg = null;&lt;br /&gt;&amp;nbsp;public BroadcastEventArgs(string message)&lt;br /&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;msg = message;&lt;br /&gt;&amp;nbsp;}&lt;/p&gt; &lt;p&gt;&amp;nbsp;public string Message&lt;br /&gt;&amp;nbsp;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;get {return msg;}&lt;br /&gt;&amp;nbsp;}&lt;br /&gt;}&lt;/p&gt; &lt;p&gt;&lt;strong&gt;五、持续改进（经Beta的提醒，我改进了我的程序，并对文章进行了修改 2004年12月13日）&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;也许，细心的读者注意到了，在我的远程对象类和EventWrapper类中，触发事件方法的Attribute[OneWay]被我注释掉了。我看到很多资料上写到，在Remoting中处理事件，触发事件的方法必须具有这个Attribute。这个attribute究竟有什么用？&lt;/p&gt; &lt;p&gt;在发送事件消息的时候，事件的订阅者会触发事件，然后响应该事件。然而当事件的订阅者发生错误的时候呢？例如，发送事件消息的时候，才发现根本没有事件订阅者；或者事件的订阅者出现故障，如断电、或异常关机。此时，发送事件一方会因为找不到正确的事件订阅者，而发生异常。以我的程序为例。当我们分别打开服务端和客户端程序的时候，此时广播信息正常。然而，当我们关闭客户端后，由于该客户端没有取消订阅，此时异常发生，提示信息如图：&lt;/p&gt; &lt;p&gt;&lt;img height="152" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re11.gif" width="437" border="0" /&gt;&lt;/p&gt; &lt;p&gt;（不知道为什么，这个异常与客户端连接服务端出现的异常一样。这个异常容易让人产生误会。）&lt;/p&gt; &lt;p&gt;如果这个时候我们同时打开了多个客户端，那么其他客户端就会因为这一个客户端关闭造成的错误，而无法收到广播信息。那么让我们先做第一步改进：&lt;/p&gt; &lt;p&gt;1、先考虑正常情况。在我的客户端，虽然提供了取消订阅的操作，但并没有考虑用户关闭客户端的情况。即，关闭客户端时，并未取消事件的订阅，所以我们应该在关闭客户端窗体中写入：&lt;/p&gt; &lt;div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"&gt; &lt;div&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align="top" /&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;private&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;ClientForm_Closing(&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;sender,&amp;nbsp;System.ComponentModel.CancelEventArgs&amp;nbsp;e)&lt;br /&gt;&lt;img id="Codehighlighter1_92_172_Open_Image" onclick="this.style.display='none'; Codehighlighter1_92_172_Open_Text.style.display='none'; Codehighlighter1_92_172_Closed_Image.style.display='inline'; Codehighlighter1_92_172_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /&gt;&lt;img id="Codehighlighter1_92_172_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_92_172_Closed_Text.style.display='none'; Codehighlighter1_92_172_Open_Image.style.display='inline'; Codehighlighter1_92_172_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span id="Codehighlighter1_92_172_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/images/dot.gif" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_92_172_Open_Text"&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;watch.BroadCastEvent&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;-=&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;new&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;BroadCastEventHandler(wrapper.BroadCasting);&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;2、仅仅是这样还不够。如果客户端并没有正常关闭，而是因为突然断电而导致客户端关闭呢？此时，客户端还没有来得及取消事件订阅呢。在这种情况下，我们需要用到OneWayAttribute。&lt;/p&gt; &lt;p&gt;前面说到，发送事件一方如果找不到正确的事件订阅者，会发生异常。也就是说，这个事件是unreachable的。幸运的是，OneWayAttribute恰好解决了这个问题。其实从该特性的命名OneWay，大约也能猜到其中的含义。当事件不可到达，无法发送时，正常情况下，会返回一个异常信息。如果加上OneWayAttribute，这个事件的发送就变成单向的了。假如此时发生异常，那么系统会自动抛掉该异常信息。由于没有异常信息的返回，发送信息方会认为发送信息成功了。程序会正常运行，错误的客户端被忽略，而正确的客户端仍然能够收到广播信息。&lt;/p&gt; &lt;p&gt;因此，远程对象的代码就应该是这样：&lt;/p&gt; &lt;div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"&gt; &lt;div&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align="top" /&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;event&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;BroadCastEventHandler&amp;nbsp;BroadCastEvent;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align="top" /&gt;&lt;br /&gt;&lt;img id="Codehighlighter1_52_201_Closed_Image" onclick="this.style.display='none'; Codehighlighter1_52_201_Closed_Text.style.display='none'; Codehighlighter1_52_201_Open_Image.style.display='inline'; Codehighlighter1_52_201_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /&gt;&lt;img id="Codehighlighter1_52_201_Open_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_52_201_Open_Text.style.display='none'; Codehighlighter1_52_201_Closed_Image.style.display='inline'; Codehighlighter1_52_201_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_52_201_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;IBroadCast&amp;nbsp;成员&lt;/span&gt;&lt;span id="Codehighlighter1_52_201_Open_Text" style="DISPLAY: none"&gt;&lt;span style="COLOR: #0000ff"&gt;#region&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;IBroadCast&amp;nbsp;成员&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&gt;&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;//&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;[OneWay]&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&gt;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;BroadCastingInfo(&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;info)&lt;br /&gt;&lt;img id="Codehighlighter1_128_189_Open_Image" onclick="this.style.display='none'; Codehighlighter1_128_189_Open_Text.style.display='none'; Codehighlighter1_128_189_Closed_Image.style.display='inline'; Codehighlighter1_128_189_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /&gt;&lt;img id="Codehighlighter1_128_189_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_128_189_Closed_Text.style.display='none'; Codehighlighter1_128_189_Open_Image.style.display='inline'; Codehighlighter1_128_189_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_128_189_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/images/dot.gif" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_128_189_Open_Text"&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;(BroadCastEvent&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;!=&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;)&lt;br /&gt;&lt;img id="Codehighlighter1_160_187_Open_Image" onclick="this.style.display='none'; Codehighlighter1_160_187_Open_Text.style.display='none'; Codehighlighter1_160_187_Closed_Image.style.display='inline'; Codehighlighter1_160_187_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /&gt;&lt;img id="Codehighlighter1_160_187_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_160_187_Closed_Text.style.display='none'; Codehighlighter1_160_187_Open_Image.style.display='inline'; Codehighlighter1_160_187_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /&gt;&amp;nbsp;&lt;/span&gt;&lt;span id="Codehighlighter1_160_187_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/images/dot.gif" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_160_187_Open_Text"&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&gt;&amp;nbsp;&amp;nbsp;BroadCastEvent(info);&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /&gt;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /&gt;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;#endregion&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align="top" /&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align="top" /&gt;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;override&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;object&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;InitializeLifetimeService()&lt;br /&gt;&lt;img id="Codehighlighter1_255_271_Open_Image" onclick="this.style.display='none'; Codehighlighter1_255_271_Open_Text.style.display='none'; Codehighlighter1_255_271_Closed_Image.style.display='inline'; Codehighlighter1_255_271_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /&gt;&lt;img id="Codehighlighter1_255_271_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_255_271_Closed_Text.style.display='none'; Codehighlighter1_255_271_Open_Image.style.display='inline'; Codehighlighter1_255_271_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_255_271_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/images/dot.gif" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_255_271_Open_Text"&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;return&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align="top" /&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align="top" /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;3、最后的改进&lt;/p&gt; &lt;p&gt;使用OneWay固然可以解决上述的问题，但不够友好。因为对于广播消息的一方来说，象被蒙上了眼睛一样，对于客户端发生的事情懵然不知。这并不是一个好的idea。在Ingo Rammer的Advanced .NET Remoting一书中，Ingo Rammer先生提出了一个更好的办法，就是在发送信息一方时，检查了委托链。并在委托链的遍历中来捕获异常。当其中一个委托发生异常时，显示提示信息。然后继续遍历后面的委托，这样既保证了异常信息的提示，又保证了其他订阅者正常接收消息。因此，我对本例的远程对象进行了修改，注释掉[OneWay]，修改了BroadCastInfo()方法：&lt;/p&gt; &lt;div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"&gt; &lt;div&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align="top" /&gt;&lt;span style="COLOR: #008000"&gt;//&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;[OneWay]&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/None.gif" align="top" /&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;public&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;void&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;BroadCastingInfo(&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;string&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;info)&lt;br /&gt;&lt;img id="Codehighlighter1_57_586_Open_Image" onclick="this.style.display='none'; Codehighlighter1_57_586_Open_Text.style.display='none'; Codehighlighter1_57_586_Closed_Image.style.display='inline'; Codehighlighter1_57_586_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" /&gt;&lt;img id="Codehighlighter1_57_586_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_57_586_Closed_Text.style.display='none'; Codehighlighter1_57_586_Open_Image.style.display='inline'; Codehighlighter1_57_586_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedBlock.gif" align="top" /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span id="Codehighlighter1_57_586_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/images/dot.gif" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_57_586_Open_Text"&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;/span&gt;&lt;span style="COLOR: #0000ff"&gt;if&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;(BroadCastEvent&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;!=&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;)&lt;br /&gt;&lt;img id="Codehighlighter1_93_513_Open_Image" onclick="this.style.display='none'; Codehighlighter1_93_513_Open_Text.style.display='none'; Codehighlighter1_93_513_Closed_Image.style.display='inline'; Codehighlighter1_93_513_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /&gt;&lt;img id="Codehighlighter1_93_513_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_93_513_Closed_Text.style.display='none'; Codehighlighter1_93_513_Open_Image.style.display='inline'; Codehighlighter1_93_513_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /&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;/span&gt;&lt;span id="Codehighlighter1_93_513_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/images/dot.gif" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_93_513_Open_Text"&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;BroadCastEventHandler&amp;nbsp;tempEvent&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;=&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;null&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;int&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;index&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;=&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;1&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;//&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;记录事件订阅者委托的索引，为方便标识，从1开始。&lt;/span&gt;&lt;span style="COLOR: #008000"&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&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;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;foreach&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;(Delegate&amp;nbsp;del&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;in&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;BroadCastEvent.GetInvocationList())&lt;br /&gt;&lt;img id="Codehighlighter1_255_504_Open_Image" onclick="this.style.display='none'; Codehighlighter1_255_504_Open_Text.style.display='none'; Codehighlighter1_255_504_Closed_Image.style.display='inline'; Codehighlighter1_255_504_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /&gt;&lt;img id="Codehighlighter1_255_504_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_255_504_Closed_Text.style.display='none'; Codehighlighter1_255_504_Open_Image.style.display='inline'; Codehighlighter1_255_504_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /&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;&lt;/span&gt;&lt;span id="Codehighlighter1_255_504_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/images/dot.gif" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_255_504_Open_Text"&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;try&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br /&gt;&lt;img id="Codehighlighter1_271_347_Open_Image" onclick="this.style.display='none'; Codehighlighter1_271_347_Open_Text.style.display='none'; Codehighlighter1_271_347_Closed_Image.style.display='inline'; Codehighlighter1_271_347_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /&gt;&lt;img id="Codehighlighter1_271_347_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_271_347_Closed_Text.style.display='none'; Codehighlighter1_271_347_Open_Image.style.display='inline'; Codehighlighter1_271_347_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span id="Codehighlighter1_271_347_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/images/dot.gif" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_271_347_Open_Text"&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tempEvent&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;=&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;(BroadCastEventHandler)del;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;tempEvent(info);&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #0000ff"&gt;catch&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br /&gt;&lt;img id="Codehighlighter1_365_484_Open_Image" onclick="this.style.display='none'; Codehighlighter1_365_484_Open_Text.style.display='none'; Codehighlighter1_365_484_Closed_Image.style.display='inline'; Codehighlighter1_365_484_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /&gt;&lt;img id="Codehighlighter1_365_484_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_365_484_Closed_Text.style.display='none'; Codehighlighter1_365_484_Open_Image.style.display='inline'; Codehighlighter1_365_484_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;span id="Codehighlighter1_365_484_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/images/dot.gif" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_365_484_Open_Text"&gt;&lt;span style="COLOR: #000000"&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;MessageBox.Show(&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;"&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;事件订阅者&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;"&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;+&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;index.ToString()&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;+&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;"&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;发生错误,系统将取消事件订阅!&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;"&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;);&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BroadCastEvent&amp;nbsp;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;-=&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&amp;nbsp;tempEvent;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;index&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;++&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /&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;}&lt;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&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;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /&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;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;/span&gt;&lt;span style="COLOR: #0000ff"&gt;else&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br /&gt;&lt;img id="Codehighlighter1_526_582_Open_Image" onclick="this.style.display='none'; Codehighlighter1_526_582_Open_Text.style.display='none'; Codehighlighter1_526_582_Closed_Image.style.display='inline'; Codehighlighter1_526_582_Closed_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /&gt;&lt;img id="Codehighlighter1_526_582_Closed_Image" style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_526_582_Closed_Text.style.display='none'; Codehighlighter1_526_582_Open_Image.style.display='inline'; Codehighlighter1_526_582_Open_Text.style.display='inline';" src="http://www.cnblogs.com/images/OutliningIndicators/ContractedSubBlock.gif" align="top" /&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;/span&gt;&lt;span id="Codehighlighter1_526_582_Closed_Text" style="BORDER-RIGHT: #808080 1px solid; BORDER-TOP: #808080 1px solid; DISPLAY: none; BORDER-LEFT: #808080 1px solid; BORDER-BOTTOM: #808080 1px solid; BACKGROUND-COLOR: #ffffff"&gt;&lt;img src="http://www.cnblogs.com/images/dot.gif" /&gt;&lt;/span&gt;&lt;span id="Codehighlighter1_526_582_Open_Text"&gt;&lt;span style="COLOR: #000000"&gt;{&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/InBlock.gif" align="top" /&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;MessageBox.Show(&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;"&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;事件未被订阅或订阅发生错误!&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;"&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;);&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" /&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;/span&gt;&lt;/span&gt;&lt;span style="COLOR: #000000"&gt;&lt;br /&gt;&lt;img src="http://www.cnblogs.com/images/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt; &lt;p&gt;我们来试验一下。首先打开服务端，然后同时打开三个客户端。广播消息：&lt;/p&gt; &lt;p&gt;&lt;img height="375" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re12.gif" width="500" border="0" /&gt;&lt;/p&gt; &lt;p&gt;消息发送正常。&lt;/p&gt; &lt;p&gt;接着关闭其中一个客户端窗口，再广播消息（注意为模拟客户端异常情况，应在ClientForm_Closing方法中把第一步改进的取消订阅代码注释。否则不会发生异常。难道你真的愿意用断电来导致异常发生吗^_^），结果如图：&lt;/p&gt; &lt;p&gt;&lt;img height="375" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re13.gif" width="500" border="0" /&gt;&lt;/p&gt; &lt;p&gt;此时服务端报告了“事件订阅者1发生错误，系统将取消事件订阅”。注意此时另外两个客户端，还是和前面一样，只有两条广播信息。&lt;/p&gt; &lt;p&gt;当我们点击提示框的“确定”按钮后，广播仍然发送：&lt;/p&gt; &lt;p&gt;&lt;img height="375" src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/re14.gif" width="500" border="0" /&gt;&lt;/p&gt; &lt;p&gt;通过这样的改进后，程序更加的完善，也更加的健壮和友好！&lt;/p&gt; &lt;p&gt;&lt;font color="#006400"&gt;附：&lt;br /&gt;示例代码说明：&lt;br /&gt;1、&amp;nbsp;Remoting事件(客户端发传真)压缩包：为第一节内容；&lt;br /&gt;2、&amp;nbsp;Remoting事件(服务端广播)压缩包：为第二节、第三节内容，其中：&lt;br /&gt;第二节代码包含于：&lt;br /&gt;#region 客户端订阅服务端事件&lt;br /&gt;#endregion&lt;br /&gt;第三节代码包含于：&lt;br /&gt;#region 客户端订阅客户端事件&lt;br /&gt;#endregion&lt;br /&gt;如果要实现第二节的程序，请注释掉第三节代码；反之亦然。示例程序默认为第二节程序。&lt;br /&gt;3、&amp;nbsp;运行示例程序时，请先运行服务端程序，然后运行客户端程序。否则会抛出“基础连接已关闭”的异常。&lt;br /&gt;4、&amp;nbsp;解决方案均放在Common（或ICommon）文件夹中。&lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font color="#a52a2a"&gt;5、改进后的代码放到Remoting事件(服务端广播改进)压缩包中，大家可以比较一下改进后的程序有何不同！&lt;/font&gt;&lt;/p&gt; &lt;p&gt;参考资料：&lt;br /&gt;1、&amp;nbsp;Ingo Rammer，《Advanced .NET Remoting》&lt;br /&gt;2、&amp;nbsp;吕震宇，《&lt;A href="http://www.cnblogs.com/zhenyulu/articles/29357.html"&gt;利用Event松耦合远程对象与远程系统&lt;/a&gt;》&lt;br /&gt;3、&amp;nbsp;大坏蛋，《&lt;A href="http://www.cnblogs.com/dahuaidan410/articles/31656.html"&gt;.NET Remoting中的事件处理(.NET Framework 2.0)（一）&lt;/a&gt;》&lt;/p&gt;&lt;/div&gt;&lt;br /&gt;  &lt;p class="postfoot"&gt;&lt;br /&gt;   posted on 2004-12-13 10:42 &lt;a href='http://wayfarer.cnblogs.com/'&gt;Bruce Zhang&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-6081109716195233128?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/6081109716195233128/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=6081109716195233128&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6081109716195233128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6081109716195233128'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/04/microsoft-net-remotingremotingbruce.html' title='Microsoft .Net Remoting系列专题之三：Remoting事件处理全接触（Bruce Zhang&apos;s Blog）'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-6894455295300355606</id><published>2007-04-29T10:31:00.000+08:00</published><updated>2007-05-10T09:57:17.571+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Remoting'/><title type='text'>Microsoft .Net Remoting系列专题之二：Marshal、Disconnect与生命周期以及跟踪服务（Bruce Zhang's Blog）</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;&lt;a id="viewpost1_TitleUrl" href="http://www.cnblogs.com/wayfarer/archive/2004/08/05/30437.html"&gt;Microsoft .Net Remoting系列专题之二：Marshal、Disconnect与生命周期以及跟踪服务&lt;/a&gt;&lt;br /&gt;&lt;div class="postText"&gt;&lt;FONT face=楷体_GB2312&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT face=楷体_GB2312&gt;我写的.Net Remoting系列专题：&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;A id=viewpost1_TitleUrl href="/wayfarer/archive/2004/07/30/28723.html"&gt;&lt;FONT color=#000080&gt;Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇&lt;/FONT&gt;&lt;/A&gt;&lt;A id=viewpost1_TitleUrl href="/wayfarer/archive/2004/08/05/30437.html"&gt;&lt;/A&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;A id=viewpost1_TitleUrl href="/wayfarer/articles/75213.html"&gt;&lt;FONT color=#000080&gt;Microsoft .Net Remoting系列专题之三：Remoting事件处理全接触&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;/FONT&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;&lt;STRONG&gt;&lt;FONT color=#000000&gt;Microsoft .Net Remoting系列专题之二&lt;/FONT&gt;&lt;/STRONG&gt;&amp;nbsp;&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;&lt;STRONG&gt;一、远程对象的激活&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;在Remoting中有三种激活方式，一般的实现是通过RemotingServices类的静态方法来完成。工作过程事实上是将该远程对象注册到通道中。由于Remoting没有提供与之对应的Unregister方法来注销远程对象，所以如果需要注册/注销指定对象，微软推荐使用Marshal（一般译为编组）和Disconnect配对使用。在《&lt;A href="http://www.brucezhang.com/?p=70" rel=bookmark mce_href="http://www.brucezhang.com/?p=70"&gt;Net Remoting基础篇&lt;/A&gt;》中我已经谈到：Marshal()方法是将MarshalByRefObject类对象转化为ObjRef类对象，这个对象是存储生成代理以与远程对象通讯所需的所有相关信息。这样就可以将该实例序列化以便在应用程序域之间以及通过网络进行传输，客户端就可以调用了。而Disconnect()方法则将具体的实例对象从通道中断开。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;根据上述说明，Marshal()方法对远程对象以引用方式进行编组（Marshal-by-Reference，MBR），并将对象的代理信息放到通道中。客户端可以通过Activator.GetObject()来获取。如果用户要注销该对象，则通过调用Disconnect()方法。那么这种方式对于编组的远程对象是否存在生命周期的管理呢？这就是本文所要描述的问题。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;&lt;STRONG&gt;二、生命周期&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;在CLR中，框架提供了GC（垃圾回收器）来管理内存中对象的生命周期。同样的，.Net Remoting使用了一种分布式垃圾回收，基于租用的形式来管理远程对象的生命周期。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;早期的DCOM对于对象生命周期的管理是通过ping和引用计数来确定对象何时应当作为垃圾回收。然而ping引起的网络流量对分布式应用程序的性能是一种痛苦的负担，它大大地影响了分布式处理的整体性能。.Net Remoting在每个应用程序域中都引入一个租用管理器，为每个服务器端的SingleTon，或每个客户端激活的远程对象保存着对租用对象的引用。（说明：对于服务器端激活的SingleCall方式，由于它是无状态的，对于每个激活的远程对象，都由CLR的GC来自动回收，因此对于SingleCall模式激活的远程对象，不存在生命周期的管理。）&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;1、租用&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;租用是个封装了TimeSpan值的对象，用以管理远程对象的生存期。在.Net Remoting中提供了定义租用功能的ILease接口。当Remoting通过SingleTon模式或客户端激活模式来激活远程对象时，租用对象调用从System.MarshalByRefObject继承的InitializeLifetimeService方法，向对象请求租用。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;ILease接口定义了有关生命周期的属性，均为TimeSpan值。如下：&lt;BR&gt;InitialLeaseTime：初始化有效时间，默认值为300秒，如果为0，表示永不过期；&lt;BR&gt;RenewOnCallTime：调用远程对象一个方法时的租用更新时间，默认值为120秒；&lt;BR&gt;SponsorshipTimeout：超时值，通知Sponsor（发起人）租用过期后，Remoting会等待的时间，默认值为120秒；&lt;BR&gt;CurrentLeaseTime：当前租用时间，首次获得租用时，为InitializeLeaseTime的值。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;Remoting的远程对象因为继承了MarshalByRefObject，因此默认继承了InitializeLifetimeService方法，那么租用的相关属性为默认值。如果要改变这些设置，可以在远程对象中重写该方法。例如：&lt;BR&gt;&amp;nbsp;public override object InitializeLifetimeService()&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;ILease lease = (ILease)base.InitializeLifetimeService();&lt;BR&gt;&amp;nbsp;&amp;nbsp;if (lease.CurrentState == LeaseState.Initial)&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;lease.InitialLeaseTime = TimeSpan.FromMinutes(1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;lease.RenewOnCallTime = TimeSpan.FromSeconds(20);&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;return lease;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;}&lt;/P&gt;&lt;br /&gt;&lt;P&gt;也可以忽略该方法，将对象的租用周期改变为无限：&lt;BR&gt;&amp;nbsp;public override object InitializeLifetimeService()&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;return null;&lt;BR&gt;&amp;nbsp;}&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;2、租用管理器&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;如果是前面所说的租用主要是应用在每个具体的远程对象上，那么租用管理器是服务器端专门用来管理远程对象生命周期的管理器，它维持着一个System.Hashtable成员，将租用映射为System.DateTime实例表示每个租用何时应过期。Remoting采用轮询的方式以一定的时间唤醒租用管理器，检查每个租用是否过期。默认为每10秒钟唤醒一次。轮询的间隔可以配置，如将轮询间隔设置为5分钟：LifetimeService.LeaseManagerPollTime = System.TimeSpan.FromMinutes(5);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;我们还可以在租用管理器中设置远程对象租用的属性，如改变远程对象的初始有效时间为永久有效：&lt;BR&gt;LifetimeServices.LeaseTime = TimeSpan.Zero;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;我们也可以通过配置文件来设置生命周期，如：&lt;BR&gt;&amp;amp;lt;configuration&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;amp;lt;system.runtime.remoting&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;amp;lt;application name = "SimpleServer"&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;amp;lt;lifetime leaseTime = "0" sponsorshipTimeOut = "1M"&amp;nbsp;renewOnCallTime = "1M" pollTime = "30S"/&amp;amp;gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;amp;lt;/application&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;amp;lt;/system.runtime.remoting&amp;amp;gt;&lt;BR&gt;&amp;amp;lt;/configuration&amp;amp;gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;注：配置文件中的pollTime即为上面所说的租用管理器的轮询间隔时间LeaseManagerPollTime。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;租用管理器对于生命周期的设置是针对服务器上所有的远程对象。当我们通过配置文件或租用管理器设置租用的属性时，所有远程对象的生命周期都遵循该设置，除非我们对于指定的远程对象通过重写InitializeLifetimeService方法，改变了相关配置。也就是说，远程对象的租用配置优先级高于服务器端配置。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;3、发起人（Sponsor）&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;发起人是针对客户端而言的。远程对象就是发起人要租用的对象，发起人可以与服务器端签订租约，约定租用时间。一旦到期后，发起人还可以续租，就像现实生活中租方的契约，房东、租房者之间的关系一样。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;在.Net Framework中的System.Runtime.Remoting.Lifetime命名空间中定义了ClientSponsor类，该类继承了System.MarshalByRefObject，并实现了ISponsor接口。ClientSponsor类的属性和方法，可以参考MSDN。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;客户端要使用发起人机制，必须创建ClientSponsor类的一个实例。然后调用相关方法如Register()或Renewal()方法来注册远程对象或延长生命周期。如：&lt;BR&gt;RemotingObject obj = new RemotingObject();&lt;BR&gt;ClientSponsor sponsor = new ClientSponsor();&lt;BR&gt;sponsor.RenewalTime = TimeSpan.FromMinutes(2);&lt;BR&gt;sponsor.Register(obj);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;续租时间也可以在ClientSponsor的构造函数中直接设置，如：&lt;BR&gt;ClientSponsor sponsor = new ClientSponsor(TimeSpan.FromMinutes(2));&lt;BR&gt;sponsor.Register(obj);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;我们也可以自己编写Sponsor来管理发起人机制，这个类必须继承ClientSponsor并实现ISponsor接口。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;&lt;STRONG&gt;三、跟踪服务&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;如前所述，我们要判断通过Marshal编组远程对象是否存在生命周期的管理。在Remoting中，可以通过跟踪服务程序来监视MBR对象的编组进程。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;我们可以创建一个简单的跟踪处理程序，该程序实现接口ITrackingHandler。接口ITrackingHandler定义了3个方法，MarshalObject、UnmarshalObject和DisconnectedObject。当远程对象被编组、解组和断开连接时，就会调用相应的方法。下面是该跟踪处理类的代码：public class MyTracking:ITrackingHandler&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;public MyTracking()&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;&amp;nbsp;// TODO: 在此处添加构造函数逻辑&lt;BR&gt;&amp;nbsp;&amp;nbsp;//&lt;BR&gt;&amp;nbsp;}&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;public void MarshaledObject(object obj,ObjRef or)&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;Console.WriteLine();&lt;BR&gt;&amp;nbsp;&amp;nbsp;Console.WriteLine("对象" + obj.Tostring() + " is marshaled at " + DateTime.Now.ToShortTimeString());&lt;BR&gt;&amp;nbsp;}&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;public void UnmarshaledObject(object obj,ObjRef or)&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;Console.WriteLine();&lt;BR&gt;&amp;nbsp;&amp;nbsp;Console.WriteLine("对象" + obj.Tostring() + " is unmarshaled at " + DateTime.Now.ToShortTimeString());&lt;BR&gt;&amp;nbsp;}&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;public void DisconnectedObject(object obj)&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;Console.WriteLine(obj.ToString() + " is disconnected at " + DateTime.Now.ToShortTimeString());&lt;BR&gt;&amp;nbsp;}&lt;BR&gt;}&lt;/P&gt;&lt;br /&gt;&lt;P&gt;然后再服务器端创建该跟踪处理类的实例，并注册跟踪服务：&lt;BR&gt;TrackingServices.RegisterTrackingHandler(new MyTracking());&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;&lt;STRONG&gt;四、测试&lt;/STRONG&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;1、建立两个远程对象，并重写InitializeLifetimeService方法：&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;对象一：AppService1&lt;BR&gt;初始生命周期：1分钟&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;public class AppService1:MarshalByRefObject&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;public void PrintString(string contents)&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(contents);&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;public override object InitializeLifetimeService()&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ILease lease = (ILease)base.InitializeLifetimeService();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (lease.CurrentState == LeaseState.Initial)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lease.InitialLeaseTime = TimeSpan.FromMinutes(1);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lease.RenewOnCallTime = TimeSpan.FromSeconds(20);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return lease;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;}&lt;/P&gt;&lt;br /&gt;&lt;P&gt;对象二：AppService2&lt;BR&gt;初始生命周期：3分钟&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;public class AppService2:MarshalByRefObject&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;public void PrintString(string contents)&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;Console.WriteLine(contents);&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;public override object InitializeLifetimeService()&lt;BR&gt;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;ILease lease = (ILease)base.InitializeLifetimeService();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (lease.CurrentState == LeaseState.Initial)&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lease.InitialLeaseTime = TimeSpan.FromMinutes(3);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;lease.RenewOnCallTime = TimeSpan.FromSeconds(40);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;return lease;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;&amp;nbsp;}&lt;/P&gt;&lt;br /&gt;&lt;P&gt;为简便起见，两个对象的方法都一样。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;2、服务器端&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;(1) 首先建立如上的监控处理类；&lt;/P&gt;&lt;br /&gt;&lt;P&gt;(2) 注册通道：&lt;BR&gt;TcpChannel channel = new TcpChannel(8080);&lt;BR&gt;ChannelServices.RegisterChannel(channel);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;(3) 设置租用管理器的初始租用时间为无限：&lt;BR&gt;LifetimeServices.LeaseTime = TimeSpan.Zero;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;(4) 创建该跟踪处理类的实例，并注册跟踪服务：&lt;BR&gt;TrackingServices.RegisterTrackingHandler(new MyTracking());&lt;/P&gt;&lt;br /&gt;&lt;P&gt;(5) 编组两个远程对象：&lt;BR&gt;ServerAS.AppService1 service1 = new ServerAS1.AppService1();&lt;BR&gt;ObjRef objRef1 = RemotingServices.Marshal((MarshalByRefObject)service1,"AppService1");&lt;/P&gt;&lt;br /&gt;&lt;P&gt;ServerAS.AppService2 service2 = new ServerAS1.AppService2();&lt;BR&gt;ObjRef objRef2 = RemotingServices.Marshal((MarshalByRefObject)service2,"AppService2");&lt;/P&gt;&lt;br /&gt;&lt;P&gt;(6) 使服务器端保持运行：&lt;BR&gt;Console.WriteLine("Remoting服务启动，按退出...");&amp;nbsp;&lt;BR&gt;Console.ReadLine();&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;3、客户端&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;通过Activator.GetObject()获得两个远程对象，并调用其方法PrintString。代码略。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;4、运行测试&lt;/FONT&gt;：&lt;/P&gt;&lt;br /&gt;&lt;P&gt;运行服务器端和客户端，由于监控程序将监视远程对象的编组进程，因此在运行开始，就会显示远程对象已经被Marshal：&lt;/P&gt;&lt;br /&gt;&lt;P align=center&gt;&lt;IMG height=271 src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/ar1.gif" width=668 border=0 mce_src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/ar1.gif"&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;然后再客户端调用这两个远程对象的PrintString方法，服务器端接受字符串：&lt;/P&gt;&lt;br /&gt;&lt;P align=center&gt;&lt;IMG height=303 src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/ar2.gif" width=668 border=0 mce_src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/ar2.gif"&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;一分钟后，远程对象一自动被Disconnect：&lt;/P&gt;&lt;br /&gt;&lt;P align=center&gt;&lt;IMG height=303 src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/ar3.gif" width=668 border=0 mce_src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/ar3.gif"&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;此时客户端如要调用远程对象一，会抛出RemotingException异常；&lt;/P&gt;&lt;br /&gt;&lt;P&gt;又一分钟后，远程对象二被Disconnect了：&lt;/P&gt;&lt;br /&gt;&lt;P&gt;align="center"&amp;gt;&lt;IMG height=303 src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/ar4.gif" width=668 border=0 mce_src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/ar4.gif"&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;用户还可以根据这个代码测试RenewOnCallTime的时间是否正确。也即是说，在对象还未被Disconnect时，调用对象，则从调用对象的这一刻起，其生命周期不再是原来设定的初始有效时间值（InitialLeaseTime），而是租用更新时间值（RenewOnCallTime）。另外，如果这两个远程对象没有重写InitializeLifetimeService方法，则生命周期应为租用管理器所设定的值，为永久有效（设置为0）。那么这两个对象不会被自动Disconnect，除非我们显式指定关闭它的连接。当然，如果我们显式关闭连接，跟踪程序仍然会监视到它的变化，然后显示出来。&lt;BR&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;FONT color=#a52a2a&gt;&lt;STRONG&gt;五、结论&lt;/STRONG&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;通过我们的测试，其实结论已经很明显了。通过Marshal编组的对象要受到租用的生命周期所控制。注意对象被Disconnect，并不是指这个对象被GC回收，而是指这个对象保存在通道的相关代理信息被断开了，而对象本身仍然在服务器端存在。&lt;BR&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;所以我们通过Remoting提供服务，应根据实际情况指定远程对象的生命周期，如果不指定，则为Remoting默认的设定。要让所有的远程对象永久有效，可以通过配置文件或租用管理器将初始有效时间设为0。&lt;/P&gt;&lt;/div&gt;&lt;br /&gt;  &lt;p class="postfoot"&gt;&lt;br /&gt;   posted on 2004-08-05 16:44 &lt;a href='http://wayfarer.cnblogs.com/'&gt;Bruce Zhang&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-6894455295300355606?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/6894455295300355606/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=6894455295300355606&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6894455295300355606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6894455295300355606'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/04/microsoft-net-remotingmarshaldisconnect.html' title='Microsoft .Net Remoting系列专题之二：Marshal、Disconnect与生命周期以及跟踪服务（Bruce Zhang&apos;s Blog）'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-8175774265208666265</id><published>2007-04-29T10:28:00.000+08:00</published><updated>2007-05-10T09:57:17.572+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Remoting'/><title type='text'>Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇（Bruce Zhang's Blog）</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;&lt;a id="viewpost1_TitleUrl" href="http://www.cnblogs.com/wayfarer/archive/2004/07/30/28723.html"&gt;Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇 &lt;/a&gt;&lt;br /&gt;&lt;div class="postText"&gt;&lt;P&gt;&lt;FONT face=楷体_GB2312&gt;我写的.Net Remoting系列专题：&lt;/FONT&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;A id=viewpost1_TitleUrl href="/wayfarer/archive/2004/08/05/30437.html"&gt;&lt;FONT color=#000080&gt;Microsoft .Net Remoting系列专题之二：Marshal、Disconnect与生命周期以及跟踪服务&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;A id=viewpost1_TitleUrl href="/wayfarer/articles/75213.html"&gt;&lt;FONT color=#000080&gt;Microsoft .Net Remoting系列专题之三：Remoting事件处理全接触&lt;/FONT&gt;&lt;/A&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;Microsoft .Net Remoting系列专题之一&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;一、Remoting基础&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;什么是Remoting，简而言之，我们可以将其看作是一种分布式处理方式。从微软的产品角度来看，可以说Remoting就是DCOM的一种升级，它改善了很多功能，并极好的融合到.Net平台下。Microsoft® .NET Remoting 提供了一种允许对象通过应用程序域与另一对象进行交互的框架。这也正是我们使用Remoting的原因。为什么呢？在Windows操作系统中，是将应用程序分离为单独的进程。这个进程形成了应用程序代码和数据周围的一道边界。如果不采用进程间通信（RPC）机制，则在一个进程中执行的代码就不能访问另一进程。这是一种操作系统对应用程序的保护机制。然而在某些情况下，我们需要跨过应用程序域，与另外的应用程序域进行通信，即穿越边界。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;在Remoting中是通过通道（channel）来实现两个应用程序域之间对象的通信的。如图所示：&lt;/P&gt;&lt;br /&gt;&lt;P align=center&gt;&lt;IMG height=341 src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/Remoting1.jpg" width=650 border=0 mce_src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/Remoting1.jpg"&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;首先，客户端通过Remoting，访问通道以获得服务端对象，再通过代理解析为客户端对象。这就提供一种可能性，即以服务的方式来发布服务器对象。远程对象代码可以运行在服务器上（如服务器激活的对象和客户端激活的对象），然后客户端再通过Remoting连接服务器，获得该服务对象并通过序列化在客户端运行。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;在Remoting中，对于要传递的对象，设计者除了需要了解通道的类型和端口号之外，无需再了解数据包的格式。但必须注意的是，客户端在获取服务器端对象时，并不是获得实际的服务端对象，而是获得它的引用。这既保证了客户端和服务器端有关对象的松散耦合，同时也优化了通信的性能。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;1、Remoting的两种通道&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;Remoting的通道主要有两种：Tcp和Http。在.Net中，System.Runtime.Remoting.Channel中定义了IChannel接口。IChannel接口包括了TcpChannel通道类型和Http通道类型。它们分别对应Remoting通道的这两种类型。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;TcpChannel类型放在名字空间System.Runtime.Remoting.Channel.Tcp中。Tcp通道提供了基于Socket的传输工具，使用Tcp协议来跨越Remoting边界传输序列化的消息流。TcpChannel类型默认使用二进制格式序列化消息对象，因此它具有更高的传输性能。HttpChannel类型放在名字空间System.Runtime.Remoting.Channel.Http中。它提供了一种使用Http协议，使其能在Internet上穿越防火墙传输序列化消息流。默认情况下，HttpChannel类型使用Soap格式序列化消息对象，因此它具有更好的互操作性。通常在局域网内，我们更多地使用TcpChannel；如果要穿越防火墙，则使用HttpChannel。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;2、远程对象的激活方式&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;在访问远程类型的一个对象实例之前，必须通过一个名为Activation的进程创建它并进行初始化。这种客户端通过通道来创建远程对象，称为对象的激活。在Remoting中，远程对象的激活分为两大类：服务器端激活和客户端激活。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;(1) 服务器端激活，又叫做WellKnow方式，很多又翻译为知名对象。为什么称为知名对象激活模式呢？是因为服务器应用程序在激活对象实例之前会在一个众所周知的统一资源标识符(URI)上来发布这个类型。然后该服务器进程会为此类型配置一个WellKnown对象，并根据指定的端口或地址来发布对象。.Net Remoting把服务器端激活又分为SingleTon模式和SingleCall模式两种。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;SingleTon模式：此为有状态模式。如果设置为SingleTon激活方式，则Remoting将为所有客户端建立同一个对象实例。当对象处于活动状态时，SingleTon实例会处理所有后来的客户端访问请求，而不管它们是同一个客户端，还是其他客户端。SingleTon实例将在方法调用中一直维持其状态。举例来说，如果一个远程对象有一个累加方法（i=0；++i），被多个客户端（例如两个）调用。如果设置为SingleTon方式，则第一个客户获得值为1，第二个客户获得值为2，因为他们获得的对象实例是相同的。如果熟悉Asp.Net的状态管理，我们可以认为它是一种Application状态。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;SingleCall模式：SingleCall是一种无状态模式。一旦设置为SingleCall模式，则当客户端调用远程对象的方法时，Remoting会为每一个客户端建立一个远程对象实例，至于对象实例的销毁则是由GC自动管理的。同上一个例子而言，则访问远程对象的两个客户获得的都是1。我们仍然可以借鉴Asp.Net的状态管理，认为它是一种Session状态。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;(2) 客户端激活。与WellKnown模式不同，Remoting在激活每个对象实例的时候，会给每个客户端激活的类型指派一个URI。客户端激活模式一旦获得客户端的请求，将为每一个客户端都建立一个实例引用。SingleCall模式和客户端激活模式是有区别的：首先，对象实例创建的时间不一样。客户端激活方式是客户一旦发出调用的请求，就实例化；而SingleCall则是要等到调用对象方法时再创建。其次，SingleCall模式激活的对象是无状态的，对象生命期的管理是由GC管理的，而客户端激活的对象则有状态，其生命周期可自定义。其三，两种激活模式在服务器端和客户端实现的方法不一样。尤其是在客户端，SingleCall模式是由GetObject()来激活，它调用对象默认的构造函数。而客户端激活模式，则通过CreateInstance()来激活，它可以传递参数，所以可以调用自定义的构造函数来创建实例。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;二、远程对象的定义&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;前面讲到，客户端在获取服务器端对象时，并不是获得实际的服务端对象，而是获得它的引用。因此在Remoting中，对于远程对象有一些必须的定义规范要遵循。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;由于Remoting传递的对象是以引用的方式，因此所传递的远程对象类必须继承MarshalByRefObject。MSDN对MarshalByRefObject的说明是：MarshalByRefObject 是那些通过使用代理交换消息来跨越应用程序域边界进行通信的对象的基类。不是从 MarshalByRefObject 继承的对象会以隐式方式按值封送。当远程应用程序引用一个按值封送的对象时，将跨越远程处理边界传递该对象的副本。因为您希望使用代理方法而不是副本方法进行通信，因此需要继承MarshallByRefObject。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;以下是一个远程对象类的定义：&lt;BR&gt;public class ServerObject:MarshalByRefObject&lt;BR&gt;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Person GetPersonInfo(string name,string sex,int age)&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;&amp;nbsp;&amp;nbsp; Person person = new Person();&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; person.Name = name;&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; person.Sex = sex;&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; person.Age = age;&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; return person;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;}&lt;/P&gt;&lt;br /&gt;&lt;P&gt;这个类只实现了最简单的方法，就是设置一个人的基本信息，并返回一个Person类对象。注意这里返回的Person类。由于这里所传递的Person则是以传值的方式来完成的，而Remoting要求必须是引用的对象，所以必须将Person类序列化。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;因此，在Remoting中的远程对象中，如果还要调用或传递某个对象，例如类，或者结构，则该类或结构则必须实现串行化Attribute[SerializableAttribute]：&lt;BR&gt;[Serializable]&lt;BR&gt;&amp;nbsp;public class Person&lt;BR&gt;&amp;nbsp;{&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Person()&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;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private string name;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private string sex;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; private int age;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Name&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;&amp;nbsp;&amp;nbsp; get&amp;nbsp;&amp;nbsp;&amp;nbsp; {return name;}&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; set&amp;nbsp;&amp;nbsp;&amp;nbsp; {name = value;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public string Sex&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;&amp;nbsp;&amp;nbsp; get {return sex;}&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; set {sex = value;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public int Age&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;&amp;nbsp;&amp;nbsp; get {return age;}&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; set {age = value;}&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;&amp;nbsp;&amp;nbsp;}&lt;BR&gt;将该远程对象以类库的方式编译成Dll。这个Dll将分别放在服务器端和客户端，以添加引用。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;在Remoting中能够传递的远程对象可以是各种类型，包括复杂的DataSet对象，只要它能够被序列化。远程对象也可以包含事件，但服务器端对于事件的处理比较特殊，我将在本系列之三中介绍。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;三、服务器端&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;根据第一部分所述，根据激活模式的不同，通道类型的不同服务器端的实现方式也有所不同。大体上说，服务器端应分为三步：&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;1、注册通道&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;要跨越应用程序域进行通信，必须实现通道。如前所述，Remoting提供了IChannel接口，分别包含TcpChannel和HttpChannel两种类型的通道。这两种类型除了性能和序列化数据的格式不同外，实现的方式完全一致，因此下面我们就以TcpChannel为例。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;注册TcpChannel，首先要在项目中添加引用“System.Runtime.Remoting”，然后using名字空间：System.Runtime.Remoting.Channel.Tcp。代码如下：&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; TcpChannel channel = new TcpChannel(8080);&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; ChannelServices.RegisterChannel(channel);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;在实例化通道对象时，将端口号作为参数传递。然后再调用静态方法RegisterChannel()来注册该通道对象即可。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;2、注册远程对象&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;注册了通道后，要能激活远程对象，必须在通道中注册该对象。根据激活模式的不同，注册对象的方法也不同。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;(1) SingleTon模式&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;对于WellKnown对象，可以通过静态方法RemotingConfiguration.RegisterWellKnownServiceType()来实现：RemotingConfiguration.RegisterWellKnownServiceType(&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; typeof(ServerRemoteObject.ServerObject),&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; "ServiceMessage",WellKnownObjectMode.SingleTon);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;(2)SingleCall模式&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;注册对象的方法基本上和SingleTon模式相同，只需要将枚举参数WellKnownObjectMode改为SingleCall就可以了。RemotingConfiguration.RegisterWellKnownServiceType(&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; typeof(ServerRemoteObject.ServerObject),&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; "ServiceMessage",WellKnownObjectMode.SingleCall);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;(3)客户端激活模式&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;对于客户端激活模式，使用的方法又有不同，但区别不大，看了代码就一目了然。&lt;BR&gt;RemotingConfiguration.ApplicationName = "ServiceMessage";&lt;BR&gt;RemotingConfiguration.RegisterActivatedServiceType(&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; typeof(ServerRemoteObject.ServerObject));&lt;/P&gt;&lt;br /&gt;&lt;P&gt;为什么要在注册对象方法前设置ApplicationName属性呢？其实这个属性就是该对象的URI。对于WellKnown模式，URI是放在RegisterWellKnownServiceType()方法的参数中，当然也可以拿出来专门对ApplicationName属性赋值。而RegisterActivatedServiceType()方法的重载中，没有ApplicationName的参数，所以必须分开。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;3、注销通道&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;如果要关闭Remoting的服务，则需要注销通道，也可以关闭对通道的监听。在Remoting中当我们注册通道的时候，就自动开启了通道的监听。而如果关闭了对通道的监听，则该通道就无法接受客户端的请求，但通道仍然存在，如果你想再一次注册该通道，会抛出异常。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#008000&gt;//获得当前已注册的通道；&lt;BR&gt;&lt;/FONT&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IChannel[] channels = ChannelServices.RegisteredChannels;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;FONT color=#008000&gt;//关闭指定名为MyTcp的通道；&lt;/FONT&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; foreach (IChannel eachChannel in channels)&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; {&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; if (eachChannel.ChannelName == "MyTcp")&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; {&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;&amp;nbsp;&amp;nbsp;&amp;nbsp; TcpChannel tcpChannel = (TcpChannel)eachChannel;&lt;/P&gt;&lt;br /&gt;&lt;P&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#008000&gt; //关闭监听；&lt;/FONT&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; tcpChannel.StopListening(null);&lt;/P&gt;&lt;br /&gt;&lt;P&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;FONT color=#008000&gt; //注销通道；&lt;/FONT&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;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ChannelServices.UnregisterChannel(tcpChannel);&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; }&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; }&lt;BR&gt;代码中，RegisterdChannel属性获得的是当前已注册的通道。在Remoting中，是允许同时注册多个通道的，这一点会在后面说明。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;四、客户端&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;客户端主要做两件事，一是注册通道。这一点从图一就可以看出，Remoting中服务器端和客户端都必须通过通道来传递消息，以获得远程对象。第二步则是获得该远程对象。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;1、注册通道：&lt;/STRONG&gt;&lt;BR&gt;TcpChannel channel = new TcpChannel();&lt;BR&gt;ChannelServices.RegisterChannel(channel);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;注意在客户端实例化通道时，是调用的默认构造函数，即没有传递端口号。事实上，这个端口号是缺一不可的，只不过它的指定被放在后面作为了Uri的一部分。&lt;BR&gt;&lt;STRONG&gt;&lt;BR&gt;2、获得远程对象。&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;与服务器端相同，不同的激活模式决定了客户端的实现方式也将不同。不过这个区别仅仅是WellKnown激活模式和客户端激活模式之间的区别，而对于SingleTon和SingleCall模式，客户端的实现完全相同。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;(1) WellKnown激活模式&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;要获得服务器端的知名远程对象，可通过Activator进程的GetObject()方法来获得：&lt;BR&gt;ServerRemoteObject.ServerObject serverObj = (ServerRemoteObject.ServerObject)Activator.GetObject(&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; typeof(ServerRemoteObject.ServerObject), "tcp://localhost:8080/ServiceMessage");&lt;/P&gt;&lt;br /&gt;&lt;P&gt;首先以WellKnown模式激活，客户端获得对象的方法是使用GetObject（）。其中参数第一个是远程对象的类型。第二个参数就是服务器端的uri。如果是http通道，自然是用&lt;A href="http://localhost:8080/ServiceMessage" mce_href="http://localhost:8080/ServiceMessage"&gt;http://localhost:8080/ServiceMessage&lt;/A&gt;了。因为我是用本地机，所以这里是localhost，你可以用具体的服务器IP地址来代替它。端口必须和服务器端的端口一致。后面则是服务器定义的远程对象服务名，即ApplicationName属性的内容。&lt;BR&gt;&lt;STRONG&gt;&lt;BR&gt;(2) 客户端激活模式&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;如前所述，WellKnown模式在客户端创建对象时，只能调用默认的构造函数，上面的代码就说明了这一点，因为GetObject()方法不能传递构造函数的参数。而客户端激活模式则可以通过自定义的构造函数来创建远程对象。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;客户端激活模式有两种方法：&lt;BR&gt;1) 调用RemotingConfiguration的静态方法RegisterActivatedClientType()。这个方法返回值为Void，它只是将远程对象注册在客户端而已。具体的实例化还需要调用对象类的构造函数。&lt;BR&gt;&amp;nbsp;RemotingConfiguration.RegisterActivatedClientType(&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;&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; typeof(ServerRemoteObject.ServerObject),&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; "tcp://localhost:8080/ServiceMessage");&lt;BR&gt;&amp;nbsp;ServerRemoteObject.ServerObject serverObj = new ServerRemoteObject.ServerObject();&lt;/P&gt;&lt;br /&gt;&lt;P&gt;2) 调用进程Activator的CreateInstance()方法。这个方法将创建方法参数指定类型的类对象。它与前面的GetObject()不同的是，它要在客户端调用构造函数，而GetObject()只是获得对象，而创建实例是在服务器端完成的。CreateInstance()方法有很多个重载，我着重说一下其中常用的两个。&lt;BR&gt;a、&amp;nbsp;public static object CreateInstance(Type type, object[] args, object[] activationAttributes);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;参数说明：&lt;BR&gt;type：要创建的对象的类型。&lt;BR&gt;args ：与要调用构造函数的参数数量、顺序和类型匹配的参数数组。如果 args 为空数组或空引用（Visual Basic 中为 Nothing），则调用不带任何参数的构造函数（默认构造函数）。&lt;BR&gt;activationAttributes ：包含一个或多个可以参与激活的属性的数组。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;这里的参数args是一个object[]数组类型。它可以传递要创建对象的构造函数中的参数。从这里其实可以得到一个结论：WellKnown激活模式所传递的远程对象类，只能使用默认的构造函数；而Activated模式则可以用户自定义构造函数。activationAttributes参数在这个方法中通常用来传递服务器的url。&lt;BR&gt;假设我们的远程对象类ServerObject有个构造函数：&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; ServerObject(string pName,string pSex,int pAge)&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; {&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; name = pName;&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; sex = pSex;&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; age = pAge;&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; }&lt;/P&gt;&lt;br /&gt;&lt;P&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; object[] attrs = {new UrlAttribute("tcp://localhost:8080/ServiceMessage")};&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; object[] objs = new object[3];&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; objs[0] = "wayfarer";&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; objs[1] = "male";&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; objs[2] = 28;&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; ServerRemoteObject.ServerObject = Activator.CreateInstance(&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; typeof(ServerRemoteObject.ServerObject),objs,attrs);&lt;BR&gt;可以看到，objs[]数组传递的就是构造函数的参数。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;b、public static ObjectHandle CreateInstance(string assemblyName, string typeName, object[] activationAttribute);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;参数说明：&lt;BR&gt;assemblyName ：将在其中查找名为 typeName 的类型的程序集的名称。如果 assemblyName 为空引用（Visual Basic 中为 Nothing），则搜索正在执行的程序集。&lt;BR&gt;typeName：首选类型的名称。&lt;BR&gt;activationAttributes ：包含一个或多个可以参与激活的属性的数组。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;参数说明一目了然。注意这个方法返回值为ObjectHandle类型，因此代码与前不同：&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; object[] attrs = {new UrlAttribute("tcp://localhost:8080/EchoMessage")};&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; ObjectHandle handle = Activator.CreateInstance("ServerRemoteObject",&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;&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;&amp;nbsp;&amp;nbsp; "ServerRemoteObject.ServerObject",attrs);&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; ServerRemoteObject.ServerObject obj = (ServerRemoteObject.ServerObject)handle.Unwrap();&lt;/P&gt;&lt;br /&gt;&lt;P&gt;这个方法实际上是调用的默认构造函数。ObjectHandle.Unwrap()方法是返回被包装的对象。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;说明：要使用UrlAttribute，还需要在命名空间中添加：using System.Runtime.Remoting.Activation;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;五、Remoting基础的补充&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;通过上面的描述，基本上已经完成了一个最简单的Remoting程序。这是一个标准的创建Remoting程序的方法，但在实际开发过程中，我们遇到的情况也许千奇百怪，如果只掌握一种所谓的“标准”，就妄想可以“一招鲜、吃遍天”，是不可能的。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;1、注册多个通道&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;在Remoting中，允许同时创建多个通道，即根据不同的端口创建不同的通道。但是，Remoting要求通道的名字必须不同，因为它要用来作为通道的唯一标识符。虽然IChannel有ChannelName属性，但这个属性是只读的。因此前面所述的创建通道的方法无法实现同时注册多个通道的要求。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;这个时候，我们必须用到System.Collection中的IDictionary接口：&lt;/P&gt;&lt;br /&gt;&lt;P&gt;注册Tcp通道：&lt;BR&gt;IDictionary tcpProp = new Hashtable();&lt;BR&gt;tcpProp["name"] = "tcp9090";&lt;BR&gt;tcpProp["port"] = 9090;&lt;BR&gt;IChannel channel = new TcpChannel(tcpProp,&lt;BR&gt;&amp;nbsp;new BinaryClientFormatterSinkProvider(),&lt;BR&gt;&amp;nbsp;new BinaryServerFormatterSinkProvider());&lt;BR&gt;ChannelServices.RegisterChannel(channel);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;注册Http通道：&lt;BR&gt;IDictionary httpProp = new Hashtable();&lt;BR&gt;httpProp["name"] = "http8080";&lt;BR&gt;httpProp["port"] = 8080;&lt;BR&gt;IChannel channel = new HttpChannel(httpProp,&lt;BR&gt;&amp;nbsp;new SoapClientFormatterSinkProvider(),&lt;BR&gt;&amp;nbsp;new SoapServerFormatterSinkProvider());&lt;BR&gt;ChannelServices.RegisterChannel(channel);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;在name属性中，定义不同的通道名称就可以了。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;2、远程对象元数据相关性&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;由于服务器端和客户端都要用到远程对象，通常的方式是生成两份完全相同的对象Dll，分别添加引用。不过为了代码的安全性，且降低客户端对远程对象元数据的相关性，我们有必要对这种方式进行改动。即在服务器端实现远程对象，而在客户端则删除这些实现的元数据。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;由于激活模式的不同，在客户端创建对象的方法也不同，所以要分离元数据的相关性，也应分为两种情况。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;(1) WellKnown激活模式：&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;通过接口来实现。在服务器端，提供接口和具体类的实现，而在客户端仅提供接口：&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public interface IServerObject&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; Person GetPersonInfo(string name,string sex,int age);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;public class ServerObject:MarshalByRefObject,IServerObject&lt;BR&gt;{ ......}&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;&lt;BR&gt;&lt;STRONG&gt;(2) 客户端激活模式：&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;如前所述，对于客户端激活模式，不管是使用静态方法，还是使用CreateInstance()方法，都必须在客户端调用构造函数实例化对象。所以，在客户端我们提供的远程对象，就不能只提供接口，而没有类的实现。实际上，要做到与远程对象元数据的分离，可以由两种方法供选择：&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;a、利用WellKnown激活模式模拟客户端激活模式：&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;方法是利用设计模式中的“抽象工厂”，下面的类图表描述了总体解决方案：&lt;/P&gt;&lt;br /&gt;&lt;P align=center&gt;&lt;IMG height=278 src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/remoting2.gif" width=370 border=0 mce_src="http://www.cnblogs.com/images/cnblogs_com/wayfarer/remoting2.gif"&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;我们在服务器端的远程对象中加上抽象工厂的接口和实现类：&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public interface IServerObject&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; Person GetPersonInfo(string name,string sex,int age);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public interface IServerObjFactory&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; IServerObject CreateInstance();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class ServerObject:MarshalByRefObject,IServerObject&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; public Person GetPersonInfo(string name,string sex,int age)&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;&amp;nbsp;&amp;nbsp; Person person = new Person();&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; person.Name = name;&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; person.Sex = sex;&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; person.Age = age;&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; return person;&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;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class ServerObjFactory:MarshalByRefObject,IServerObjFactory&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; public IServerObject CreateInstance()&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;&amp;nbsp;&amp;nbsp; return new ServerObject();&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; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;然后再客户端的远程对象中只提供工厂接口和原来的对象接口：&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public interface IServerObject&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; Person GetPersonInfo(string name,string sex,int age);&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public interface IServerObjFactory&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; IServerObject CreateInstance();&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;BR&gt;我们用WellKnown激活模式注册远程对象，在服务器端：&lt;BR&gt;&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; RemotingConfiguration.RegisterWellKnownServiceType(&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; typeof(ServerRemoteObject.ServerObjFactory),&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; "ServiceMessage",WellKnownObjectMode.SingleCall);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;注意这里注册的不是ServerObject类对象，而是ServerObjFactory类对象。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;客户端：&lt;BR&gt;ServerRemoteObject.IServerObjFactory serverFactory =&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;&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; (ServerRemoteObject.IServerObjFactory)&amp;nbsp;Activator.GetObject(&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; typeof(ServerRemoteObject.IServerObjFactory),&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; "tcp://localhost:8080/ServiceMessage");&lt;/P&gt;&lt;br /&gt;&lt;P&gt;ServerRemoteObject.IServerObject serverObj = serverFactory.CreateInstance();&lt;/P&gt;&lt;br /&gt;&lt;P&gt;为什么说这是一种客户端激活模式的模拟呢？从激活的方法来看，我们是使用了SingleCall模式来激活对象，但此时激活的并非我们要传递的远程对象，而是工厂对象。如果客户端要创建远程对象，还应该通过工厂对象的CreateInstance()方法来获得。而这个方法正是在客户端调用的。因此它的实现方式就等同于客户端激活模式。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;b、利用替代类来取代远程对象的元数据&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;实际上，我们可以用一个trick，来欺骗Remoting。这里所说的替代类就是这个trick了。既然是提供服务，Remoting传递的远程对象其实现的细节当然是放在服务器端。而要在客户端放对象的副本，不过是因为客户端必须调用构造函数，而采取的无奈之举。既然具体的实现是在服务器端，又为了能在客户端实例化，那么在客户端就实现这些好了。至于实现的细节，就不用管了。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;如果远程对象有方法，服务器端则提供方法实现，而客户端就提供这个方法就OK了，至于里面的实现，你可以是抛出一个异常，或者return 一个null值；如果方法返回void，那么里面可以是空。关键是这个客户端类对象要有这个方法。这个方法的实现，其实和方法的声明差不多，所以我说是一个trick。方法如是，构造函数也如此。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;还是用代码来说明这种“阴谋”，更直观：&lt;/P&gt;&lt;br /&gt;&lt;P&gt;服务器端：&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class ServerObject:MarshalByRefObject&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; public ServerObject()&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;&amp;nbsp;&amp;nbsp;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Person GetPersonInfo(string name,string sex,int age)&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;&amp;nbsp;&amp;nbsp; Person person = new Person();&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; person.Name = name;&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; person.Sex = sex;&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; person.Age = age;&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; return person;&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;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;客户端：&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public class ServerObject:MarshalByRefObject&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; public ServerObj()&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;&amp;nbsp;&amp;nbsp; throw new System.NotImplementedException();&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; public Person GetPersonInfo(string name,string sex,int age)&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;&amp;nbsp;&amp;nbsp; throw new System.NotImplementedException();&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;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/P&gt;&lt;br /&gt;&lt;P&gt;比较客户端和服务器端，客户端的方法GetPersonInfo()，没有具体的实现细节，只是抛出了一个异常。或者直接写上语句return null，照样OK。我们称客户端的这个类为远程对象的替代类。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;3、利用配置文件实现&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;前面所述的方法，于服务器uri、端口、以及激活模式的设置是用代码来完成的。其实我们也可以用配置文件来设置。这样做有个好处，因为这个配置文件是Xml文档。如果需要改变端口或其他，我们就不需要修改程序，并重新编译，而是只需要改变这个配置文件即可。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;(1) 服务器端的配置文件：&lt;BR&gt;&amp;amp;lt;configuration&amp;amp;gt;&lt;BR&gt;&amp;nbsp; &amp;amp;lt;system.runtime.remoting&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;lt;application name="ServerRemoting"&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;lt;service&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;lt;wellknown mode="Singleton" type="ServerRemoteObject.ServerObject" objectUri="ServiceMessage"/&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;lt;/service&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;lt;channels&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;lt;channel ref="tcp" port="8080"/&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;lt;/channels&amp;amp;gt;&lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;amp;lt;/application&amp;amp;gt;&lt;BR&gt;&amp;nbsp; &amp;amp;lt;/system.runtime.remoting&amp;amp;gt;&lt;BR&gt;&amp;amp;lt;/configuration&amp;amp;gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;如果是客户端激活模式，则把wellknown改为activated，同时删除mode属性。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;把该配置文件放到服务器程序的应用程序文件夹中，命名为ServerRemoting.config。那么前面的服务器端程序直接用这条语句即可：&lt;BR&gt;RemotingConfiguration.Configure("ServerRemoting.config");&lt;/P&gt;&lt;br /&gt;&lt;P&gt;(2) 客户端配置文件&lt;/P&gt;&lt;br /&gt;&lt;P&gt;如果是客户端激活模式，修改和上面一样。调用也是使用RemotingConfiguration.Configure()方法来调用存储在客户端的配置文件。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;配置文件还可以放在machine.config中。如果客户端程序是web应用程序，则可以放在web.config中。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;4、启动/关闭指定远程对象&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;Remoting中没有提供类似UnregisterWellKnownServiceType()的方法，也即是说，一旦通过注册了远程对象，如果没有关闭通道的话，该对象就一直存在于通道中。只要客户端激活该对象，就会创建对象实例。如果Remoting传送的只有一个远程对象，这不存在问题，关闭通道就可以了。如果传送多个远程对象呢？要关闭指定的远程对象应该怎么做？关闭之后又需要启动又该如何？&lt;/P&gt;&lt;br /&gt;&lt;P&gt;我们注意到在Remoting中提供了Marshal()和Disconnect()方法，答案就在这里。Marshal()方法是将MarshalByRefObject类对象转化为ObjRef类对象，这个对象是存储生成代理以与远程对象通讯所需的所有相关信息。这样就可以将该实例序列化以便在应用程序域之间以及通过网络进行传输，客户端就可以调用了。而Disconnect()方法则将具体的实例对象从通道中断开。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;方法如下：&lt;BR&gt;首先注册通道：&lt;BR&gt;TcpChannel channel = new TcpChannel(8080);&lt;BR&gt;ChannelServices.RegisterChannel(channel);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;接着启动服务：&lt;BR&gt;先在服务器端实例化远程对象。&lt;BR&gt;ServerObject obj = new ServerObject();&lt;/P&gt;&lt;br /&gt;&lt;P&gt;然后，注册该对象。注意这里不用RemotingConfiguration.RegisterWellKnownServiceType()，而是使用RemotingServices.Marshal()：&lt;/P&gt;&lt;br /&gt;&lt;P&gt;ObjRef objrefWellKnown = RemotingServices.Marshal(obj, "ServiceMessage");&lt;/P&gt;&lt;br /&gt;&lt;P&gt;如果要注销对象，则：&lt;BR&gt;RemotingServices.Disconnect(obj);&lt;/P&gt;&lt;br /&gt;&lt;P&gt;要注意，这里Disconnect的类对象必须是前面实例化的对象。正因为此，我们可以根据需要创建指定的远程对象，而关闭时，则Disconnect之前实例化的对象。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;至于客户端的调用，和前面WellKnown模式的方法相同，仍然是通过Activator.GetObject()来获得。但从实现代码来看，我们会注意到一个问题，由于服务器端是显式的实例化了远程对象，因此不管客户端有多少，是否相同，它们调用的都是同一个远程对象。因此我们将这个方法称为模拟的SingleTon模式。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;客户端激活模式&lt;/P&gt;&lt;br /&gt;&lt;P&gt;我们也可以通过Marshal()和Disconnect()来模拟客户端激活模式。首先我们来回顾“远程对象元数据相关性”一节，在这一节中，我说到采用设计模式的“抽象工厂”来创建对象实例，以此用SingleCall模式来模拟客户端激活模式。在仔细想想前面的模拟的SingleTon模式。是不是答案就将呼之欲出呢？&lt;/P&gt;&lt;br /&gt;&lt;P&gt;在“模拟的SingleTon”模式中，我们是将具体的远程对象实例进行Marshal，以此让客户端获得该对象的引用信息。那么我们换一种思路，当我们用抽象工厂提供接口，工厂类实现创建远程对象的方法。然后我们在服务器端创建工厂类实例。再将这个工厂类实例进行Marshal。而客户端获取对象时，不是获取具体的远程对象，而是获取具体的工厂类对象。然后再调用CreateInstance()方法来创建具体的远程对象实例。此时，对于多个客户端而言，调用的是同一个工厂类对象；然而远程对象是在各个客户端自己创建的，因此对于远程对象而言，则是由客户端激活，创建的是不同对象了。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;当我们要启动/关闭指定对象时，只需要用Disconnet()方法来注销工厂类对象就可以了。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;&lt;STRONG&gt;六、小结&lt;/STRONG&gt;&lt;/P&gt;&lt;br /&gt;&lt;P&gt;Microsoft.Net Remoting真可以说是博大精深。整个Remoting的内容不是我这一篇小文所能尽述的，更不是我这个Remoting的初学者所能掌握的。王国维在《人间词话》一书中写到：古今之成大事业大学问者，必经过三种境界。“昨夜西风凋碧树，独上高楼，望尽天涯路。”此第一境界也。“衣带渐宽终不悔，为伊消得人憔悴。”此第二境界也。“众里寻他千百度，蓦然回首，那人却在灯火阑珊处。”此第三境界也。如以此来形容我对Remoting的学习，还处于“独上高楼，望尽天涯路”的时候，真可以说还未曾登堂入室。&lt;/P&gt;&lt;br /&gt;&lt;P&gt;或许需得“衣带渐宽”，学得Remoting“终不悔”，方才可以“蓦然回首”吧。&lt;/P&gt;&lt;/div&gt;&lt;br /&gt;  &lt;p class="postfoot"&gt;&lt;br /&gt;   posted on 2004-07-30 20:44 &lt;a href='http://wayfarer.cnblogs.com/'&gt;Bruce Zhang&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-8175774265208666265?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/8175774265208666265/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=8175774265208666265&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/8175774265208666265'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/8175774265208666265'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/04/microsoft-net-remotingnet-remotingbruce.html' title='Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇（Bruce Zhang&apos;s Blog）'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-6845772069411722699</id><published>2007-04-26T13:55:00.000+08:00</published><updated>2007-09-04T10:26:26.655+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='英文时事'/><title type='text'>Preparing Your Kids for the World of Money (yahoo)</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;Posted on Friday, March 30, 2007, 12:00AM&lt;br /&gt;From an entirely personal, even selfish perspective, I dread the day my oldest child -- now 18 -- heads off to college.&lt;br /&gt;&lt;br /&gt;If you have teenagers preparing to leave the nest, you probably know how I feel. Naturally, I want him to find his path in the real world, the path to work and a life he enjoys; I want him to become independent. But I'll miss him, I'll worry about him, and I'll wonder if I've prepared him well enough for the challenges of adulthood.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Teaching Financial Literacy&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;One of those challenges has to do with money. My son, along with my two other children and every other kid out there, needs to know how to handle financial matters responsibly. And he needs a set of financial values -- a framework for staying grounded in an affluent society and an age of ever-increasing consumerism.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;These topics aren't taught in school, though I'm convinced they should be. And even though personal finance is very much in my blood, and my husband and I have been teaching our kids about money matters since they were quite young, I'm convinced we could have done more. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;But it's never too late to teach your kids about the challenges of money. What follows are some ideas for giving your children the values and the tools to make good financial decisions about budgeting, spending, how to use credit, and investing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Dollars and Sense&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;When my father was a boy, the lesson to be learned was "the value of a dollar." While that may seem a bit archaic in today's world -- even a metaphoric dollar hardly holds much value these days -- it's still a great concept.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If you want your child to succeed in building a responsible financial life, he or she needs to understand the value of money: The challenges of earning it and spending it prudently, and the challenges of saving it and investing it for the future.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;One of the best ways for young people to grasp the value of a dollar is to get a job. They'll learn the basic responsibilities of the working life, and the importance of showing up on time every day and doing their best. They'll also experience the rewards of getting paid. Getting a taste of the world of work at a young age can be immensely valuable -- a superb first step on the journey to financial independence.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The Wisdom of Budgeting&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Whether your kids work or not, they need to learn about spending wisely, and that requires some experience with a budget. Say your high school senior is heading off to college next fall, and you plan on giving her a fixed sum each month to cover everything but room and board.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now, while she's still at home, is a good time to get her accustomed to living on a budget. You could give her a monthly allowance with the provision that she can only come to you for extraordinary expenses.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Help her create a budget that reflects her actual spending patterns and needs (and your financial realities, of course). It only takes a time or two of running out of money on the 15th of the month to drive home the wisdom of budgeting. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Credit Pros and Cons&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;When I was a teenager, no one my age had a credit card. In fact, few adults had them. Today, credit cards are ubiquitous; they've become indispensable financial tools. Not surprisingly, credit card debt has emerged as a real issue for college-age kids and young adults, and for many, it has become a substantial problem. When freshmen arrive on campus, they receive countless credit card offers, and kids who aren't prepared to use credit wisely often fall into a debt spiral at a painfully early age. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Your children may already have credit cards, but do they fully understand the pros and cons of using them? Do they realize the potential liabilities when compound interest works against them? Do they know the consequences to their credit rating (and their wallet) of late payments?&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I believe that teens and college kids should have a credit card, which is useful in emergencies, offers some degree of consumer protection, and is essential for online purchases. But it should be viewed as a financial tool, not as an extra source of cash. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You can start them off with a credit card with a spending limit. Be sure to monitor their credit card statements to ensure that they're using the card responsibly. Teach them to pay off the balance every month before the finance charges start to mount up. These lessons are vital now, while your kids are still under your roof.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A Taxing Situation&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Obviously, most high school and college kids are not going to pay substantial taxes, unless they have a great deal of investment income. Even if they have part-time jobs, the taxes are withheld automatically and the IRS paperwork is trivial.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;But learning about this particular inevitability of life is an important aspect of financial maturity. If they do work, help them fill out their tax forms. You might even want to consider sharing your own tax return with them to help them understand the substantial burden that taxation poses, as well as the mechanics of dealing with the IRS. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Investing in the Future&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;My own children were "early adopters" when it came to investing -- must be something in our family's DNA -- and I believe that every child should learn to save and every teen should learn the basics of investing through hands-on experience.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Teaching children to save is best started when they are very young -- six or seven, say. We encouraged our kids to save part of their allowance and gifts; we wanted saving to be second nature to them. When they reached their teenage years, we opened small custodial accounts and taught them about investing -- the potential to make their money grow significantly over time and the basics of stocks, bonds, and mutual funds.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now I often talk about the markets with my kids, and while their interest level waxes and wanes, they understand the basics of asset allocation and portfolio diversification. It's not just an issue of building wealth, either. I strongly believe that being involved in the markets engages people with the world. News takes on an added dimension when you've got something invested.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I may be overstating it, but I think investing helps teens become better, more informed citizens. And it certainly helps prepare them for another aspect of adult financial life. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The Value of Good Values&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Practical lessons about money and personal finance are obviously important, but financial responsibility also means having good values. Whether you're conscious of it not, you set a financial example for your kids every day in the way that you earn your living, spend and invest your money, and contribute to society through charity.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I'm not saying you need to change your financial habits; I'm saying you need to be aware of what your children learn from your habits. Believe me, they notice!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Ultimately, money is a resource that can be used well or badly; its real value is that it gives people choices in their lives. I know I want my son and his siblings to use their financial resources well. By teaching them the basics of personal finance now, while they're still at home, I'm trying to give them a foundation for making their way into the world.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I hope it makes the transition away from home a little easier -- for all of us.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-6845772069411722699?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/6845772069411722699/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=6845772069411722699&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6845772069411722699'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6845772069411722699'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/04/carrie-schwab-pomerantz-money-smart_2116.html' title='Preparing Your Kids for the World of Money (yahoo)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-3211378175591006930</id><published>2007-04-26T13:54:00.000+08:00</published><updated>2007-09-04T10:26:26.656+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='英文时事'/><title type='text'>Talking to Your Kids About Building Wealth (yahoo)</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;Posted on Tuesday, April 10, 2007, 12:00AM&lt;br /&gt;The primary task of parenting (besides loving, of course) is preparing your kids for independence. You teach them about life and give them the tools and the wisdom to make the most of their talents and their opportunities.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It's easy when they're young. "Look both ways before crossing the street." "Study hard." "Do your best." But as your kids get older, the issues get more challenging -- sex, drugs, and alcohol come to mind -- and the conversations get a lot more difficult.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Yet too few parents are having the one conversation that's vitally important to their children's future, and which -- when compared to talks about sex or drugs -- is surprisingly easy to begin: The one about building wealth.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It's Up to You&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I'm not talking about motivating your children to get rich. I'm talking about teaching them to take full advantage of one of the most powerful financial opportunities they'll encounter when they enter the working world: company-sponsored retirement plans like 401(k) and 403(b) plans, as well as their close relatives, IRAs.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The fact is that retirement is one of the biggest financial challenges your kids -- or any of us -- will have to face, and the next generation in particular will probably bear much of the burden themselves. But if you can convince your older children to invest early, regularly, and aggressively for their long-term future using tax-advantaged plans, you'll be giving them the chance to build the kind of wealth that could not only ensure a comfortable retirement but also give them an unprecedented degree of flexibility and freedom when they get older.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I realize that few teenagers or even young adults are very focused on retirement planning. But according to a recent survey conducted on the attitudes and expectations of teens toward money, they're positively eager to learn about investing for the future. In fact, 89 percent of the teens surveyed said they want to learn how to make their money grow.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Even more significant, just 20 percent of them said that "my parents/guardians have taught me how to invest money wisely" and only 11 percent said their parents have educated them about the importance of a 401(k) plan. They want to know more, and they're sure not going to learn it in school.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The Importance of Starting Early&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Obviously, there's a lot to teach when it comes to investing, from the various investment opportunities (stocks, bonds, mutual funds, exchange-traded funds) to ideas like asset allocation, diversification, and risk tolerance. But as a first step, I urge you to explain to your older kids that they possess an incredibly valuable and incredibly easy-to-use asset: time.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;A couple of examples should drive the point home. If your 18-year-old son could invest $1,000 a year in a traditional IRA (in which taxes on investment income are deferred until withdrawal), and earn an average annual return of 8 percent, his retirement account would be worth more than $328,000 (minus investment costs) when he turned 60. That's a pretty dramatic demonstration of the power of compounding growth.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;But the outcome is even better for tax-deferred accounts such as 401(k) plans, many of which offer a company "match." Let's say your 22-year-old is about to start her first job, which pays a salary of $30,000 a year. Her company offers a 401(k) plan that enables her to save, pretax, a percentage of her income (the federal ceiling for 2007 is $15,500) and will match up to 5 percent of her savings at the rate of 50 cents on the dollar. She's willing to divert 5 percent of her pretax pay into the 401(k).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The math works like this: 5 percent of $30,000 is $1,500 per year. Her employer match adds another $750 (50 percent of $1,500), so her annual investment totals $2,250. That's a good start made even better by the fact that it only "costs" her $1,225. (Her $1,500 contribution is made pretax; assuming a marginal rate of 15 percent, this reduces her tax burden for the year by $275. So the net cost to her of a $2,250 investment is just $1,225.)&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Let's also assume that she earns an average annual return of 8 percent. By the time she's 60, her savings would amount to more than $535,000 (minus investment costs) -- and that's assuming she never increases her contributions at all. If she leaves the company, she can take the money with her by rolling it into her new employer's plan or rolling it over into an IRA; it solely belongs to her.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I hope your children can put away even more of their earned income through these plans. But the point of these examples is crystal-clear: Even a relatively small amount has the potential to turn into a relatively big sum when invested over a long time period. And, in any case, chances are good that these early adopters can increase contributions as they get older and their salary goes up. Finally, some employers are considerably more generous with the company match. The potential of these investment vehicles is enormous.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Hands-on Experience&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You can use examples like these (or your own retirement plan experience) to start the discussion of building wealth over the long-term. Lesson No. 1 is the value of starting early. But you should also point out the tax benefits of company-sponsored retirement plans -- the chance to use pretax dollars and to defer taxes on investment income and capital gains.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And, of course, highlight the irresistible allure of the employer match. It's as close as they or anyone else will ever come to an immediate and often substantial return on their investment. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;But if you have the opportunity -- say your teenager has a job at the local mall or your college-age kid is working part-time -- urge him to open an IRA now and get his feet wet with some actual hands-on investing experience. Even if the amount invested is small (and even if you have to fund it yourself), it can be an incredibly valuable learning experience.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You can teach him about the importance of asset allocation and managing risk, and the potential rewards of seeing an investment grow. Not only will your child be starting early on a path toward building wealth, he'll be building a foundation of knowledge and a positive habit that will serve him well for a lifetime. After all, for many people, the 401(k) plan or its equivalent in a first job is their first opportunity to invest. Give your kids a head start. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Obviously, if you have grown kids working at jobs with employer-sponsored plans, you should definitely urge them to participate -- and help them take the first steps. Encourage them to get started, even if it's just a percent or two of their salary; most people don't even miss the contributions from their take-home pay once they get going.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;If they're really strapped for cash -- for instance, if they have huge student loans or work in a city with a particularly high cost of living -- you might even consider helping further. You could make up the difference from what their take-home pay would be without a 401(k) contribution so that their income stays the same while they're struggling with the beginnings of life on their own. An even better idea is to offer a match of your own to encourage them to save.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Investing More Aggressively&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In my hypothetical examples above, I used 8 percent as an average annual return. Part of your discussion about building wealth should focus on the importance of investing for growth. In other words, your kids can benefit from more aggressive exposure to the equity markets.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Some kids are surprisingly risk-averse when it comes to investing, but lower-risk/low-return investments won't give them the growth they need to outpace inflation and accumulate wealth. History shows that three or four decades is plenty of time to weather the normal ups and downs of the equity markets, so I believe you should urge your children to be as growth-oriented as they can, and a strong case can be made for people in their 20s to be substantially invested in a broadly diversified portfolio of U.S. and international stocks.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Of course, these decisions are personal; someone who is completely risk-averse, who would only be able to sleep at night by having the most conservative investments, will typically have to balance that preference by saving more, usually a lot more, to reach the same ultimate goal. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Again, It's Up to You&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The daughter of a friend of mine recently got her first "real" job, and she positively pounced on the opportunity to participate in her company-sponsored plan.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;When I asked what motivated her, she said that for as long as she could remember, her father had been selling her on the virtues and benefits of 401(k) plans. "It was like a mantra," she told me. "'Participate in your 401(k). Participate in your 401(k).' And it worked!"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It can be hard, sometimes, to imagine a 17-year-old or a 21-year-old actually listening to your advice. But when it comes to the challenge and the opportunity of building wealth, you can have a huge impact on your children's future. So sit them down and have the talk.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-3211378175591006930?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/3211378175591006930/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=3211378175591006930&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/3211378175591006930'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/3211378175591006930'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/04/carrie-schwab-pomerantz-money-smart_5301.html' title='Talking to Your Kids About Building Wealth (yahoo)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-115970968627198804</id><published>2007-04-26T13:53:00.000+08:00</published><updated>2007-09-04T10:26:26.657+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='英文时事'/><title type='text'>Raising Kids in a Consumerist World (yahoo)</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;Posted on Tuesday, April 17, 2007, 12:00AM&lt;br /&gt;The focus of my two previous Yahoo! Finance columns has been on the practical skills your child will need when he or she leaves home, and why you should encourage your older children to begin the process of building long-term savings.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;These are the kinds of things I've been trying to teach my own three children, and I believe they're vital for every kid. But there's another aspect of money that's less tangible but no less important: the virtue of values.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The Importance of Financial Values&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Call me old-fashioned, but lessons like the work ethic, financial responsibility, delayed gratification, and charity are, to my mind, just as vital as knowing about balancing your checkbook, portfolio diversification, and the ins and outs of 401(k) plans.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In an affluent society that seems more determined than ever to get more -- more wealth, more possessions, and more of the status that seems to come with those commodities -- values and virtues are more important than ever. Teaching your kids the ABCs of money management is crucial, but sharing your good money values can help make your hard work stick.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I probably don't need to convince you that values are important. Instead, my goal is to help you see how financial values can be taught, and that -- whether you're conscious of it or not -- you're passing your own values to your children through your words, behavior, and actions. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;The Example You Set&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I'm a big believer in giving kids direct, hands-on experience with money. Give them an allowance. Teach them to save. When they're old enough, encourage them to work part-time. All these lessons will help your kids learn to use, accumulate, and earn money.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;But remember this: They're also learning by example -- your example. They watch you spend money every single day. They hear how you talk about work and investing. The way you deal with personal finance may be the single biggest factor in shaping their attitudes toward money. This does not, of course, mean you have to change the way you spend, earn, save, or invest. But it does mean you need to be aware of the example you set. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;And as a parent, you're the ideal teacher for all kinds of lessons about finances and the values associated with them. It starts with the little things, like encouraging them to save part of their allowance. But every day is filled with opportunities to impart practical and philosophical lessons about money and values.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Hands-on Lessons&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Small children can help comparison shop in the supermarket, for example; they'll learn something useful and realize you're prudent with money. Older children can help when you pay the bills; again, they'll be learning something practical, and it'll be an opportunity to teach them about day-to-day financial responsibility. Sharing this can teach them the importance of paying off credit card bills monthly.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Tax time can be a chance to explore the financial realities of being a citizen in the community. When you make donations to the institutions you support, you can teach your children about the importance of charity and the idea of giving something back. But this shouldn't only be about monetary donations; invite them to participate in the next walk-a-thon or fundraiser, or to volunteer time for a favorite charity.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Perhaps you review your 401(k) statement or investment portfolio on a quarterly basis; that's another terrific teaching opportunity. Even watching television can be a source of knowledge and values: Kids are extremely susceptible to the desires and manipulations of advertising, and you can help them see through the hype and teach them that their happiness isn't dependent on the next big thing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Family-Finance Dynamics&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Kids like being part of the bigger family picture, but they'll also be learning a subtler lesson about financial values. They'll realize you take personal finance seriously, and that money is a resource to be used wisely and well.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;You might even pick out certain financial challenges that highlight specific lessons, such as making tradeoffs ("If we ate out a few times less per month, we could take a better vacation this summer" or "I'm going to buy a used car instead of a new one and put the extra money into your 529 college saving plans"). This will teach them about the pleasures of delayed gratification.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;In one sense, every financial transaction you make can be a lesson for your kids, at least the ones they witness or experience. If you're cavalier with money, they'll pick up on that; if you're prudent, they'll pick up on that, too.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Spheres of Influence&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Of course, you're not the only point on their moral compass. Your kids also get messages about values from a host of other sources: their peers, relatives, and other adults as well as the pervasive and very powerful media. You'll never be the sole influence on your kids, especially as they enter the teenage years and their drive toward independence begins to accelerate. &lt;br /&gt;&lt;br /&gt;Indeed, it would be foolish and counterproductive to try to shield them from values different from your own. A good part of growing up is learning how to make judgments about what's right. But of all the forces affecting your children's development, you're surely the most powerful one.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;When my son was 16, one of his friends got a new BMW as a birthday present. But when he told me about it, he said, "You know, Mom, I would be embarrassed if you bought me a car like that. It's just not right." His sense that such an extravagance was "just not right" was, I believe, based on an idea my husband and I have tried hard to instill in all of our children: that you have to work for what you want.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Every parent, no matter how much money they have, has to make choices about what to give their children and what to make them work or save for, and I realize that different people will come down on different points on that spectrum. But just because you can afford something doesn't necessarily mean you should buy it. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Who You Want Them to Be&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I'm certainly not suggesting that deprivation is a good thing, but teaching your children sense of accomplishment that accompanies working and saving for a substantial goal is clearly valuable -- and will serve them better in the long run.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I want my kids to plan for big purchases, to put their own resourcefulness, as savers and earners, to work. I'm more than willing to help them, but they have to show some initiative, put forth some effort, and demonstrate that they're willing to make short-term sacrifices for long-term goals. That, of course, is part of the essence of adult life and adult responsibility, and it's what I was taught as a young girl. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I believe the primary goal of parents is to foster independence, self-reliance, and confidence. Thinking about the values behind your financial decisions and articulating those values to your children will go a long way toward helping your kids mature into the kind of adults you want them to be.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-115970968627198804?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/115970968627198804/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=115970968627198804&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/115970968627198804'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/115970968627198804'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/04/carrie-schwab-pomerantz-money-smart_26.html' title='Raising Kids in a Consumerist World (yahoo)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-6396232829566573217</id><published>2007-04-26T13:47:00.001+08:00</published><updated>2007-09-04T10:26:26.658+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='英文时事'/><title type='text'>Kids' Money Expectations and the Gender Gap (yahoo)</title><content type='html'>&lt;div class="hd"&gt;Posted on Tuesday, April 24, 2007, 12:00AM&lt;/div&gt; &lt;div class="bd"&gt;&lt;span&gt;&lt;/span&gt; &lt;p&gt;Today&amp;#39;s teenagers, like generations before them, are looking forward to financial independence. But are they really prepared, intellectually, for the responsibilities of adult life? And how do boys and girls differ when it comes to thinking about their financial futures? &lt;br&gt;&lt;/p&gt; &lt;p&gt;These were some of the issues addressed by &lt;a href="http://www.aboutschwab.com/teensurvey2007.pdf" target="_blank"&gt;&lt;font color="#0f55c3"&gt;a recent Schwab survey on teens and money&lt;/font&gt;&lt;/a&gt;. The results were a bit surprising -- and instructive, for teens and, in particular, for their parents. &lt;br&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;&lt;font color="#000000"&gt;Mixed Findings&lt;/font&gt;&lt;/strong&gt;&lt;br&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;According to the teens polled, the next generation of American workers is very confident about its collective ability to earn a good living and to address the financial responsibilities of adulthood.&lt;br&gt;&lt;/p&gt; &lt;p&gt;On the one hand, that&amp;#39;s reassuring; it would&amp;#39;ve been disconcerting to discover pessimism on the part of teens about their income-earning potential as adults or their ability to deal with personal finance issues when they enter the world of careers and salaries, mortgages and debt, and investing and planning for retirement.  &lt;br&gt;&lt;/p&gt; &lt;p&gt;But on the other hand, the findings also suggest that this generation may be too confident, even naively so, about their future. Teens have what seems to me an overly rosy view of their future earning potential. And I was quite surprised by some of the differences between the sexes when they consider how they&amp;#39;re going to fare when they enter the workforce.  &lt;br&gt;&lt;/p&gt; &lt;p&gt;I&amp;#39;ve always felt that parents are the most vital source of information about personal finance for their children; after all, &amp;quot;Money Management 101&amp;quot; isn&amp;#39;t offered in very many schools&amp;#39; curricula. But the results of this year&amp;#39;s survey have convinced me of three things: first, that the gender gap is (sadly) alive and well; second, that too few parents are making the effort to educate their children about topics like budgeting, using credit wisely, and investing; and finally (here&amp;#39;s the good news), that kids are eager to learn -- and they want to learn from their parents. &lt;br&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;&lt;font color="#000000"&gt;Different Genders, Different Visions&lt;/font&gt;&lt;/strong&gt;&lt;br&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;My generation was brought up to believe that women could have any job we wanted, but we entered the workforce knowing that the gender &lt;span id="lw_1177473721_0" style="BACKGROUND: none transparent scroll repeat 0% 0%; CURSOR: hand; BORDER-BOTTOM: #0066cc 1px dashed; HEIGHT: 1em"&gt; gap -- the&lt;/span&gt; much-discussed disparity between the incomes of men and women -- was real. Nevertheless, I was shocked by how much of a gender gap exists in the expectations of today&amp;#39;s teenagers.&lt;br&gt;&lt;/p&gt; &lt;p&gt;For instance, about 81 percent of the boys surveyed believe they&amp;#39;ll earn &amp;quot;plenty of money&amp;quot; when they take their place in the workforce, but for girls, the figure is significantly lower at 65 percent. And when asked to estimate their annual salary as adults, boys, on average, believe they&amp;#39;ll make $173,000 a year while girls expect an average of $114,200. That&amp;#39;s a substantial difference. &lt;br&gt;&lt;/p&gt; &lt;p&gt;I confess that I&amp;#39;d hoped girls would see themselves on a more equitable footing with the boys, especially given the fact that girls appear to be the more industrious gender, according to the results of this survey. Forty-five percent of the girls report that they currently have a job or work occasionally compared to just 29 percent of the boys. &lt;br&gt;&lt;/p&gt; &lt;p&gt;This budding work ethic will certainly serve girls well when they enter the workforce as women. But why do girls have lower expectations than boys about their earning potential?&lt;br&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;&lt;font color="#000000"&gt;Managing Expectations&lt;/font&gt;&lt;/strong&gt;&lt;br&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;I don&amp;#39;t have a great answer, and I realize that the gender gap is a huge cultural and societal issue that can&amp;#39;t be solely addressed by parents. But I also believe that parents need to be aware of their kids&amp;#39; expectations, particularly since two-thirds of teens (both boys and girls) agree that men tend to earn more than women. &lt;br&gt;&lt;/p&gt; &lt;p&gt;And while this may be true today, we need to remind our girls that there&amp;#39;s no reason to automatically assume they&amp;#39;ll make less money than their male counterparts (for similar jobs, hours, and responsibilities, of course). It&amp;#39;s just possible that expecting less could translate into accepting less or being less assertive about negotiating salary requirements or raises. &lt;br&gt;&lt;/p&gt; &lt;p&gt;At the same time, there&amp;#39;s something a bit startling about these inflated income expectations; you should remind children of both sexes to be a bit more realistic about what they can hope to earn in their chosen careers. After all, according to the  U.S. &lt;span id="lw_1177473721_1" style="BACKGROUND: none transparent scroll repeat 0% 0%; CURSOR: hand; BORDER-BOTTOM: #0066cc 1px dashed; HEIGHT: 1em"&gt;Census Bureau&lt;/span&gt;, just 5 percent of the American population earns more than $100,000, and based on  &lt;span id="lw_1177473721_2" style="BACKGROUND: none transparent scroll repeat 0% 0%; CURSOR: hand; BORDER-BOTTOM: #0066cc 1px dashed; HEIGHT: 1em"&gt;Bureau of Labor Statistics&lt;/span&gt; data the average national wage is approximately $40,000. &lt;br&gt;&lt;/p&gt; &lt;p&gt;Your kids could be in for some unpleasant surprises when they enter the workforce. I&amp;#39;m not talking about crushing their dreams, but setting more reasonable expectations will help them understand the need for prudence and planning when it comes to their financial lives. &lt;br&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;&lt;font color="#000000"&gt;A Lack of Preparation&lt;/font&gt;&lt;/strong&gt;&lt;br&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;I can&amp;#39;t speculate about the sources of kids&amp;#39; optimism, but it extends beyond expectations about future income-earning potential. In fact, the survey found that nearly two-thirds (62 percent) of American teens believe they&amp;#39;re prepared to handle adult financial responsibilities after high school. &lt;br&gt;&lt;/p&gt; &lt;p&gt;Here again, the teens&amp;#39; confidence may be slightly misplaced. Most teens actually don&amp;#39;t have a firm grasp of the basics of personal and consumer finance, let alone more sophisticated topics. Just 41 percent consider themselves knowledgeable about budgeting. Only 34 percent know the mechanics of paying bills. And a mere 26 percent understand how credit card interest and fees work, which is particularly alarming given the prevalence of the  &lt;span id="lw_1177473721_3" style="BACKGROUND: none transparent scroll repeat 0% 0%; CURSOR: hand; BORDER-BOTTOM: #0066cc 1px dashed; HEIGHT: 1em"&gt;credit card&lt;/span&gt; as an important financial tool.&lt;br&gt;&lt;/p&gt; &lt;p&gt;As for slightly more advanced financial know-how, the level of knowledge is even scantier. Just 14 percent of the teens say they understand how income taxes work, and only 13 percent of them know what a 401(k) plan is. &lt;br&gt;&lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;&lt;strong&gt;&lt;font color="#000000"&gt;A Desire to Learn&lt;/font&gt;&lt;/strong&gt;&lt;br&gt;&lt;/font&gt;&lt;/p&gt; &lt;p&gt;The message to me is unmistakable: Today&amp;#39;s kids, boys and girls, don&amp;#39;t have a solid grounding in financial realities. They need to know more about personal and consumer finance. The good news is that they want to know more. &lt;br&gt;&lt;/p&gt; &lt;p&gt;Nearly 9 in 10 (89 percent), for example, say they want to learn how to make their money grow, and almost two-thirds (65 percent) believe that learning about money management is interesting. Further, more than half of them (60 percent) say that learning about money management is one of their top priorities. But they&amp;#39;re not getting these lessons from their parents: just 28 percent report that their parents or guardians are giving them actual experience with &amp;quot;budgeting, spending, and saving.&amp;quot;  &lt;br&gt;&lt;/p&gt; &lt;p&gt;The call to action couldn&amp;#39;t be more obvious: It&amp;#39;s up to you to educate your kids about money. Open savings accounts for them, and encourage them to save. Teach them about the need to pay off credit card bills monthly and the real dangers of  &lt;span id="lw_1177473721_4" style="BACKGROUND: none transparent scroll repeat 0% 0%; CURSOR: hand; BORDER-BOTTOM: #0066cc 1px dashed; HEIGHT: 1em"&gt;credit card&lt;/span&gt; overuse (credit cards are cash substitutes, not income extenders). Help them plan for future purchases -- as I like to call it, &amp;quot;the pleasures of delayed gratification.&amp;quot; Include them in your own financial chores, from the simple act of paying your bills to more sophisticated tasks like managing your 401(k) plan. Consider getting them involved in the financial markets, perhaps with small custodial accounts or by allowing them to &amp;quot;look over your shoulder&amp;quot; when you&amp;#39;re managing your money. &lt;br&gt;&lt;/p&gt; &lt;p&gt;And, of course, encourage them to ask questions. You&amp;#39;ll be giving them a solid financial foundation: a core of knowledge, confidence, and wisdom that will serve them well as they continue on their journey to independence. &lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8705367749555657878-6396232829566573217?l=beautyhill.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://beautyhill.blogspot.com/feeds/6396232829566573217/comments/default' title='帖子评论'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=8705367749555657878&amp;postID=6396232829566573217&amp;isPopup=true' title='0 条评论'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6396232829566573217'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8705367749555657878/posts/default/6396232829566573217'/><link rel='alternate' type='text/html' href='http://beautyhill.blogspot.com/2007/04/carrie-schwab-pomerantz-money-smart.html' title='Kids&apos; Money Expectations and the Gender Gap (yahoo)'/><author><name>陛下</name><uri>http://www.blogger.com/profile/12998460215329067947</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='31' height='32' src='http://4.bp.blogspot.com/_W5Nmtt573as/SN20BjkamNI/AAAAAAAAAcY/17d6sEOONzE/S220/r_%25e9%2597%25aa%25e9%2597%25aa%25e7%25ba%25a2%25e6%2598%259f.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8705367749555657878.post-3385775678086207213</id><published>2007-04-26T12:44:00.000+08:00</published><updated>2007-09-04T10:26:26.659+08:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='.Net/C#'/><category scheme='http://www.blogger.com/atom/ns#' term='.Net/Asp'/><title type='text'>各类搜索引擎（摘自《傲游论坛 » 傲游 2.0 系列 » 使用交流专区 - M2》）</title><content type='html'>&lt;em&gt;(任何引用请注明:转载于&lt;a href="http://beautyhill.blogspot.com"&gt;美人山下http://beautyhill.blogspot.com&lt;/a&gt;)&lt;/em&gt;&lt;br /&gt;百度搜索&
