﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-备注学院-文章分类-C#</title><link>http://www.blogjava.net/smildlzj/category/33212.html</link><description>LuLu</description><language>zh-cn</language><lastBuildDate>Mon, 16 Mar 2009 13:52:33 GMT</lastBuildDate><pubDate>Mon, 16 Mar 2009 13:52:33 GMT</pubDate><ttl>60</ttl><item><title>C#中将dll汇入exe，并加壳 </title><link>http://www.blogjava.net/smildlzj/articles/249903.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Mon, 05 Jan 2009 05:44:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/249903.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/249903.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/249903.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/249903.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/249903.html</trackback:ping><description><![CDATA[From:http://www.cnblogs.com/Daylight/archive/2008/10/01/1302890.html<br />
<br />
<p>这几天在做自己的一个小程序，因为使用了3层架构，运行目录下有很多dll文件，最终发布时，我打算将dll文件都合并到exe文件中去。微软发布的免费软件ILmerge可以完成这项工作，研究了一下，其用法如下：</p>
<p>1、合并file1.dll、file2.dll到destination.dll</p>
<p>ILmerge /ndebug /target:dll /out:C:\destination.dll /log C:\file1.dll C:\file2.dll </p>
<p>2、合并file1.dll、file2.dll以及myApp.exe到newApp.exe<br />
</p>
<p>ILmerge /ndebug /target:winexe /out:C:\newApp.exe /log C:\myapp.exe C:\file1.dll C:\file2.dll </p>
<p>注意：合并为exe时，myapp.exe必须写在file1.dll、file2.dll前面</p>
<p>完成之后，就得到了一个exe文件，如果想做一些邪恶的事情，可以将一些破解软件的dll合并到你的exe中去。前提是，所有的dll都是托管的，如果尝试合并C++写的dll，则会失败。有一个工具，叫做mergebin.exe，可以合并托管和非托管dll，用法我还没研究出来，似乎比较困难的样子。这个工具是ADO.NET 2.0 Data Provider for SQLite的作者写的，他发布的System.Data.SQLite.dll可以被dotNet程序引用，还可以直接被C/C++程序调用，这个dll就是托管和非托管混合的dll，果然是很牛的！mergebin.exe在其源码包里，有兴趣的朋友可以研究一下。这是其官方网站：http://sqlite.phxsoftware.com</p>
<p>继续邪恶的话题，如果你的exe里面合并有破解的dll，你可能不想让别人知道，或者你不想让别人反编译你的exe文件。混淆软件都收费，而且混淆之后方法还是看得见的，只不过名字毫无规则，没办法，用不了。还是加壳来的直接，我们得找一款很牛的加壳软件。给大家推荐个软件，叫做Sixxpack，专门加壳dotNet程序的，目前的最新版本为Sixxpack22，要求机器上装有.netframework2.0以上版本。Sixxpack除了加壳，还使用了压缩技术，最高压缩比达80%。Sixxpack是免费软件，官网是：http://www.reversers.net/</p>
<p>经Sixxpack加壳后，用Reflector打开exe文件，哈哈，看到的永远都只是一个actmp.dll的信息，其中包含4个7zip命名空间和1个Sixxpack命名空间，反编出来这些东西对也没啥用处。呵呵，原来是用7zip压缩的，难怪那么高的压缩比。</p>
<p>有一个问题是，用Sixxpack处理之后的程序集，版本信息是0.0.0.0，其他信息也不对。没关系，使用Resource Hacker修改一下就OK了！ Resource Hacker也是免费软件，官网是：http://angusj.com/resourcehacker/</p>
<p>我这个小项目为了美化界面，用了一些邪恶的东西，最终的exe文件5MB左右，用Sixxpack处理之后，体积降到了2MB以内，运行时几乎没有性能损失。最重要的，很难反编译，可以放心拿给别人用了。</p>
<img src ="http://www.blogjava.net/smildlzj/aggbug/249903.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2009-01-05 13:44 <a href="http://www.blogjava.net/smildlzj/articles/249903.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Java&amp;.Net虚拟机精简</title><link>http://www.blogjava.net/smildlzj/articles/247662.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Sun, 21 Dec 2008 14:39:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/247662.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/247662.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/247662.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/247662.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/247662.html</trackback:ping><description><![CDATA[From: http://blog.csdn.net/cping1982/archive/2008/08/21/2806598.aspx<br />
<a href="http://blog.csdn.net/cping1982/archive/2008/09/02/2865198.aspx">&nbsp;&nbsp;<strong> 精简JRE体积的小工具：http://blog.csdn.net/cping1982/archive/2008/09/02/2865198.aspx</strong></a><br />
<br />
&nbsp;&nbsp;<strong> <a href="http://code.google.com/p/greenvm/">项目地址：http://code.google.com/p/greenvm/</a></strong><br />
<br />
&nbsp;&nbsp; 关键字:JRE,精简,压缩,JVM,JAVA.NET,虚拟机,绿色软件,最小空间,脱框,压缩,GREEN,GREENJVM<br />
<br />
&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/cping1982/EntryImages/20080902/20080902_jvm_s_00" /> <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/cping1982/EntryImages/20080902/20080902_jvm_s_00.gif" /><br />
&nbsp;&nbsp; <br />
<font color="#ff6600">&nbsp;&nbsp; <strong>9月6日更新版本为 0.1.1.4</strong></font><br />
<br />
&nbsp;&nbsp;<strong> 变更：</strong><br />
&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp; 增加[SET_START_MAIN_CLASS_AUTO_LOAD]参数，当此项为真时，程序将设置主函数所在类开机自动启动。<br />
<br />
&nbsp;&nbsp;&nbsp; 增加初始化界面设置，参数如下：<br />
<div class="highlighter">
<ol class="highlighter-j">
    <li><span class="comment">//程序启动前使用初始界面(此项为false时,以下设定皆无效)</span>
    <li class="alt"><span>SET_START_INIT=</span><span class="keyword">true</span>
    <li><span class="comment">//使用的初始界面图片</span>
    <li class="alt"><span>SET_START_IMAGE=init.bmp</span>
    <li><span class="comment">//设置true时初始窗体将自动居中,同时top及left无效</span>
    <li class="alt"><span>SET_START_LOCATION_AUTO=</span><span class="keyword">true</span><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>
    <li><span class="comment">//&nbsp;设置初始窗体在桌面的X轴</span>
    <li class="alt"><span>SET_START_LOCATION_LEFT=</span><span class="number">100</span><span>&nbsp;</span>
    <li><span class="comment">//&nbsp;设置初始窗体在桌面的Y轴</span>
    <li class="alt"><span>SET_START_LOCATION_TOP=</span><span class="number">100</span>
    <li><span class="comment">//&nbsp;设定初始窗体显示时间</span>
    <li class="alt"><span>SET_START_TIME=</span><span class="number">1000</span></li>
</ol>
</div>
<br />
&nbsp;&nbsp; <br />
<br />
&nbsp;&nbsp; PS:本文中所有关于JRE部分皆指Sun JRE。<br />
<br />
&nbsp;&nbsp; 众所周知，Java能够运行于近乎所有的操作系统，包括Windows、 Mac或Linux等等。<br />
<br />
&nbsp;&nbsp; 对于任何组织或个人的Java应用而言，只要你的应用程序需要移植或多OS发布，那么将现有应用从一个系统移植到另一个操作系统将是件非常轻松的事情，因为Java使用了虚拟机机制，可以脱离OS的约束而独立解释并执行class。<br />
<br />
&nbsp;&nbsp; 但有利也有弊，对于很多程序而言，这也同时意味着你的用户必须获得JRE支持，也就是说他需要安装JVM。但我国的现实情况却是很多人别说让他自己下载安装JRE，你就是给他做好全[下一步]的安装程序，他恐怕也连&#8220;下一步&#8221;都搞不定&#8230;&#8230;||||<br />
<br />
&nbsp;&nbsp; 有鉴于此，我尝试提供一种解决方案，我将它命名为：GreenJVM，也就是绿色的JVM。<br />
<br />
&nbsp;&nbsp; GreenJVM是一个专为绿化Java应用而存在的小程序,以C++开发（昨晚上抽空写的小应用程序，代码原型以前在Blog发过：<a href="http://blog.csdn.net/cping1982/archive/2007/10/27/1847478.aspx">通过exe启动class</a> ）。它的执行文件体积很小仅仅370KB,本身也是一个基于JNI的Java应用.真正的核心文件只有2个,一是GreenJVM.exe(执行文件),一个vm.cfg(配置文件),如下图:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/cping1982/EntryImages/20080821/greenvm_bear1.gif" /><br />
<br />
&nbsp;&nbsp;&nbsp; 它的功能非常简单,仅是解压自带的JRE并取代java.exe文件直接调度jvm.dll罢了。但就是这样一个小程序，却可以很轻松的实现Java软件的绿色发布。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp; 以千里冰封兄的YOYOPlayer为例(冰封兄blog:http://www.blogjava.net/hadeslee/)，我们都知道这是一个非常之好的Java音乐播放器,在Java圈内已经小有名气。但遗憾的是,对比千千静听这类知名软件而言,了解它的人简直比华南虎还要稀有......虽然软件普及率低的原因多种多样,但对Java应用而言,究其根本还是JVM安装的关系。就像&#8220;妈是女人&#8221;的道理一样，Java程序的运行环境必须有与其开发版本兼容的JRE存在，否则无法运作。也就是这道门槛,不知把多少普通用户拦在了Java应用之外。<br />
<br />
&nbsp;&nbsp; 可能你会说这些是小事，的确，对我们这些Java程序员来讲当然不存在任何问题；但令人遗憾的是，对绝大多数普通用户，特别是并不成熟的中国数亿网民而言（我是指软件知识的平均值&#8230;&#8230;其实牛人也很多&#8230;&#8230;），安装JRE这几乎是件不可想象的艰巨任务;除非他们有必须使用不可的理由，否则需要下载第三方软件的程序，绝对是第一时间被pass掉的（一般人使用软件的准则就一条：简单就用，麻烦就不用）；无形中大大增加了Java软件普及的难度，明明是很好的程序，却只能在Java圈子里流传，不禁令人扼腕。<br />
<br />
&nbsp;&nbsp; 事实上，我们可以通过极简单的技术手段来突破这一限制，轻而易举将Java应用做成绿色软件，免除用户这些不必要犹豫，令他们放心大胆的使用Java程序。<br />
<br />
&nbsp;&nbsp; 这个过程仅仅需要三步：<br />
<br />
&nbsp;&nbsp; 1、压缩你的JRE：<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/cping1982/EntryImages/20080821/greenvm_02.gif" /><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 目前GreenJVM支持rar和zip两种方式的解压。<br />
<br />
&nbsp;&nbsp; 2、设置vm.cfg：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vm.cfg内容配置如下:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<div class="highlighter">
<ol class="highlighter-j">
    <li><span>[LOON]</span>
    <li class="alt"><span class="comment">/*虚拟机解压方式,0.1版仅提供RAR及ZIP两种,Windows平台下建议使用RAR(调用自带unrar.dll,故不要求本地</span>
    <li><span class="comment">存在WinRAR,使用ZIP则可以删除unrar.dll)*/</span>
    <li class="alt">SET_UNPACK_METHOD=rar
    <li><span class="comment">//虚拟机压缩包名称,要求配置在vm.cfg同路径下</span>
    <li class="alt"><span>SET_VM_NAME=jre.pack</span>
    <li><span class="comment">//检测本地jvm版本,低于期望值时使用自带jvm,否则以本地虚拟机优先运行</span>
    <li class="alt"><span>SET_START_REQUIRE_VERSION=</span><span class="number">1.6</span>
    <li><span class="comment">//期望加载的jar,多包以';'分隔</span>
    <li class="alt"><span>SET_START_JAR_PATH=fps_test.jar</span>
    <li><span class="comment">//期望执行的main类</span>
    <li class="alt"><span>SET_START_MAIN_CLASS=org/test/BallPanel</span>
    <li><span class="comment">//选填,尝试从指定环境变量获取jvm路径,存在则优先运行本地jvm</span>
    <li class="alt"><span class="comment">//SET_START_ENV=JAVA_HOME</span></li>
</ol>
</div>
&nbsp;&nbsp; 3、发布应用，此时只需一个文件夹，就可以完全容纳下整个Java应用了。<br />
<br />
&nbsp;&nbsp; 现在我们来看看一个基本完整JRE1.6压缩包(去掉了bin下的exe文件)与YOYOPlayer放在一起后的空间占用情况，如下图：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp; &nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/cping1982/EntryImages/20080821/yoyo_01.gif" /><br />
&nbsp;&nbsp;&nbsp; <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 对比百来MB的JRE而言，现在总体不过20MB的体积已经是小的太多。只需直接丢给用户这个文件夹，告诉用户一句&#8220;双击EXE文件执行&#8221;，就能如常运行此程序，而不必再解释或说明什么。&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 但饶是如此，20MB的音乐播放器，相较2MB左右的千千静听而言还是太大了，对很多普通用户来说依旧难以接受，他们不会去考虑Java特性，只会去想&#8220;千千2MB就能搞定的事，你怎么就要用20MB才行？肯定是水平不行，不用&#8230;&#8230;&#8221;，Java程序员们集体抱头哭~~~。为了避免这类情况的发生，这时就需要我们在jre的体积上做些文章了。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 就和人的大脑活动区域一样，相对于我们每个应用而言，JRE中也至少会有20MB以上（只多不少）是被浪费掉的终身不使用区域，而这些区域中的组件及类库的唯一作用就是贪婪的占用硬盘空间罢了~因此找出这些区域并缩减它，就能最大限度的减小程序体积。（虽然sun或其它jvm提供商大多都反对这样，但我们只是在实验罢了:)，况且我认为他们早晚也会开放jvm定制服务的。 ）<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以YOYOPlayer为例，实际上我们只需在JRE中保留其音频支持、AWT/SWing支持、及网络支持等部分就好，其余的部分大可删掉不要。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下例我做了一个精简的JRE压缩包，如下图:<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/cping1982/EntryImages/20080821/yoyo_02.gif" />&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 只用了不足8MB的空间,便足以完成YOYOPlayer的全部功能.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们把这个JRE和YOYOPlayer放在一起,全部加起来也不过9MB多一点,而YOYOPlayer依旧可以在无JRE系统中正常运行.效果如下图:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/cping1982/EntryImages/20080821/yoyo_03.gif" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当然,如果再继续删的话，占用空间肯定还会有一定的下降幅度，我认为至少能将JRE压缩到6MB以内;但现实意义不大，毕竟不是做嵌入式开发，为了1，2MB费那么大劲不值当的&#8230;&#8230;。事实上，对于绝大多数Java应用而言，压缩后至多9MB左右的空间占用便绰绰有余了,况且还有进一步精简的余地。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如下例,这是我以前在Blog发过的一个FPS测速程序,效果如下:<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/cping1982/EntryImages/20080821/greenvm_00.gif" /><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 现在我使用一个针对AWT使用而精简的JRE,在另一台无Java环境的电脑上测试,结果如下图:<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/cping1982/EntryImages/20080821/greenvm_01.gif" /><br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 可以看到,程序正常运行,而且FPS数有明显提高,并没有因为直接调用JVM而削弱了性能.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这个完全支持AWT组件的JRE和执行程序全打成一个rar文件也不过4MB左右（PS:由于最占空间的JRE已经压缩过，所以再压缩其实意义不大&#8230;&#8230;）,实际上与本地程序的大小已经相差无几了.<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 不过就算是4MB的JRE也不能说很小了,如果愿意深度精简的话，2MB的JRE运行敝人的loonframework-game（尚未发布）都已经绰绰有余。就运行库而言，对比rmxp（ruby语言的游戏开发玩具&#8230;&#8230;）还要小的多。<br />
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这些几MB的Java应用,放到U盘里随身携带绰绰有余，要用时在U盘里便可以直接运行(当然，由于api依赖的关系，除非我为其它平台重新制作启动文件,否则只支持提供win32 api的系统)，不用了就直接删文件，环保安全无污染，标准的绿色食品，不买也看看啊~&nbsp;&nbsp; <br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 再稍微正规点做个安装文件（绿色软件不能等同于无需安装的软件，毕竟安装只不过是个部署过程，和绿不绿色没有实质上关系。愚以为，只要不改变现有系统配置，不依赖本地系统组件的软件都可称为绿色软件；相反就算不用安装，一执行就注册到系统中一堆乱七八糟东西的软件同样不能说是绿色的。），那么程序的体积还将进一步减小。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以YOYOPlayer为例,最终提供给用户一个5MB甚至4MB左右的绿色应用是绝对可以做到的,对比5.2.1版占用2.85MB空间的千千静听来说,已经看不出两者间有太大区别,普通的音乐爱好者已经没有理由不下载看看了.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而一旦他们用了,就会慢慢发现Java应用的精妙之处,他会发现无论以后他用什么系统,这套软件他都将无法自拔的使用下去.<br />
<br />
<font color="#ff6600"><strong>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </strong></font><a href="http://download.csdn.net/source/581442"><br />
&nbsp;&nbsp;<strong> </strong></a><strong><a href="http://code.google.com/p/greenvm/">项目地址：http://code.google.com/p/greenvm/</a></strong><font color="#ff6600"><strong><a href="http://download.csdn.net/source/581442"></a><br />
<br />
————————————————————————————————————————————<br />
<br />
0.1.1版发布：<br />
<br />
</strong></font><strong><a style="font-size: 12pt" href="http://download.csdn.net/source/586635"><strong>&nbsp;</strong></a></strong><a style="font-size: 12pt" href="http://download.csdn.net/source/586635"><br />
&nbsp; <strong></strong></a><strong><a href="http://code.google.com/p/greenvm/">项目地址：http://code.google.com/p/greenvm/</a></strong><strong><br />
</strong><br />
&nbsp; 新增[SET_LOCAL_JRE_UPDATE]项，通过此项可以命令本地JRE自动更新。<br />
<br />
&nbsp; 一起发布的是一个Java仿雷电游戏（源码见包内），共设置有三关三个小BOSS。采用有GreenJVM发布，因此可以运行在未装载JRE的Windows系统之上。 (N久以前写的一个古董&#8230;&#8230;凑活看吧&#8230;&#8230;)。<br />
<br />
&nbsp; 准备写到1.0时再去Sourceforge申请项目&#8230;&#8230;现在Loonframework还没弄完呢&#8230;&#8230;<br />
<br />
<font color="#ff6600"><strong><br />
0.1.1.3版发布：<br />
</strong></font><a style="font-size: 12pt" href="http://download.csdn.net/source/586635"><br />
&nbsp; </a><strong><a href="http://code.google.com/p/greenvm/">项目地址：http://code.google.com/p/greenvm/</a></strong><strong><br />
</strong><br />
&nbsp;&nbsp; 新增7z格式压缩包解压支持，建议使用此格式进行虚拟机压缩。 <br />
<br />
_____________________________________________________________________________________________________________<br />
_____________________________________________________________________________________________________________<br />
<br />
<br />
<strong>GreenDotNet0.1.0</strong><br />
<br />
<strong>GreenDotNet</strong>是一个根据GreenJVM移植的应用,目标是实现.netframework虚拟机的绿色发布。<br />
<br />
GreenDotNet 0.1.1 简要说明<br />
<br />
1、本程序是一个非常简单的.Net程序免安装发布工具，可以满足绝大部分.Net framework2.0及以下环境开发之桌面应用的绿色发布及使用。<br />
<br />
2、本程序目前阶段不尝试虚拟.Net运行环境（一是难写，二是敝人极懒，三我是Java程序员，明白？^^&#8230;&#8230;），虚拟机初始化后将直接通过GreenDotNet.exe在Windows中布署最简.Net环境，故对程序运行效率无影响。<br />
<br />
3、虚拟机压缩包中仅删除了System.Web（如果要用编码之类的功能自己实现就好，不然这堆东西也5MB左右呢|||），保留了其余一切链接库(如操作数据库必须的System.Data等，不要就自己删吧~)，因此绝大多数操作皆可在此环境下正常使用。<br />
<br />
4、由于采用了真实的Windows环境进行布署，因此加密或混淆后的.Net程序依旧可以正常在此环境下运行。<br />
<br />
5、相较使用Salamander .NET Linker等收费工具（含使用飞信运行框架）而言，这只是一个简写的.Net布署方式，故而绝对不会存在版权或收费等问题。<br />
<br />
<br />
相关文件说明：<br />
<br />
GreenDotNet.exe : 启动文件，它将起到本地环境探针及布署.Net环境的作用。<br />
<br />
vm.cfg : 配置文件，决定GreenDotNet.exe对系统进行的相关操作。<br />
<br />
dotnet.pack（8MB） : 虚拟机压缩包，使用7z格式产生，目前仅提供.Net 2.0版本支持，不保证2.0以下或以上版本开发之应用在此环境能够正常运行。 <br />
<br />
<br />
vm.cfg配置如下:<br />
<div class="highlighter">
<ol class="highlighter-c">
    <li><span>[LOON]</span>
    <li class="alt"><span class="comment">//虚拟机解压方式,目前提供RAR、ZIP、7Z三种压缩方式的解压支持</span>
    <li><span>SET_UNPACK_METHOD=7z</span>
    <li class="alt"><span class="comment">//虚拟机压缩包名称,要求配置在vm.cfg同路径下</span>
    <li><span>SET_VM_NAME=DotNet.pack</span>
    <li class="alt"><span class="comment">//检测本地.net版本,低于期望值时使用自带.net,否则以本地虚拟机优先运行</span>
    <li><span>SET_START_REQUIRE_VERSION=1.1</span>
    <li class="alt"><span class="comment">//期望执行的exe文件,要求与vm.cfg同路径下</span>
    <li><span>SET_START_MAIN_EXE=ComicStars.exe</span>
    <li class="alt"><br />
    </li>
</ol>
</div>
<br />
<br />
<strong><a href="http://code.google.com/p/greenvm/">项目地址：http://code.google.com/p/greenvm/</a><br />
<br />
<br />
示例程序:</strong><br />
<br />
&nbsp;Zero漫天星辰漫画下载器是一个.Net的在线漫画检索及下载工具，采用.netframework1.1开发(使用.net纯粹是由于拖控件方便|||),作为GreenDotNet的示例程序一起发布.<br />
<br />
<img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/cping1982/EntryImages/20080902/20080902_dotnet_02.gif" /><br />
 <img src ="http://www.blogjava.net/smildlzj/aggbug/247662.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-12-21 22:39 <a href="http://www.blogjava.net/smildlzj/articles/247662.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#.Net: 实现支持断点续传多线程下载的 Http Web 客户端工具类</title><link>http://www.blogjava.net/smildlzj/articles/247435.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Sat, 20 Dec 2008 01:34:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/247435.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/247435.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/247435.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/247435.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/247435.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: From:http://blog.csdn.net/begtostudy/archive/2008/03/06/2155010.aspx/**//*&nbsp;.Net/C#:&nbsp;实现支持断点续传多线程下载的&nbsp;Http&nbsp;Web&nbsp;客户端工具类&nbsp;(C#&nbsp;DIY&nbsp;HttpWebClient)&nbsp;*&n...&nbsp;&nbsp;<a href='http://www.blogjava.net/smildlzj/articles/247435.html'>阅读全文</a><img src ="http://www.blogjava.net/smildlzj/aggbug/247435.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-12-20 09:34 <a href="http://www.blogjava.net/smildlzj/articles/247435.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Microsoft .Net Remoting系列专题之二：Marshal、Disconnect与生命周期以及跟踪服务</title><link>http://www.blogjava.net/smildlzj/articles/246885.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Wed, 17 Dec 2008 07:34:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/246885.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/246885.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/246885.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/246885.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/246885.html</trackback:ping><description><![CDATA[<p>From:http://www.cnblogs.com/wayfarer/archive/2004/08/05/30437.html<br />
<a id="viewpost1_TitleUrl" href="http://www.cnblogs.com/wayfarer/archive/2004/07/30/28723.html"><font color="#000080"><br />
Microsoft .Net Remoting系列专题之一:.Net Remoting基础篇</font></a><a id="viewpost1_TitleUrl" href="http://www.cnblogs.com/wayfarer/archive/2004/08/05/30437.html"></a></p>
<p><a id="viewpost1_TitleUrl" href="http://www.cnblogs.com/wayfarer/articles/75213.html"><font color="#000080">Microsoft .Net Remoting系列专题之三：Remoting事件处理全接触</font></a></p>
<p><font color="#a52a2a"><strong><font color="#000000">Microsoft .Net Remoting系列专题之二</font></strong>&nbsp;</font></p>
<p><font color="#a52a2a"><strong>一、远程对象的激活</strong></font></p>
<p>在Remoting中有三种激活方式，一般的实现是通过RemotingServices类的静态方法来完成。工作过程事实上是将该远程对象注册到通道中。由于Remoting没有提供与之对应的Unregister方法来注销远程对象，所以如果需要注册/注销指定对象，微软推荐使用Marshal（一般译为编组）和Disconnect配对使用。在《<a href="http://www.brucezhang.com/?p=70" rel="bookmark" mce_href="http://www.brucezhang.com/?p=70">Net Remoting基础篇</a>》中我已经谈到：Marshal()方法是将MarshalByRefObject类对象转化为ObjRef类对象，这个对象是存储生成代理以与远程对象通讯所需的所有相关信息。这样就可以将该实例序列化以便在应用程序域之间以及通过网络进行传输，客户端就可以调用了。而Disconnect()方法则将具体的实例对象从通道中断开。</p>
<p>根据上述说明，Marshal()方法对远程对象以引用方式进行编组（Marshal-by-Reference，MBR），并将对象的代理信息放到通道中。客户端可以通过Activator.GetObject()来获取。如果用户要注销该对象，则通过调用Disconnect()方法。那么这种方式对于编组的远程对象是否存在生命周期的管理呢？这就是本文所要描述的问题。</p>
<p><font color="#a52a2a"><strong>二、生命周期</strong></font></p>
<p>在CLR中，框架提供了GC（垃圾回收器）来管理内存中对象的生命周期。同样的，.Net Remoting使用了一种分布式垃圾回收，基于租用的形式来管理远程对象的生命周期。</p>
<p>早期的DCOM对于对象生命周期的管理是通过ping和引用计数来确定对象何时应当作为垃圾回收。然而ping引起的网络流量对分布式应用程序的性能是一种痛苦的负担，它大大地影响了分布式处理的整体性能。.Net Remoting在每个应用程序域中都引入一个租用管理器，为每个服务器端的SingleTon，或每个客户端激活的远程对象保存着对租用对象的引用。（说明：对于服务器端激活的SingleCall方式，由于它是无状态的，对于每个激活的远程对象，都由CLR的GC来自动回收，因此对于SingleCall模式激活的远程对象，不存在生命周期的管理。）</p>
<p><font color="#a52a2a">1、租用</font></p>
<p>租用是个封装了TimeSpan值的对象，用以管理远程对象的生存期。在.Net Remoting中提供了定义租用功能的ILease接口。当Remoting通过SingleTon模式或客户端激活模式来激活远程对象时，租用对象调用从System.MarshalByRefObject继承的InitializeLifetimeService方法，向对象请求租用。</p>
<p>ILease接口定义了有关生命周期的属性，均为TimeSpan值。如下：<br />
InitialLeaseTime：初始化有效时间，默认值为300秒，如果为0，表示永不过期；<br />
RenewOnCallTime：调用远程对象一个方法时的租用更新时间，默认值为120秒；<br />
SponsorshipTimeout：超时值，通知Sponsor（发起人）租用过期后，Remoting会等待的时间，默认值为120秒；<br />
CurrentLeaseTime：当前租用时间，首次获得租用时，为InitializeLeaseTime的值。</p>
<p>Remoting的远程对象因为继承了MarshalByRefObject，因此默认继承了InitializeLifetimeService方法，那么租用的相关属性为默认值。如果要改变这些设置，可以在远程对象中重写该方法。例如：<br />
&nbsp;public override object InitializeLifetimeService()<br />
&nbsp;{<br />
&nbsp;&nbsp;ILease lease = (ILease)base.InitializeLifetimeService();<br />
&nbsp;&nbsp;if (lease.CurrentState == LeaseState.Initial)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;lease.InitialLeaseTime = TimeSpan.FromMinutes(1);<br />
&nbsp;&nbsp;&nbsp;lease.RenewOnCallTime = TimeSpan.FromSeconds(20);<br />
&nbsp;&nbsp;}<br />
&nbsp;&nbsp;return lease;&nbsp;&nbsp;<br />
&nbsp;}</p>
<p>也可以忽略该方法，将对象的租用周期改变为无限：<br />
&nbsp;public override object InitializeLifetimeService()<br />
&nbsp;{<br />
&nbsp;&nbsp;return null;<br />
&nbsp;}</p>
<p><font color="#a52a2a">2、租用管理器</font></p>
<p>如果是前面所说的租用主要是应用在每个具体的远程对象上，那么租用管理器是服务器端专门用来管理远程对象生命周期的管理器，它维持着一个System.Hashtable成员，将租用映射为System.DateTime实例表示每个租用何时应过期。Remoting采用轮询的方式以一定的时间唤醒租用管理器，检查每个租用是否过期。默认为每10秒钟唤醒一次。轮询的间隔可以配置，如将轮询间隔设置为5分钟：LifetimeService.LeaseManagerPollTime = System.TimeSpan.FromMinutes(5);</p>
<p>我们还可以在租用管理器中设置远程对象租用的属性，如改变远程对象的初始有效时间为永久有效：<br />
LifetimeServices.LeaseTime = TimeSpan.Zero;</p>
<p>我们也可以通过配置文件来设置生命周期，如：<br />
&amp;lt;configuration&amp;gt;<br />
&nbsp;&amp;lt;system.runtime.remoting&amp;gt;<br />
&nbsp;&nbsp;&amp;lt;application name = "SimpleServer"&amp;gt;<br />
&nbsp;&nbsp;&nbsp;&amp;lt;lifetime leaseTime = "0" sponsorshipTimeOut = "1M"&nbsp;renewOnCallTime = "1M" pollTime = "30S"/&amp;gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&amp;lt;/application&amp;gt;<br />
&nbsp;&amp;lt;/system.runtime.remoting&amp;gt;<br />
&amp;lt;/configuration&amp;gt;</p>
<p>注：配置文件中的pollTime即为上面所说的租用管理器的轮询间隔时间LeaseManagerPollTime。</p>
<p>租用管理器对于生命周期的设置是针对服务器上所有的远程对象。当我们通过配置文件或租用管理器设置租用的属性时，所有远程对象的生命周期都遵循该设置，除非我们对于指定的远程对象通过重写InitializeLifetimeService方法，改变了相关配置。也就是说，远程对象的租用配置优先级高于服务器端配置。</p>
<p><font color="#a52a2a">3、发起人（Sponsor）</font></p>
<p>发起人是针对客户端而言的。远程对象就是发起人要租用的对象，发起人可以与服务器端签订租约，约定租用时间。一旦到期后，发起人还可以续租，就像现实生活中租方的契约，房东、租房者之间的关系一样。</p>
<p>在.Net Framework中的System.Runtime.Remoting.Lifetime命名空间中定义了ClientSponsor类，该类继承了System.MarshalByRefObject，并实现了ISponsor接口。ClientSponsor类的属性和方法，可以参考MSDN。</p>
<p>客户端要使用发起人机制，必须创建ClientSponsor类的一个实例。然后调用相关方法如Register()或Renewal()方法来注册远程对象或延长生命周期。如：<br />
RemotingObject obj = new RemotingObject();<br />
ClientSponsor sponsor = new ClientSponsor();<br />
sponsor.RenewalTime = TimeSpan.FromMinutes(2);<br />
sponsor.Register(obj);</p>
<p>续租时间也可以在ClientSponsor的构造函数中直接设置，如：<br />
ClientSponsor sponsor = new ClientSponsor(TimeSpan.FromMinutes(2));<br />
sponsor.Register(obj);</p>
<p>我们也可以自己编写Sponsor来管理发起人机制，这个类必须继承ClientSponsor并实现ISponsor接口。</p>
<p><font color="#a52a2a"><strong>三、跟踪服务</strong></font></p>
<p>如前所述，我们要判断通过Marshal编组远程对象是否存在生命周期的管理。在Remoting中，可以通过跟踪服务程序来监视MBR对象的编组进程。</p>
<p>我们可以创建一个简单的跟踪处理程序，该程序实现接口ITrackingHandler。接口ITrackingHandler定义了3个方法，MarshalObject、UnmarshalObject和DisconnectedObject。当远程对象被编组、解组和断开连接时，就会调用相应的方法。下面是该跟踪处理类的代码：public class MyTracking:ITrackingHandler<br />
{<br />
&nbsp;public MyTracking()<br />
&nbsp;{<br />
&nbsp;&nbsp;//<br />
&nbsp;&nbsp;// TODO: 在此处添加构造函数逻辑<br />
&nbsp;&nbsp;//<br />
&nbsp;}</p>
<p>&nbsp;public void MarshaledObject(object obj,ObjRef or)<br />
&nbsp;{<br />
&nbsp;&nbsp;Console.WriteLine();<br />
&nbsp;&nbsp;Console.WriteLine("对象" + obj.Tostring() + " is marshaled at " + DateTime.Now.ToShortTimeString());<br />
&nbsp;}</p>
<p>&nbsp;public void UnmarshaledObject(object obj,ObjRef or)<br />
&nbsp;{<br />
&nbsp;&nbsp;Console.WriteLine();<br />
&nbsp;&nbsp;Console.WriteLine("对象" + obj.Tostring() + " is unmarshaled at " + DateTime.Now.ToShortTimeString());<br />
&nbsp;}</p>
<p>&nbsp;&nbsp;public void DisconnectedObject(object obj)<br />
&nbsp;{<br />
&nbsp;&nbsp;Console.WriteLine(obj.ToString() + " is disconnected at " + DateTime.Now.ToShortTimeString());<br />
&nbsp;}<br />
}</p>
<p>然后再服务器端创建该跟踪处理类的实例，并注册跟踪服务：<br />
TrackingServices.RegisterTrackingHandler(new MyTracking());</p>
<p><font color="#a52a2a"><strong>四、测试</strong></font></p>
<p><font color="#a52a2a">1、建立两个远程对象，并重写InitializeLifetimeService方法：</font></p>
<p>对象一：AppService1<br />
初始生命周期：1分钟</p>
<p>&nbsp;public class AppService1:MarshalByRefObject<br />
&nbsp;{<br />
&nbsp;&nbsp;public void PrintString(string contents)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;Console.WriteLine(contents);&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;public override object InitializeLifetimeService()<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;ILease lease = (ILease)base.InitializeLifetimeService();<br />
&nbsp;&nbsp;&nbsp;if (lease.CurrentState == LeaseState.Initial)<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;lease.InitialLeaseTime = TimeSpan.FromMinutes(1);<br />
&nbsp;&nbsp;&nbsp;&nbsp;lease.RenewOnCallTime = TimeSpan.FromSeconds(20);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;return lease;<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p>对象二：AppService2<br />
初始生命周期：3分钟</p>
<p>&nbsp;public class AppService2:MarshalByRefObject<br />
&nbsp;{<br />
&nbsp;&nbsp;public void PrintString(string contents)<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;Console.WriteLine(contents);&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}</p>
<p>&nbsp;&nbsp;public override object InitializeLifetimeService()<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;ILease lease = (ILease)base.InitializeLifetimeService();<br />
&nbsp;&nbsp;&nbsp;if (lease.CurrentState == LeaseState.Initial)<br />
&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;lease.InitialLeaseTime = TimeSpan.FromMinutes(3);<br />
&nbsp;&nbsp;&nbsp;&nbsp;lease.RenewOnCallTime = TimeSpan.FromSeconds(40);<br />
&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;return lease;<br />
&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;}<br />
&nbsp;}</p>
<p>为简便起见，两个对象的方法都一样。</p>
<p><font color="#a52a2a">2、服务器端</font></p>
<p>(1) 首先建立如上的监控处理类；</p>
<p>(2) 注册通道：<br />
TcpChannel channel = new TcpChannel(8080);<br />
ChannelServices.RegisterChannel(channel);</p>
<p>(3) 设置租用管理器的初始租用时间为无限：<br />
LifetimeServices.LeaseTime = TimeSpan.Zero;</p>
<p>(4) 创建该跟踪处理类的实例，并注册跟踪服务：<br />
TrackingServices.RegisterTrackingHandler(new MyTracking());</p>
<p>(5) 编组两个远程对象：<br />
ServerAS.AppService1 service1 = new ServerAS1.AppService1();<br />
ObjRef objRef1 = RemotingServices.Marshal((MarshalByRefObject)service1,"AppService1");</p>
<p>ServerAS.AppService2 service2 = new ServerAS1.AppService2();<br />
ObjRef objRef2 = RemotingServices.Marshal((MarshalByRefObject)service2,"AppService2");</p>
<p>(6) 使服务器端保持运行：<br />
Console.WriteLine("Remoting服务启动，按退出...");&nbsp;<br />
Console.ReadLine();</p>
<p><font color="#a52a2a">3、客户端</font></p>
<p>通过Activator.GetObject()获得两个远程对象，并调用其方法PrintString。代码略。</p>
<p><font color="#a52a2a">4、运行测试</font>：</p>
<p>运行服务器端和客户端，由于监控程序将监视远程对象的编组进程，因此在运行开始，就会显示远程对象已经被Marshal：</p>
<p align="center"><img height="271" src="http://images.cnblogs.com/cnblogs_com/wayfarer/ar1.gif" width="668" border="0" mce_src="http://images.cnblogs.com/cnblogs_com/wayfarer/ar1.gif"  alt="" /></p>
<p>然后再客户端调用这两个远程对象的PrintString方法，服务器端接受字符串：</p>
<p align="center"><img height="303" src="http://images.cnblogs.com/cnblogs_com/wayfarer/ar2.gif" width="668" border="0" mce_src="http://images.cnblogs.com/cnblogs_com/wayfarer/ar2.gif"  alt="" /></p>
<p>一分钟后，远程对象一自动被Disconnect：</p>
<p align="center"><img height="303" src="http://images.cnblogs.com/cnblogs_com/wayfarer/ar3.gif" width="668" border="0" mce_src="http://images.cnblogs.com/cnblogs_com/wayfarer/ar3.gif"  alt="" /></p>
<p>此时客户端如要调用远程对象一，会抛出RemotingException异常；</p>
<p>又一分钟后，远程对象二被Disconnect了：</p>
<p>align="center"&gt;<img height="303" src="http://images.cnblogs.com/cnblogs_com/wayfarer/ar4.gif" width="668" border="0" mce_src="http://images.cnblogs.com/cnblogs_com/wayfarer/ar4.gif"  alt="" /></p>
<p>用户还可以根据这个代码测试RenewOnCallTime的时间是否正确。也即是说，在对象还未被Disconnect时，调用对象，则从调用对象的这一刻起，其生命周期不再是原来设定的初始有效时间值（InitialLeaseTime），而是租用更新时间值（RenewOnCallTime）。另外，如果这两个远程对象没有重写InitializeLifetimeService方法，则生命周期应为租用管理器所设定的值，为永久有效（设置为0）。那么这两个对象不会被自动Disconnect，除非我们显式指定关闭它的连接。当然，如果我们显式关闭连接，跟踪程序仍然会监视到它的变化，然后显示出来。<br />
</p>
<p><font color="#a52a2a"><strong>五、结论</strong><br />
</font></p>
<p>通过我们的测试，其实结论已经很明显了。通过Marshal编组的对象要受到租用的生命周期所控制。注意对象被Disconnect，并不是指这个对象被GC回收，而是指这个对象保存在通道的相关代理信息被断开了，而对象本身仍然在服务器端存在。<br />
</p>
<p>所以我们通过Remoting提供服务，应根据实际情况指定远程对象的生命周期，如果不指定，则为Remoting默认的设定。要让所有的远程对象永久有效，可以通过配置文件或租用管理器将初始有效时间设为0。</p>
<img src ="http://www.blogjava.net/smildlzj/aggbug/246885.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-12-17 15:34 <a href="http://www.blogjava.net/smildlzj/articles/246885.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 使用飞信VMDotNet使C#程序脱离.NET FRAMEWORK也能运行的一些心得(转)</title><link>http://www.blogjava.net/smildlzj/articles/245614.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Thu, 11 Dec 2008 01:42:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/245614.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/245614.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/245614.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/245614.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/245614.html</trackback:ping><description><![CDATA[FROM:http://blog.csdn.net/my22xo/archive/2008/03/14/2183811.aspx<br />
<br />
之前看到有用别的方法来实现的，但我还是选择了现在比较流行的软件飞信中带的VMDotNet，也就是所谓的.NET FRAMEWORK虚拟机吧。相信有很多人也已经看过相关文章了，但是对于新手我还是再提一下，在你的飞信的安装目录下有一个VMDotNet文件夹，这 个就是我们要用的最主要的内容了，先把它COPY出来吧！
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 下面先来简单说明一下VMDotNet文件夹吧，在这个文件夹之下有一个v2.0.50727文件夹，很明显是.NET FRAMEWORK的版本号啦，进入这个文件夹，里面有一个FetionVM.exe的可执行文件（飞信的图标），这个便是我们要用到的虚拟机文件了。其 它文件我们不用考虑。这个程序可以带入一个参数，即要在此虚拟环境下运行的程序的路径。形如FetionVM.exe C:\1.exe，也可以使用相对路径：FetionVM.exe 1.exe，当然这样要求两者在同一目录下啦。这里顺便要再说一下VMDotNet.log这个文件，这里记录了在调用FetionVM.exe时的错误 信息，主要是路径不对，找不到对应的程序。在了解了这个文件夹之后，我们可以动手开始做啦！</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 把这个文件夹复制到你的项目的DEBUG目录下，我的已有项目名为PicProcessor，生成的可执行文件为，当然你也可以视情况而定了，如果放别的地方就应该注意一下路径就好了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在这里我们需要再新建一个C#应用程序项目，我把它命名为PicStart，把FORM1.CS删除，或者直接新建一个控制台程序，在Program.cs中写入以下代码：</p>
<p>using System; using System.Collections.Generic; using System.Windows.Forms;</p>
<p>namespace PicStart { &nbsp;&nbsp;&nbsp; static class Program &nbsp;&nbsp;&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;summary&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// 应用程序的主入口点。 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /// &lt;/summary&gt; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [STAThread] &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static void Main() &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //下面是调用外部程序的代码 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Diagnostics.ProcessStartInfo Info = new System.Diagnostics.ProcessStartInfo(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Info.FileName = "VMDotNet\\v2.0.50727\\FetionVM.exe"; //这里是你要调用到的外部程序 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Info.Arguments = "PicProcessor.exe"; //调用外部程序的参数，这里是图片处理项目的可执行文件，注意不是现在这个项目的可执行文件 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Diagnostics.Process Proc;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //启动外部程序 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Proc = System.Diagnostics.Process.Start(Info); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (System.ComponentModel.Win32Exception e) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; { &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("系统找不到指定的程序文件。\r{0}", e); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } &nbsp;&nbsp;&nbsp; } }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在做完了这个项目以后我们生成此项目，这个时候我们就可以开始制作程序的安装文件了。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以前我们利用VS2005做安装包的时候可以选择把.NET FRAMEWORK集成进去，但现在我们不用了，请大家把相应的选项全部去掉，还不会使用VS2005安装和部署功能的朋友请到此网址去看一下。<a href="http://www.vs2005.com/Setup/205/1/default.aspx">http://www.vs2005.com/Setup/205/1/default.aspx</a></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们把PicProcessor和PicStart项目都添加进新建的安装和部署项目Setup中来，把程序启动的快捷方式全部设为 PicStart.exe就可以了，具体的操作方法在上面的链接里有。然后开始生成安装包，生成的安装包如果选择大小优先的话，VMDotNet会占用大 概10Mb左右的空间，然后加上你程序的大小就是这个安装文件的大小了，比以前20多MB的.Net Framework小多了，而且安装速度也要快的多，这样程序在没有.Net Framework的机器上也能运行了，大家都试试吧，有什么问题可以给我留言。每天晚上一般我都会上线，会及时给大家回复的！</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 第一次写原创技术文章，不足之处，请大家多多包涵！谢谢！</p>
<p>&nbsp;转贴自<a href="http://hi.baidu.com/ck436/blog/item/b91b5f8295b7e8a10cf4d256.html">http://hi.baidu.com/ck436/blog/item/b91b5f8295b7e8a10cf4d256.html</a></p>
<p>&nbsp;</p>
<p>此文件是网上转贴过来的，只是给自己作为参考，起抛砖引玉的作用，没想到也有朋友看了这文章，所以特在此处说明一下：其实再用.Net作启动程序是不行的，应该用C++6.0的做一个启动程序，这样就OK了，呵。08.07.13</p>
<img src ="http://www.blogjava.net/smildlzj/aggbug/245614.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-12-11 09:42 <a href="http://www.blogjava.net/smildlzj/articles/245614.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使C#程序脱离.net框架运行(非飞信方式) </title><link>http://www.blogjava.net/smildlzj/articles/245611.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Thu, 11 Dec 2008 01:21:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/245611.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/245611.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/245611.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/245611.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/245611.html</trackback:ping><description><![CDATA[转：http://www.cnblogs.com/daylight/archive/2008/10/02/1303037.html<br />
<br />
<p>这几天看了很多关于脱离框架运行C#程序的文章，千篇一律，都是讲飞信方案的，此方案涉及一些法律问题，只能自己研究一下，后来用google美国网站搜了一把，看了些文章，无意中发现mono，又用mono关键字到google中国搜了一把，已经有人实现控制台程序脱离.net框架了。</p>
<p>其实就是换mono的公共语言运行时来使用。这样做的好处是体积小，发布免安装。首先，您需要下载mono的最新版。http://ftp.novell.com/pub/mono/archive/1.9.1/windows-installer/2/mono-1.9.1-gtksharp-2.10.4-win32-2.exe，安装后，就可以继续进行了。<br />
</p>
<p>1、用Visual Studio创建一个Windows应用程序，假设叫做WinApp，并添加一个按钮。</p>
<p>2、编译此项目，得到一个WinApp.exe文件。<br />
</p>
<p>3、自己建立一个文件夹WinApp，其中再建立bin和lib这两个文件夹</p>
<p>4、将mono安装文件夹中的bin和lib子文件夹中需要的文件拷贝至刚才建立的那两个文件夹。mono的默认安装位置是：C:\Program Files\Mono-1.9.1</p>
<p>5、将需要运行的exe文件放入WinApp文件夹。<br />
</p>
<p>6、调用，可以使用bat批处理来调用，bin\mono.exe WinApp.exe。(其实写个VC++的小程序调用最好，可以我没学过VC++)</p>
<p>好了，发个代码上来，有兴趣的朋友可以研究一下，7zip打包后仅3.26MB，却实现了免安装微软庞大的框架。此测试项目我在纯净的虚拟机和本机均测试过，但有个bug，mono对中文路径支持不好，如若有中文路径，则无法运行。我后来又试了用C:\Program Files\Mono-1.9.1\bin\mono.exe来执行，则没有中文路径问题。我觉得缺少了哪个文件，一个一个试着拷贝到WinApp文件夹中，再用批处理来执行，还是错误。后来干脆将整个安装目录的文件全搬到WinApp目录中，执行批处理还是失败，可是用C:\Program Files\Mono-1.9.1\bin\mono.exe来执行就是能成功，百思不得其解啊！究竟少了什么东西呢？</p>
<p>博客园单个文件限制在了1.95MB，我试了好多次不成功，大家到我的CSDN上下载吧，0分资源。<br />
</p>
<p>http://download.csdn.net/source/661248</p>
<img src ="http://www.blogjava.net/smildlzj/aggbug/245611.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-12-11 09:21 <a href="http://www.blogjava.net/smildlzj/articles/245611.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#使用BerkeleyDB操作简介 </title><link>http://www.blogjava.net/smildlzj/articles/240253.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Thu, 13 Nov 2008 02:37:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/240253.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/240253.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/240253.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/240253.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/240253.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Berkeley DB是历史悠久的嵌入式数据库系统，主要应用在UNIX/LINUX操作系统上。Berkeley DB的存储的是key/value键值对，可以理解为硬盘上的超级hash表。其可以管理256TB数据，而且能支撑几千个并发访问。目前Berkeley DB有C++版和Java版。所以，我们需要一个访问的中间转换，已经有人发布了C#的API。可以从 Berkeley DB for .NET&...&nbsp;&nbsp;<a href='http://www.blogjava.net/smildlzj/articles/240253.html'>阅读全文</a><img src ="http://www.blogjava.net/smildlzj/aggbug/240253.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-11-13 10:37 <a href="http://www.blogjava.net/smildlzj/articles/240253.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Berkeley DB for .NET - Hello, World!</title><link>http://www.blogjava.net/smildlzj/articles/240251.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Thu, 13 Nov 2008 02:35:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/240251.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/240251.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/240251.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/240251.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/240251.html</trackback:ping><description><![CDATA[<a title="http://www.oracle.com/database/berkeley-db/index.html" href="http://www.oracle.com/database/berkeley-db/index.html" target="_blank">Berkeley DB</a> 是个驰名已久的好东西，在专用领域，其性能罕有敌手。作为其 .NET 平台的封装版本，<a title="http://sourceforge.net/projects/libdb-dotnet" href="http://sourceforge.net/projects/libdb-dotnet" target="_blank">Berkeley DB for .NET</a> 却让人感觉非常郁闷，且不说那类似 C++ 风格的源码，单就其升级维护周期都让人很不放心。有点不理解，为什么作者不参考 Berkeley DB for Java ~~~~ 不过还好，0.95 版本的发布，让我们看到了实用的可能。Berkeley DB for .NET 的源码和文档看得我头晕脑胀，如果有什么差错，多多包涵&#8230;&#8230;<br />
<br />
有关 Berkeley DB 的基本概念，可参考以下文章。<br />
<br />
<a title="http://www-128.ibm.com/developerworks/cn/linux/l-embdb/" href="http://www-128.ibm.com/developerworks/cn/linux/l-embdb/" target="_blank">嵌入式数据库系统Berkeley DB</a> (施聪)<br />
<a title="http://blog.csdn.net/solotony/archive/2004/09/27/118163.aspx" href="http://blog.csdn.net/solotony/archive/2004/09/27/118163.aspx" target="_blank">Berkeley DB 概述</a> (皮东)<br />
<br />
C/C++ 使用教程<br />
<br />
<a title="http://www.cnblogs.com/jiezhi/category/54592.html" href="http://www.cnblogs.com/jiezhi/category/54592.html" target="_blank">风满袖</a><br />
<br />
----------- 犯困的分隔线 ----------------------<br />
<br />
先下载相关的程序包。<br />
<br />
<a title="http://www.oracle.com/technology/software/products/berkeley-db/htdocs/popup/db/4.5.20/db-msi.html" href="http://www.oracle.com/technology/software/products/berkeley-db/htdocs/popup/db/4.5.20/db-msi.html" target="_blank">Berkeley DB 4.5.20</a><br />
<a title="http://sourceforge.net/project/showfiles.php?group_id=153833&amp;package_id=170759&amp;release_id=502608" href="http://sourceforge.net/project/showfiles.php?group_id=153833&amp;package_id=170759&amp;release_id=502608" target="_blank">Berkeley DB for .NET 0.95</a><br />
<br />
将两个包中的 "libdb45.dll、libdb_dotNET45.dll、BerkeleyDb.Utils45.dll、Kds.Serialization.dll" 等文件拷贝到你的项目工程相关目录中，并将 Berkeley DB for .NET 的程序集(后三个文件) 添加到工程引用中。OK，还是老样子，先来个简单的 "Hello, World!" 试试。<br />
<div class="code">using System;<br />
using System.Collections.Generic;<br />
using System.Text;<br />
using System.IO;<br />
using BerkeleyDb;<br />
using BerkeleyDb.Serialization;<br />
using Kds.Serialization;<br />
using Kds.Serialization.Buffer;<br />
<br />
namespace ConsoleApplication1<br />
{<br />
&nbsp;&nbsp;public class Program<br />
&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;static void Main(string[] args)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;using (Db db = new Db(DbCreateFlags.None))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbFile dbf = db.Open(null, @"test._db", null, DbType.BTree, Db.OpenFlags.Create, 0);<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbEntry key = DbEntry.InOut(BitConverter.GetBytes(123));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DbEntry data = DbEntry.InOut(Encoding.UTF8.GetBytes("Hello, World!"));<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(dbf.Put(null, ref key, ref data));<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;dbf.Sync();<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ReadStatus status = dbf.Get(null, ref key, ref data, DbFile.ReadFlags.None);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;string s = Encoding.UTF8.GetString(data.Buffer, 0, data.Size);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Console.WriteLine(s);<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;}<br />
}</div>
<br />
输出：<br />
Success<br />
Hello, World! 
<img src ="http://www.blogjava.net/smildlzj/aggbug/240251.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-11-13 10:35 <a href="http://www.blogjava.net/smildlzj/articles/240251.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>两分钟用C#搭建IE BHO勾子, 窃取密码</title><link>http://www.blogjava.net/smildlzj/articles/239814.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Tue, 11 Nov 2008 02:50:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/239814.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/239814.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/239814.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/239814.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/239814.html</trackback:ping><description><![CDATA[<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">微软在1997年正式退出<span class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">Browser Helper Object (BHO), 使程序员能够更好的对IE进行二次开发和操作. 在通过编写BHO程序数月后, 我希望把我的一些经验告诉才开始的同志, 避免走一些弯路. </span></p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">我本人是非常喜欢C++的. 因为C++对内存直接操作的方式可以节省非常多的内存损耗, 也更快一些. 但是在开发BHO的时候, 我的确也认识到, C#明显要比C++强大很多. 例如C#提供的FOREACH 循环就可以避免FOR循环产生的溢出. 另外C#的类型转换也明显要强于C++. 毕竟BHO和C#都是出自微软一家, 理所当然, C#更适合BHO开发一些. 我的第一个BHO程序是用C++写的. 对于COM的操作,让我至少弄了几天才搞清楚他们到底想干什么. 但是我的第一个C# BHO程序只用了几分钟就搭建好了钩子. 如果你希望从事BHO开发, 而且你才开始学. 我想这片篇文章对您有点帮助. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">这篇文章本来是用英文写成的. 因为工作环境的原因, 中文已经越来越生疏. 如果有错误或者不太明显的地方. 请参考英文原文</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">http://www.horizonideas.com/writings/article.php?id=11 </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">下面竟让我们开始. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">首先我们需要在C#中新建一个DLL工程. 因为BHO是通过让IE调用DLL来驱动的. 我用的是V C# EXPRESS. 因为这已经完全够用了. V C# PROFESSIONAL 并不需要, 而且还很浪费内存. </p>
<span class="STYLE4"><br />
<a href="http://www.horizonideas.com/writings/1.jpg" target="_blank"><img style="width: 662px; height: 435px" src="http://www.horizonideas.com/writings/BHO/1.jpg" border="0"  alt="" /></a>&nbsp;<br />
<br />
</span>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">当我们建立一个空工程以后, 随便添加一个文件夹叫BHO, 然后添加一个文件.<br />
<img src="http://www.horizonideas.com/writings/BHO/2.jpg"  alt="" /></p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">需要我们注意的是, 我们这个文件必须被命名为IObjectWithSite.cs因为这样IE才知道这是一个BHO程序. 如果想知道更多关于IObjectWiteSite接口的内容, 请查询MSDN<a href="http://msdn2.microsoft.com/en-us/library/Aa768220.aspx"> http://msdn2.microsoft.com/en-us/library/Aa768220.aspx</a></p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">在IObjectWithSite中必须有两个方法GetSite和SetSite. 我们主要是对后者进行调用.通过名字大家就可以猜到他们是干什么的. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><a href="http://msdn2.microsoft.com/en-us/library/aa768219.aspx">GetSite</a>: <span style="mso-spacerun: yes">&nbsp;</span>Gets the last site set with <a href="http://msdn2.microsoft.com/en-us/library/aa768221.aspx">IObjectWithSite::SetSite</a>. If there is no known site, the object returns a failure code.</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><a href="http://msdn2.microsoft.com/en-us/library/aa768221.aspx">SetSite</a>: <span style="mso-spacerun: yes">&nbsp;</span>Provides the site's <a href="http://msdn2.microsoft.com/en-us/library/ms680509.aspx">IUnknown</a> pointer to the object.</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">请把VS STUIDO 默认的类名给去掉.因为IObjectWithSite并不是一个类, 而是一个接口. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/3.jpg"  alt="" />&nbsp;</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">不要忘记添加 System.Runtime.InteropServices</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/4.jpg"  alt="" /> </p>
<p class="STYLE4">下面我们再添加剂一个叫BHO.CS的主文件.</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/5.jpg"  alt="" /></p>
<p class="STYLE4">这个新建的类是基于 IObjectWithSite接口的. 正如同我前面讲的. 你就是通过这个接口来调用IE. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/7.jpg"  alt="" />&nbsp;</p>
<p class="STYLE4">为了使用微软的BHO库.我们必须添加下面两个库: SHDocVw and MSHTML.他们一般都在 Windows\System32 下面</p>
<p class="STYLE4">SHDocVw is&nbsp; Microsoft Shell Doc Object and Control Library</p>
<p class="STYLE4">MSHTML is: &nbsp; All interfaces for accessing the Dynamic HTML (DHTML) Object Model are based on <a onclick="javascript:Track('ctl00_LibFrame_ctl01|ctl00_LibFrame_ctl03',this);" href="http://msdn2.microsoft.com/en-us/library/ms221608.aspx">IDispatch</a> and are the basis of access to the object model that is also used by scripts. http://msdn2.microsoft.com/en-us/library/bb498651.aspx</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/8.jpg"  alt="" /> </p>
<p class="STYLE4">光using SHDocVw" 是不够的, 你需要添加 </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/9.jpg"  alt="" /> </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><a href="http://www.horizonideas.com/writings/10.jpg" target="_blank"><img style="width: 696px; height: 320px" height="372" src="http://www.horizonideas.com/writings/BHO/10.jpg" width="806" border="0"  alt="" /></a></p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">Add SHDocVw&nbsp;</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><a href="http://www.horizonideas.com/writings/11.jpg" target="_blank"><img style="width: 689px; height: 98px" src="http://www.horizonideas.com/writings/BHO/11.jpg" border="0"  alt="" /></a> </p>
<p class="STYLE4">因为稍后我们需要用到MESSAGEBOX, 所以这里我也添加了一个WINDOWS FORM库. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><a href="http://www.horizonideas.com/writings/12.jpg" target="_blank"><img style="width: 724px; height: 392px" src="http://www.horizonideas.com/writings/BHO/12.jpg" border="0"  alt="" /></a>&nbsp;</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">下面添加两个变量: WebBrowser and HTMLDocument. 就如同他们的名字. 一个是IE的变量, 另外一个是IE所访问的HTML页变量. </p>
<p class="STYLE4">下面在这个类中田间一个叫 OnDocumentComplete 的函数. 取其他名字也行, 没什么太大关系. 但是这里为了CODE的可用性,我们叫OnDocumentComplete. 这个函数实际上是和CDHTMLDIALOG下面的OnDocumentComplete所对应的.</p>
<p class="STYLE4">CDHtmlDialog Class http://msdn2.microsoft.com/en-us/library/8bed8k60(VS.80).aspx . </p>
<p class="STYLE4">OnDocumentComplete的触发是在一个HTML页被LOAD完以后. 你也可以避免用Navigate() or OnBeforeNavigate(). 他们表示在发出访问和访问之前触发. </p>
<p class="STYLE4">Please refer to http://msdn2.microsoft.com/en-us/library/8k5z3ekh(VS.80).aspx to find out what you need exactly. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/13.jpg"  alt="" /> </p>
<p class="STYLE4">在 IObjectWithSite.cs下,你需要支出IE的GUID, 这样才方便注册表的更改.</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/14.jpg"  alt="" /> </p>
<p class="STYLE4">另外你需要给自己的程序添加一个GUID. 这样IE才能在注册表中找到你的信息. 你可以使用System.Guid.NewGuid() method 来得到一个GUID. 这比C++得到GUID的方法要容易得多了. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/15.jpg"  alt="" />&nbsp;</p>
<p class="STYLE4">我们必须给 SetSite and GetSite 加上内容. 在SETSITE中我们就需要加入一个EVENTHANDLER, 让IE来触发我们的OnDocumentComplete函数. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/16-1.jpg"  alt="" /> </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">Add one more reference</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/16.jpg"  alt="" /> </p>
<p class="STYLE4">在BHO.CS下我们需要为我们的DLL添加register/unregister 函数. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/17.jpg"  alt="" /> <img src="http://www.horizonideas.com/writings/BHO/18.jpg"  alt="" /> </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">编译, 我们就有了我们的DLL.</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img style="width: 732px; height: 96px" src="http://www.horizonideas.com/writings/BHO/19.jpg"  alt="" /> </p>
<p class="STYLE4">下面通过DOS下的 regasm /codebase "BHO HelloWorld.dll" 命令在注册dll. 这里有一个问题了, 为什么?</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/20.jpg"  alt="" /> </p>
<p class="STYLE4">因为我们忘了把我们的主类设置成PUBLIC, 所以别人都不能调用到你的类. 自然注册不了. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/21.jpg"  alt="" />&nbsp;</p>
<p class="STYLE4">然后就成功了. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/22.jpg"  alt="" /> </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">打开注册表, 找到Browser Helper Object under LOCAL_MACHINE-&gt;SOFTWARE-&gt;MICROSOFT-&gt;WINDOWS-&gt;EXPLORER, 看看是不是有变化了? </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img style="width: 847px; height: 308px" src="http://www.horizonideas.com/writings/BHO/23.jpg"  alt="" />&nbsp; </p>
<p class="STYLE4">我们注册完了, 下面就是来写我们的住程序来控制IE了. 下面就是一个例子来抓去你正访问的页面上的所有INPUT 元素的NAME. </p>
<p class="STYLE4">在DOCUMENT中, 我们的所有元素都为IHTMLElement, 我们需要调用的是IHTMLInputElement. 所以我们通过GetElementByTagName的方法来查找所有的INPUT ELEMENT. 在找到以后还需要进行类型转换才能找到对应的ATTRIBUTE. 否则IHTMLElement是不代有NAME ATTRIBUTE的. IHTMLElement提供的ATTRIBUTE都是所有元素都有的. 例如ID, 例如TITLE, 例如OnClick等. 有的元素有自己特有的ATTRIBUTE, 例如INPUT有OnFocus这就必须要转换成IHTMLInputElement才能上使用. INPUT对应的IHTMLInputElement, Select-&gt; IHTMLSelectElement ....... </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/24.jpg"  alt="" /> </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">There you go, see? </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><a href="http://www.horizonideas.com/writings/25.jpg" target="_blank"><img src="http://www.horizonideas.com/writings/BHO/25.jpg" border="0"  alt="" /></a> </p>
<p class="STYLE4">下面我们试另外一个方法叫 BeforeNavigate() .它的触发是在你开始下一个页面之前. 也就是说例如你要提交一个表单, 页面要变化了, 他就被触发. </p>
<p class="STYLE4">实际上MS提供了两个类似的接口 BeforeNavigate and BeforeNavigate2(). 大家可以查MSDN看看有什么区别. 这里我们不多讲了. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><a href="http://www.horizonideas.com/writings/26.jpg" target="_blank"><img style="width: 728px; height: 257px" src="http://www.horizonideas.com/writings/BHO/26.jpg" border="0"  alt="" /></a>&nbsp;</p>
<p class="STYLE4">同样我们添加一个对应的函数原形(点图片, 看大图). </p>
<p class="STYLE4"><a href="http://www.horizonideas.com/writings/27.jpg" target="_blank"><img height="103" src="http://www.horizonideas.com/writings/BHO/27.jpg" width="819" border="0"  alt="" /></a> </p>
<p class="STYLE4">添加EVENTHANDLER</p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/28.jpg"  alt="" /> </p>
<p class="STYLE4">我们下面要干的是截获页面上的密码. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/29.jpg"  alt="" /> </p>
<p class="STYLE4">See, how easily, you can get it. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><span class="STYLE4"><span class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><img src="http://www.horizonideas.com/writings/BHO/30.jpg"  alt="" /></span></span></p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">通过上面的过程. 我希望您对BHO有一个初步的了解. 如果想知道更多内容, 请访问MSDN. 里面有非常详细的介绍. 这里也引出了一个话题. 我们可以看到, 几乎用不了两分钟我们就可以截获你填写的任何内容, 你觉得IE是安全的吗? 即使他可以通过SSL来对进出网卡的内容加密, 但是在应用层一样是如此的薄弱. 另外大家如果用IE都会发觉泛滥成灾的ADD-ON, 这就是因为BHO惹的祸. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">大家如果不想按照我上面的打,可以下我做好的模版.直接放到你的<span class="MsoNormal STYLE4" style="margin: 0in 0in 10pt">Visual Studio 2005\Templates\ProjectTemplates</span>文件夹下. 当开始一个新工程时候, 点下那个BHO HELLOWORLD就可以了. 所有上面的代码都给你做好了. </p>
<p class="MsoNormal STYLE4" style="margin: 0in 0in 10pt"><a class="STYLE4" href="http://www.horizonideas.com/writings/BHO/BHO%20HelloWorld.zip" target="_blank">project template</a>下载TEMPLATE</p>
<p class="STYLE4"><img src="http://www.horizonideas.com/writings/BHO/BHO%20template.JPG"  alt="" />&nbsp;</p>
<img src ="http://www.blogjava.net/smildlzj/aggbug/239814.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-11-11 10:50 <a href="http://www.blogjava.net/smildlzj/articles/239814.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>VS2005 多线程问题--窗体中的线程安全调用</title><link>http://www.blogjava.net/smildlzj/articles/237767.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Fri, 31 Oct 2008 02:32:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/237767.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/237767.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/237767.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/237767.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/237767.html</trackback:ping><description><![CDATA[<p>访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态，则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug，包括争用情况和死锁。确保以线程安全方式访问控件非常重要。</p>
<p>.NET Framework 有助于在以非线程安全方式访问控件时检测到这一问题。在调试器中运行应用程序时，如果创建某控件的线程之外的其他线程试图调用该控件，则调试器会引发一个 InvalidOperationException，并提示消息：&#8220;从不是创建控件 control name 的线程访问它。&#8221; </p>
<p>有三种方法可以从线程访问Win窗体的控件：非线程安全方式；线程安全调用；使用BackgroundWorker进行的线程安全调用。其中，只有线程的安全调用可以宏观并行处理。（另外两种方式都是在线程运行时接受命令，但在线程执行完以后才执行）。</p>
<p><strong>一：对Windows窗体控件的非线程安全调用</strong></p>
<p>该方式是从辅助线程直接调用。调用应用程序时，调试器会引发一个InvalidOperationException，警告对控件的调用不是线程安全的。</p>
<p>可以通过将 CheckForIllegalCrossThreadCalls 属性的值设置为 false 来禁用此异常。这会使控件以与在 Visual Studio 2003 下相同的方式运行。</p>
<p>具体做法如下：</p>
<p>&nbsp; </p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(0,0,255)">public</span><span style="color: rgb(0,0,0)">&nbsp;Form1()<br />
<img id="_23_149_Open_Image" onclick="this.style.display='none'; document.getElementById('_23_149_Open_Text').style.display='none'; document.getElementById('_23_149_Closed_Image').style.display='inline'; document.getElementById('_23_149_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_23_149_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_23_149_Closed_Text').style.display='none'; document.getElementById('_23_149_Open_Image').style.display='inline'; document.getElementById('_23_149_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="_23_149_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_23_149_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;InitializeComponent();<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Control.CheckForIllegalCrossThreadCalls&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">false</span><span style="color: rgb(0,0,0)">;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">这一行是关键&nbsp;用于对线程的不安全调用</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" /></span><span style="color: rgb(0,0,0)">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span></span></div>
</div>
<p>&nbsp;</p>
<p><strong>二：对Windows窗体控件的线程安全调用</strong></p>
<p>对窗体控件的线程安全调用需要用委托的方式。</p>
<p>主要思路：</p>
<p>1、查询控件的 InvokeRequired 属性。</p>
<p>2、如果 InvokeRequired 返回 true，则使用实际调用控件的委托来调用 Invoke。</p>
<p>3、如果 InvokeRequired 返回 false，则直接调用控件。</p>
<p>例子：在TextBox控件中输出相应的信息，SetText为textbox的内容设置方法，SetTextDelegate的委托类型封装 SetText方法。TextBox控件的InvokeRequired返回true是，SetText方法创建SetTextDelegate的一个实 例，并调用窗体的Invoke方法。是的SetText方法被创建TextBox控件的线程调用。</p>
<p>&nbsp;</p>
<p><font color="#008000">&nbsp;&nbsp;&nbsp; </p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><font size="+0"><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(0,0,0)">&nbsp;&nbsp;</span><span style="color: rgb(0,0,0)">/</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,0)">/</span><span style="color: rgb(0,0,0)">该委托使在一个TextBox控件上设置text属性的异步调用功能为真<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">delegate</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;SetTextCallback(</span><span style="color: rgb(0,0,255)">string</span><span style="color: rgb(0,0,0)">&nbsp;text);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;该线程用于对Windows窗体控件的安全调用</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;Thread&nbsp;demoThread&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">null</span><span style="color: rgb(0,0,0)">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />&nbsp;</span></font></div>
</div>
<br />
</font>
<p>&nbsp;</p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;该事件句柄创建一个对窗体控件线程安全调用的线程</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;setTextSafeBtn_Click(&nbsp;</span><span style="color: rgb(0,0,255)">object</span><span style="color: rgb(0,0,0)">&nbsp;sender,&nbsp;&nbsp;EventArgs&nbsp;e)<br />
<img id="_92_204_Open_Image" onclick="this.style.display='none'; document.getElementById('_92_204_Open_Text').style.display='none'; document.getElementById('_92_204_Closed_Image').style.display='inline'; document.getElementById('_92_204_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_92_204_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_92_204_Closed_Text').style.display='none'; document.getElementById('_92_204_Open_Image').style.display='inline'; document.getElementById('_92_204_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_92_204_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_92_204_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.demoThread&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;Thread(</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;ThreadStart(</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.ThreadProcSafe));<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.demoThread.Start();<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;该方法在Worker线程中执行并且发出一个线程安全的调用</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;ThreadProcSafe()<br />
<img id="_270_319_Open_Image" onclick="this.style.display='none'; document.getElementById('_270_319_Open_Text').style.display='none'; document.getElementById('_270_319_Closed_Image').style.display='inline'; document.getElementById('_270_319_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_270_319_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_270_319_Closed_Text').style.display='none'; document.getElementById('_270_319_Open_Image').style.display='inline'; document.getElementById('_270_319_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_270_319_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_270_319_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.SetText(</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">This&nbsp;text&nbsp;was&nbsp;set&nbsp;safely.</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">如果被调用的线程和创建的TextBox控件不同，该方法就创建一个SetTextCallback，<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;并且用Invoke方法异步调用自己。<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;如果相同，则直接调用方法设置Text的属性。</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;SetText(</span><span style="color: rgb(0,0,255)">string</span><span style="color: rgb(0,0,0)">&nbsp;text)<br />
<img id="_457_749_Open_Image" onclick="this.style.display='none'; document.getElementById('_457_749_Open_Text').style.display='none'; document.getElementById('_457_749_Closed_Image').style.display='inline'; document.getElementById('_457_749_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_457_749_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_457_749_Closed_Text').style.display='none'; document.getElementById('_457_749_Open_Image').style.display='inline'; document.getElementById('_457_749_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_457_749_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_457_749_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">&nbsp;获取的InvokeRequired将调用的线程ID和创建的线程ID向比较。&nbsp;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,128,0)">//</span><span style="color: rgb(0,128,0)">如果两个线程ID不同，则返回true&nbsp;</span><span style="color: rgb(0,128,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" /></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">if</span><span style="color: rgb(0,0,0)">&nbsp;(</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.textBox1.InvokeRequired)<br />
<img id="_577_691_Open_Image" onclick="this.style.display='none'; document.getElementById('_577_691_Open_Text').style.display='none'; document.getElementById('_577_691_Closed_Image').style.display='inline'; document.getElementById('_577_691_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_577_691_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_577_691_Closed_Text').style.display='none'; document.getElementById('_577_691_Open_Image').style.display='inline'; document.getElementById('_577_691_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="_577_691_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_577_691_Open_Text"><span style="color: rgb(0,0,0)">{&nbsp;&nbsp;&nbsp;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SetTextCallback&nbsp;d&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;SetTextCallback(SetText);<br />
<img id="_676_683_Open_Image" onclick="this.style.display='none'; document.getElementById('_676_683_Open_Text').style.display='none'; document.getElementById('_676_683_Closed_Image').style.display='inline'; document.getElementById('_676_683_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_676_683_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_676_683_Closed_Text').style.display='none'; document.getElementById('_676_683_Open_Image').style.display='inline'; document.getElementById('_676_683_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.Invoke(d,&nbsp;</span><span style="color: rgb(0,0,255)">new</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">object</span><span style="color: rgb(0,0,0)">[]&nbsp;</span><span id="_676_683_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_676_683_Open_Text"><span style="color: rgb(0,0,0)">{&nbsp;text&nbsp;}</span></span><span style="color: rgb(0,0,0)">);<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">else</span><span style="color: rgb(0,0,0)"><br />
<img id="_706_747_Open_Image" onclick="this.style.display='none'; document.getElementById('_706_747_Open_Text').style.display='none'; document.getElementById('_706_747_Closed_Image').style.display='inline'; document.getElementById('_706_747_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockStart.gif" align="top" /><img id="_706_747_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_706_747_Closed_Text').style.display='none'; document.getElementById('_706_747_Open_Image').style.display='inline'; document.getElementById('_706_747_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedSubBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="_706_747_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_706_747_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.textBox1.Text&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)">&nbsp;text;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span></div>
</div>
<br />
<p><strong>三、使用 BackgroundWorker 进行的线程安全调用</strong><br />
在应用程序中实现多线程的首选方式是 使用 BackgroundWorker 组件。BackgroundWorker 组件使用事件驱动模型实现多线程。辅助线程运行 DoWork 事件处理程序，创建控件的线程运行 ProgressChanged 和 RunWorkerCompleted 事件处理程序。注意不要从 DoWork 事件处理程序调用您的任何控件。</p>
<p>下面的代码示例不异步执行任何工作，因此没有 DoWork 事件处理程序的实现。TextBox 控件的 Text 属性在 RunWorkerCompleted 事件处理程序中直接设置。</p>
<div style="border-right: windowtext 0.5pt solid; padding-right: 5.4pt; border-top: windowtext 0.5pt solid; padding-left: 5.4pt; background: rgb(230,230,230) 0% 50%; padding-bottom: 4px; border-left: windowtext 0.5pt solid; width: 95%; padding-top: 4px; border-bottom: windowtext 0.5pt solid; moz-background-clip: -moz-initial; moz-background-origin: -moz-initial; moz-background-inline-policy: -moz-initial">
<div><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;setTextBackgroundWorkerBtn_Click(</span><span style="color: rgb(0,0,255)">object</span><span style="color: rgb(0,0,0)">&nbsp;sender,&nbsp;&nbsp;EventArgs&nbsp;e)<br />
<img id="_75_122_Open_Image" onclick="this.style.display='none'; document.getElementById('_75_122_Open_Text').style.display='none'; document.getElementById('_75_122_Closed_Image').style.display='inline'; document.getElementById('_75_122_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_75_122_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_75_122_Closed_Text').style.display='none'; document.getElementById('_75_122_Open_Image').style.display='inline'; document.getElementById('_75_122_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_75_122_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_75_122_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.backgroundWorker1.RunWorkerAsync();<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span><span style="color: rgb(0,0,255)">private</span><span style="color: rgb(0,0,0)">&nbsp;</span><span style="color: rgb(0,0,255)">void</span><span style="color: rgb(0,0,0)">&nbsp;backgroundWorker1_RunWorkerCompleted(</span><span style="color: rgb(0,0,255)">object</span><span style="color: rgb(0,0,0)">&nbsp;sender,&nbsp;RunWorkerCompletedEventArgs&nbsp;e)<br />
<img id="_221_305_Open_Image" onclick="this.style.display='none'; document.getElementById('_221_305_Open_Text').style.display='none'; document.getElementById('_221_305_Closed_Image').style.display='inline'; document.getElementById('_221_305_Closed_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" align="top" /><img id="_221_305_Closed_Image" style="display: none" onclick="this.style.display='none'; document.getElementById('_221_305_Closed_Text').style.display='none'; document.getElementById('_221_305_Open_Image').style.display='inline'; document.getElementById('_221_305_Open_Text').style.display='inline';" alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" align="top" /></span><span id="_221_305_Closed_Text" style="border-right: rgb(128,128,128) 1px solid; border-top: rgb(128,128,128) 1px solid; display: none; border-left: rgb(128,128,128) 1px solid; border-bottom: rgb(128,128,128) 1px solid; background-color: rgb(255,255,255)">...</span><span id="_221_305_Open_Text"><span style="color: rgb(0,0,0)">{<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,255)">this</span><span style="color: rgb(0,0,0)">.textBox1.Text&nbsp;</span><span style="color: rgb(0,0,0)">=</span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" align="top" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">This&nbsp;text&nbsp;was&nbsp;set&nbsp;safely&nbsp;by&nbsp;BackgroundWorker.</span><span style="color: rgb(0,0,0)">"</span><span style="color: rgb(0,0,0)">;<br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" align="top" />}</span></span><span style="color: rgb(0,0,0)"><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><br />
<img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /></span></div>
</div>
<br />
<img src ="http://www.blogjava.net/smildlzj/aggbug/237767.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-10-31 10:32 <a href="http://www.blogjava.net/smildlzj/articles/237767.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#线程调用带参数的方法</title><link>http://www.blogjava.net/smildlzj/articles/237762.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Fri, 31 Oct 2008 02:17:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/237762.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/237762.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/237762.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/237762.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/237762.html</trackback:ping><description><![CDATA[<p><strong><font color="#0000ff">方法一：</font></strong></p>
<p>一般来说，直接在子线程中对窗体上的控件操作是会出现异常，这是由于子线程和运行窗体的线程是不同的空间，因此想要在子线程来操作窗体上的控件，是 不可能 简单的通过控件对象名来操作，但不是说不能进行操作，微软提供了Invoke的方法，其作用就是让子线程告诉窗体线程来完成相应的控件操作。</p>
<table id="middle" style="table-layout: fixed" cellspacing="0" cellpadding="0" width="100%">
    <tbody>
        <tr>
            <td>
            <div class="mframe">
            <div class="wrapper">
            <div class="mm" id="bodyTd">
            <div id="printBody">
            <div id="content">
            <p>现在用一个用线程控制的进程条来说明，大致的步骤如下：</p>
            <p>1．创建Invoke函数，大致如下：&nbsp;&nbsp;<br />
            /// &lt;summary&gt;&nbsp;&nbsp;<br />
            /// Delegate function be invoked by main thread&nbsp;&nbsp;<br />
            /// &lt;/summary&gt;&nbsp;&nbsp;<br />
            private&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InvokeFun()&nbsp;&nbsp;<br />
            {&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; if(prgBar.Value&lt; 100)&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; prgBar.Value = prgBar.Value + 1;&nbsp;&nbsp;<br />
            }&nbsp;&nbsp;</p>
            <p>2．子线程入口函数：&nbsp;&nbsp;<br />
            /// &lt;summary&gt;&nbsp;&nbsp;<br />
            /// Thread function interface&nbsp;&nbsp;<br />
            /// &lt;/summary&gt;&nbsp;&nbsp;<br />
            private void ThreadFun()&nbsp;&nbsp;<br />
            {&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; // Create invoke method by specific function<br />
            &nbsp;&nbsp;&nbsp;&nbsp; MethodInvoker mi = new MethodInvoker(this.InvokeFun);&nbsp;&nbsp;</p>
            <p>&nbsp;&nbsp;&nbsp;&nbsp; for(int i=0; i&lt;100; i++)&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; {&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.BeginInvoke(mi);&nbsp;&nbsp;&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Thread.Sleep(100);&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }&nbsp;&nbsp;<br />
            }</p>
            <p>3.创建子线程：&nbsp;&nbsp;<br />
            Thread thdProcess = new Thread(new ThreadStart(ThreadFun));&nbsp;&nbsp;<br />
            thdProcess.Start();&nbsp;&nbsp;</p>
            <p><font color="#0000ff"><strong>方法二：</strong></font><br />
            加入该句：Control.CheckForIllegalCrossThreadCalls = False&nbsp;&nbsp;&nbsp;&nbsp; 取消线线程安全保护模式！</p>
            <p><font color="#0000ff"><strong>方法三：带参数<br />
            </strong></font>使用类、类的方法或类的属性都可以向线程传递参数：<br />
            public class UrlDownloader<br />
            {<br />
            &nbsp;&nbsp;&nbsp;&nbsp; string url;<br />
            &nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public UrlDownloader (string url)<br />
            &nbsp;&nbsp;&nbsp;&nbsp; {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.url = url;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            &nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp; public void Download()<br />
            &nbsp;&nbsp;&nbsp;&nbsp; {<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WebClient wc = new WebClient();<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("Downloading " + url);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; byte[] buffer = wc.DownloadData (url);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string download = Encoding.ASCII.GetString(buffer);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(download);<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine("Download successful.");<br />
            &nbsp;&nbsp;&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //这里你可以将download进行保存等处理......<br />
            &nbsp;&nbsp;&nbsp;&nbsp; }<br />
            }</p>
            <p>[... 在另一个类中使用它们...]<br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
            UrlDownloader downloader = new UrlDownloader (yourUrl);<br />
            new Thread (new ThreadStart (downloader.Download)).Start();</p>
            <p>注意参数是如何传递的。</p>
            <p><font color="#0000ff"><strong>方法四：带参数<br />
            </strong></font>ThreadStart starter = delegate { Download(yourUrl); };<br />
            new Thread(starter).Start();<br />
            <br />
            //使用线程池<br />
            WaitCallback callback = delegate (object state) { Download ((string)state); };<br />
            ThreadPool.QueueUserWorkItem (callback, yourUrl);</p>
            <p><font color="#0000ff"><strong>方法五：带参数</strong></font><br />
            Thread t = <span class="Keyword">new</span> Thread (<span class="Keyword">new</span> <font color="#ff6600">ParameterizedThreadStart</font>(DownloadUrl));<br />
            t.Start (myUrl);<br />
            <span class="Modifier">static</span> <span class="ValueType">void</span> DownloadUrl(<span class="ReferenceType">object</span> url)<br />
            {<br />
            &nbsp;&nbsp;<span class="InlineComment">// ....<br />
            </span>}</p>
            </div>
            </div>
            <script type="text/JavaScript">




 
alimama_pid="mm_10498610_623104_1064319"; 
alimama_titlecolor="0000FF"; 
alimama_descolor ="000000"; 
alimama_bgcolor="FFFFFF"; 
alimama_bordercolor="E6E6E6"; 
alimama_linkcolor="008000"; 
alimama_bottomcolor="FFFFFF"; 
alimama_anglesize="0"; 
alimama_bgpic="0"; 
alimama_icon="0"; 
alimama_sizecode="14"; 
alimama_width=728; 
alimama_height=90; 
alimama_type=2; </script><script src="http://a.alimama.cn/inf.js" type="text/javascript">




 </script></div>
            </div>
            </div>
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/smildlzj/aggbug/237762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-10-31 10:17 <a href="http://www.blogjava.net/smildlzj/articles/237762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c#遍历HashTable</title><link>http://www.blogjava.net/smildlzj/articles/220576.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Thu, 07 Aug 2008 02:05:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/220576.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/220576.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/220576.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/220576.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/220576.html</trackback:ping><description><![CDATA[From: <a href="http://blog.csdn.net/mike1983/archive/2008/06/20/2568647.aspx">http://blog.csdn.net/mike1983/archive/2008/06/20/2568647.aspx</a><span id="Post.ascx_ViewPost_PreviousAndNextEntriesUp">
<div class="blogstory"></span>
<fieldset><legend>方法一</legend>
<p>&nbsp;foreach (System.Collections.DictionaryEntry objDE in objHasTab) { &nbsp;&nbsp;&nbsp; Console.WriteLine(objDE.Key.ToString()); &nbsp;&nbsp;&nbsp; Console.WriteLine(objDE.Value.ToString()); } </p>
</fieldset>
<p>&nbsp;</p>
<fieldset><legend>方法二</legend>
<p>System.Collections.IDictionaryEnumerator enumerator = objHashTablet.GetEnumerator(); while (enumerator.MoveNext()) { &nbsp;&nbsp;&nbsp; Console.WriteLine(enumerator.Key);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Hashtable关健字 &nbsp;&nbsp;&nbsp; Console.WriteLine(enumerator.Value);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // Hashtable值 }</p>
</fieldset></div>
<img src ="http://www.blogjava.net/smildlzj/aggbug/220576.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-08-07 10:05 <a href="http://www.blogjava.net/smildlzj/articles/220576.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ArrayList用法 </title><link>http://www.blogjava.net/smildlzj/articles/220574.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Thu, 07 Aug 2008 02:03:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/220574.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/220574.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/220574.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/220574.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/220574.html</trackback:ping><description><![CDATA[<p>System.Collections.ArrayList类是一个特殊的数组。通过添加和删除元素，就可以动态改变数组的长度。</p>
<p>一．优点</p>
<p>1。支持自动改变大小的功能<br />
2。可以灵活的插入元素<br />
3。可以灵活的删除元素</p>
<p>二．局限性</p>
<p>跟一般的数组比起来，速度上差些</p>
<p>三．添加元素</p>
<p>1．publicvirtualintAdd(objectvalue);</p>
<p>将对象添加到ArrayList的结尾处</p>
<p>ArrayListaList=newArrayList();<br />
aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("c");<br />
aList.Add("d");<br />
aList.Add("e");<br />
内容为abcde</p>
<p>2．publicvirtualvoidInsert(intindex,objectvalue);</p>
<p>将元素插入ArrayList的指定索引处</p>
<p>ArrayListaList=newArrayList();<br />
aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("c");<br />
aList.Add("d");<br />
aList.Add("e");<br />
aList.Insert(0,"aa");</p>
<p>结果为aaabcde</p>
<p>3．publicvirtualvoidInsertRange(intindex,ICollectionc);</p>
<p>将集合中的某个元素插入ArrayList的指定索引处</p>
<p>ArrayListaList=newArrayList();<br />
aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("c");<br />
aList.Add("d");<br />
aList.Add("e");<br />
ArrayListlist2=newArrayList();<br />
list2.Add("tt");<br />
list2.Add("ttt");<br />
aList.InsertRange(2,list2);</p>
<p>结果为abtttttcde</p>
<p>四．删除</p>
<p>a)publicvirtualvoidRemove(objectobj);</p>
<p>从ArrayList中移除特定对象的第一个匹配项,注意是第一个</p>
<p>ArrayListaList=newArrayList();<br />
aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("c");<br />
aList.Add("d");<br />
aList.Add("e");<br />
aList.Remove("a");</p>
<p>结果为bcde</p>
<p>2.publicvirtualvoidRemoveAt(intindex);</p>
<p>移除ArrayList的指定索引处的元素</p>
<p>aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("c");<br />
aList.Add("d");<br />
aList.Add("e");<br />
aList.RemoveAt(0);</p>
<p>结果为bcde</p>
<p>3．publicvirtualvoidRemoveRange(intindex,intcount);</p>
<p>从ArrayList中移除一定范围的元素。Index表示索引，count表示从索引处开始的数目</p>
<p>aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("c");<br />
aList.Add("d");<br />
aList.Add("e");<br />
aList.RemoveRange(1,3);</p>
<p>结果为ae</p>
<p>4．publicvirtualvoidClear();</p>
<p>从ArrayList中移除所有元素。</p>
<p>五．排序</p>
<p>a)publicvirtualvoidSort();</p>
<p>对ArrayList或它的一部分中的元素进行排序。</p>
<p>ArrayListaList=newArrayList();<br />
aList.Add("e");<br />
aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("c");<br />
aList.Add("d");<br />
DropDownList1.DataSource=aList;//DropDownListDropDownList1;<br />
DropDownList1.DataBind();</p>
<p>结果为eabcd</p>
<p>ArrayListaList=newArrayList();<br />
aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("c");<br />
aList.Add("d");<br />
aList.Add("e");<br />
aList.Sort();//排序<br />
DropDownList1.DataSource=aList;//DropDownListDropDownList1;<br />
DropDownList1.DataBind();</p>
<p>结果为abcde</p>
<p>b)publicvirtualvoidReverse();</p>
<p>将ArrayList或它的一部分中元素的顺序反转。</p>
<p>ArrayListaList=newArrayList();<br />
aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("c");<br />
aList.Add("d");<br />
aList.Add("e");<br />
aList.Reverse();//反转<br />
DropDownList1.DataSource=aList;//DropDownListDropDownList1;<br />
DropDownList1.DataBind();<br />
结果为edcba</p>
<p>六．查找</p>
<p>a)publicvirtualintIndexOf(object);<br />
b)publicvirtualintIndexOf(object,int);<br />
c)publicvirtualintIndexOf(object,int,int);</p>
<p>返回ArrayList或它的一部分中某个值的第一个匹配项的从零开始的索引。没找到返回-1。</p>
<p>ArrayListaList=newArrayList();<br />
aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("c");<br />
aList.Add("d");<br />
aList.Add("e");<br />
intnIndex=aList.IndexOf(&#8220;a&#8221;);//1<br />
nIndex=aList.IndexOf(&#8220;p&#8221;);//没找到，-1<br />
d)publicvirtualintLastIndexOf(object);<br />
e)publicvirtualintLastIndexOf(object,int);<br />
f)publicvirtualintLastIndexOf(object,int,int);</p>
<p>返回ArrayList或它的一部分中某个值的最后一个匹配项的从零开始的索引。</p>
<p>ArrayListaList=newArrayList();<br />
aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("a");//同0<br />
aList.Add("d");<br />
aList.Add("e");<br />
intnIndex=aList.LastIndexOf("a");//值为2而不是0</p>
<p>g)publicvirtualboolContains(objectitem);</p>
<p>确定某个元素是否在ArrayList中。包含返回true,否则返回false</p>
<p>七．其他</p>
<p>1．publicvirtualintCapacity{get;set;}</p>
<p>获取或设置ArrayList可包含的元素数。</p>
<p>2．publicvirtualintCount{get;}</p>
<p>获取ArrayList中实际包含的元素数。<br />
Capacity是ArrayList可以存储的元素数。Count是ArrayList中实际包含的元素数。Capacity总是大于或等于Count。如果在添加元素时，Count超过Capacity，则该列表的容量会通过自动重新分配内部数组加倍。<br />
如果Capacity的值显式设置，则内部数组也需要重新分配以容纳指定的容量。如果Capacity被显式设置为0，则公共语言运行库将其设置为默认容量。默认容量为16。<br />
在调用Clear后，Count为0，而此时Capacity切是默认容量16，而不是0</p>
<p>3．publicvirtualvoidTrimToSize();</p>
<p>将容量设置为ArrayList中元素的实际数量。<br />
如果不向列表中添加新元素，则此方法可用于最小化列表的内存系统开销。<br />
若要完全清除列表中的所有元素，请在调用TrimToSize之前调用Clear方法。截去空ArrayList会将ArrayList的容量设置为默认容量，而不是零。</p>
<p>ArrayListaList=newArrayList();<br />
aList.Add("a");<br />
aList.Add("b");<br />
aList.Add("c");<br />
aList.Add("d");<br />
aList.Add("e");//Count=5,Capacity=16,<br />
aList.TrimToSize();//Count=Capacity=5;</p>
<img src ="http://www.blogjava.net/smildlzj/aggbug/220574.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-08-07 10:03 <a href="http://www.blogjava.net/smildlzj/articles/220574.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#快速排序类</title><link>http://www.blogjava.net/smildlzj/articles/220561.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Thu, 07 Aug 2008 01:14:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/220561.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/220561.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/220561.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/220561.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/220561.html</trackback:ping><description><![CDATA[<table cellpadding="4" width="100%" border="0">
    <tbody>
        <tr>
            <td width="10" height="19"></td>
            <td height="19">
            <table cellspacing="3" cellpadding="3" width="100%" border="0">
                <tbody>
                    <tr>
                        <td><a href="http://www.csdn.net/">CSDN</a> - <a href="http://dev.csdn.net/">文档中心</a> - <font color="#003399"><a id="ArticleTitle1_ArticleTitle1_hlClass" href="http://dev.csdn.net/articlelist.aspx?c=14">.NET</a></font> </td>
                        <td align="right">阅读：<span id="ArticleTitle1_ArticleTitle1_lblReadCount">1338</span> &nbsp;&nbsp;评论： <span id="ArticleTitle1_ArticleTitle1_lblCommentCount">0</span> &nbsp;&nbsp; <a href="http://dev.csdn.net/Develop/article/28/58956.shtm#Comment">参与评论</a> </td>
                    </tr>
                </tbody>
            </table>
            <table cellspacing="3" cellpadding="3" width="100%" bgcolor="#eeeeee" border="0">
                <tbody>
                    <tr>
                        <td noWrap width="60" height="0"></td>
                        <td></td>
                    </tr>
                    <tr>
                        <td noWrap align="center" bgcolor="#003399" height="16"><font color="#ffffff">标题</font></td>
                        <td><strong>&nbsp; <span id="ArticleTitle1_ArticleTitle1_lblTitle">【算法】C#快速排序类</span></strong>&nbsp;&nbsp;&nbsp;&nbsp; 选择自 <a id="ArticleTitle1_ArticleTitle1_AuthorLink" href="http://dev.csdn.net/user/lovewangshu">lovewangshu</a> 的 Blog </td>
                    </tr>
                    <tr>
                        <td align="center" bgcolor="#003399" height="16"><font color="#ffffff">关键字</font></td>
                        <td width="500">&nbsp; <span id="ArticleTitle1_ArticleTitle1_lblKeywords">【算法】C#快速排序类</span></td>
                    </tr>
                    <tr>
                        <td align="center" bgcolor="#003399" height="16"><font color="#ffffff">出处</font></td>
                        <td>&nbsp; </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
        <tr>
            <td width="10"></td>
            <td><span id="ArticleContent1_ArticleContent1_lblContent">
            <div class="postbody">
            <p>快速排序的基本思想是基于分治策略的。对于输入的子序列ap..ar，如果规模足够小则直接进行排序，否则分三步处理： <br />
            <br />
            <strong>分解(Divide)：</strong>将输入的序列ap..ar划分成两个非空子序列ap..aq和aq+1..ar，使ap..aq中任一元素的值不大于aq+1..ar中任一元素的值。&nbsp; <br />
            <strong>递归求解(Conquer)：</strong>通过递归对p..aq和aq+1..ar进行排序。&nbsp; <br />
            <strong>合并(Merge)：</strong>由于对分解出的两个子序列的排序是就地进行的，所以在ap..aq和aq+1..ar都排好序后不需要执行任何计算ap..ar就已排好序。&nbsp; <br />
            这个解决流程是符合分治法的基本步骤的。因此，快速排序法是分治法的经典应用实例之一。 <br />
            <br />
            using System; </p>
            <p>namespace VcQuickSort <br />
            { <br />
            <span style="color: #008000">&nbsp;/// &lt;summary&gt; <br />
            &nbsp;/// ClassQuickSort 快速排序。<br />
            &nbsp;/// 范维肖<br />
            &nbsp;/// &lt;/summary&gt;</span> <br />
            &nbsp;public class QuickSort <br />
            &nbsp;{ <br />
            &nbsp;&nbsp;public QuickSort() <br />
            &nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;} </p>
            <p>&nbsp;&nbsp;private void Swap(ref int i,ref int j) <br />
            &nbsp;&nbsp;<span style="color: #008000">//swap two integer</span> <br />
            &nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;int t; <br />
            &nbsp;&nbsp;&nbsp;t=i; <br />
            &nbsp;&nbsp;&nbsp;i=j; <br />
            &nbsp;&nbsp;&nbsp;j=t; <br />
            &nbsp;&nbsp;} <br />
            &nbsp;&nbsp; <br />
            &nbsp;&nbsp;public void Sort(int [] list,int low,int high) <br />
            &nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;if(high&lt;=low) <br />
            &nbsp;&nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000">//only one element in array list <br />
            </span>&nbsp;&nbsp;&nbsp;<span style="color: #008000">&nbsp;//so it do not need sort</span> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;return; <br />
            &nbsp;&nbsp;&nbsp;} <br />
            &nbsp;&nbsp;&nbsp;else if (high==low+1) <br />
            &nbsp;&nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000">//means two elements in array list <br />
            &nbsp;&nbsp;&nbsp;&nbsp;//so we just compare them</span> <br />
            &nbsp;&nbsp;&nbsp;&nbsp;if(list[low]&gt;list[high]) <br />
            &nbsp;&nbsp;&nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #008000">//exchange them <br />
            </span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Swap(ref list[low],ref list[high]); <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;} <br />
            &nbsp;&nbsp;&nbsp;} <br />
            &nbsp;&nbsp;&nbsp;<span style="color: #008000">//more than 3 elements in the arrary list <br />
            &nbsp;&nbsp;&nbsp;//begin QuickSort</span> <br />
            &nbsp;&nbsp;&nbsp;myQuickSort(list,low,high); <br />
            &nbsp;&nbsp;} </p>
            <p>&nbsp;&nbsp;public void myQuickSort(int [] list,int low,int high) <br />
            &nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;if(low&lt;high) <br />
            &nbsp;&nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;&nbsp;int pivot=Partition(list,low,high); <br />
            &nbsp;&nbsp;&nbsp;&nbsp;myQuickSort(list,low,pivot-1); <br />
            &nbsp;&nbsp;&nbsp;&nbsp;myQuickSort(list,pivot+1,high); <br />
            &nbsp;&nbsp;&nbsp;} <br />
            &nbsp;&nbsp;} </p>
            <p>&nbsp;&nbsp;private int Partition(int [] list,int low,int high) <br />
            &nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;<span style="color: #008000">//get the pivot of the arrary list <br />
            </span>&nbsp;&nbsp;&nbsp;int pivot; <br />
            &nbsp;&nbsp;&nbsp;pivot=list[low]; <br />
            &nbsp;&nbsp;&nbsp;while(low&lt;high) <br />
            &nbsp;&nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;&nbsp;while(low&lt;high &amp;&amp; list[high]&gt;=pivot) <br />
            &nbsp;&nbsp;&nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;high--; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;} <br />
            &nbsp;&nbsp;&nbsp;&nbsp;if(low!=high) <br />
            &nbsp;&nbsp;&nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Swap(ref list[low],ref list[high]); <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;low++; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;} <br />
            &nbsp;&nbsp;&nbsp;&nbsp;while(low&lt;high &amp;&amp; list[low]&lt;=pivot) <br />
            &nbsp;&nbsp;&nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;low++; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;} <br />
            &nbsp;&nbsp;&nbsp;&nbsp;if(low!=high) <br />
            &nbsp;&nbsp;&nbsp;&nbsp;{ <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Swap(ref list[low],ref list[high]);&nbsp; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;high--; <br />
            &nbsp;&nbsp;&nbsp;&nbsp;} <br />
            &nbsp;&nbsp;&nbsp;} <br />
            &nbsp;&nbsp;&nbsp;return low; <br />
            &nbsp;&nbsp;} </p>
            <p>&nbsp;} <br />
            } </p>
            </div>
            </span><br />
            </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/smildlzj/aggbug/220561.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-08-07 09:14 <a href="http://www.blogjava.net/smildlzj/articles/220561.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在Visual C#中用ListView显示数据记录</title><link>http://www.blogjava.net/smildlzj/articles/216861.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Wed, 23 Jul 2008 05:26:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/216861.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/216861.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/216861.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/216861.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/216861.html</trackback:ping><description><![CDATA[<table width="600" align="center" bgcolor="#ffffff" border="0">
    <tbody>
        <tr>
            <td>using System ;<br />
            using System.Windows.Forms ;<br />
            using System.Drawing ;<br />
            using System.Data ;<br />
            using System.Data.OleDb ; <br />
            class MainForm : Form<br />
            { // 定义数据连接的字符串<br />
            private static string strConnect = "Provider = Microsoft.Jet.OLEDB.4.0 ; Data Source = " +<br />
            Application.StartupPath + "\\MY.MDB" ;<br />
            private OleDbConnection conConnection = new OleDbConnection ( strConnect ) ;<br />
            private ListView lv ;<br />
            public MainForm ( )<br />
            {<br />
            // 初始化Form<br />
            this.Left = 0 ;<br />
            this.Top = 0 ;<br />
            this.Text = "在ListView中显示数据库内容!" ;<br />
            <br />
            // 初始化ListView<br />
            lv = new ListView ( ) ;<br />
            lv.Left = 0 ;<br />
            lv.Top = 0 ;<br />
            lv.Width = 700 ;<br />
            lv.Height = this.ClientRectangle.Height ;<br />
            lv.GridLines = true ; file://显示各个记录的分隔线<br />
            lv.FullRowSelect = true ; file://要选择就是一行<br />
            lv.View = View.Details ; file://定义列表显示的方式<br />
            lv.Scrollable = true ; file://需要时候显示滚动条<br />
            lv.MultiSelect = false ; // 不可以多行选择<br />
            lv.HeaderStyle = ColumnHeaderStyle.Nonclickable ;<br />
            // 针对数据库的字段名称，建立与之适应显示表头<br />
            lv.Columns.Add ( "姓名" , 60 , HorizontalAlignment.Right ) ;<br />
            lv.Columns.Add ( "住宅电话" , 100 , HorizontalAlignment.Left ) ; <br />
            lv.Columns.Add ( "<a class="bluekey" href="http://product.yesky.com/office/" target="_blank">办公</a>电话" , 100 , HorizontalAlignment.Left ) ;<br />
            lv.Columns.Add ( "移动电话" , 100 , HorizontalAlignment.Left ) ;<br />
            lv.Columns.Add ( "居住地点" , 100 , HorizontalAlignment.Left ) ;<br />
            lv.Columns.Add ( "工作单位" , 100 , HorizontalAlignment.Left ) ;<br />
            lv.Columns.Add ( "电子邮件" , 100 , HorizontalAlignment.Left ) ;<br />
            lv.Visible = true ;<br />
            <br />
            OleDbDataReader reader ;<br />
            string strCommand = "SELECT * FROM Persons" ;<br />
            this.conConnection.Open ( ) ;// 打开数据连接<br />
            OleDbCommand cmd = new OleDbCommand ( strCommand , conConnection ) ;<br />
            reader = cmd.ExecuteReader ( ) ;//获得数据集<br />
            // 不断往列表中添加数据记录<br />
            while ( reader.Read ( ) )<br />
            {<br />
            ListViewItem li = new ListViewItem ( ) ;<br />
            li.SubItems.Clear ( ) ;<br />
            li.SubItems[0].Text = reader["name"].ToString ( ) ;<br />
            li.SubItems.Add ( reader["HomePhone"].ToString ( ) ) ;<br />
            li.SubItems.Add ( reader["WorkPhone"].ToString ( ) ) ;<br />
            li.SubItems.Add ( reader["MobilePhone"].ToString ( ) ) ;<br />
            li.SubItems.Add ( reader["City"].ToString ( ) ) ;<br />
            li.SubItems.Add ( reader["Address"].ToString ( ) ) ;<br />
            li.SubItems.Add ( reader["Email"].ToString ( ) ) ;<br />
            lv.Items.Add ( li ) ;<br />
            }<br />
            reader.Close ( ) ; // 关闭数据集<br />
            // 在Form中添加此列表<br />
            this.Controls.Add ( lv ) ;<br />
            // 关闭Form的时候，同时也关闭数据连接<br />
            this.Closed+=new EventHandler ( this_Closed ) ; <br />
            }<br />
            protected void this_Closed ( object sender , EventArgs eArgs )<br />
            {<br />
            this.conConnection.Close ( ) ; file://关闭数据连接<br />
            }<br />
            public static void Main ( )<br />
            {<br />
            Application.Run ( new MainForm ( ) ) ;<br />
            }<br />
            }<br />
            </td>
        </tr>
    </tbody>
</table>
<br />
　　在成功编译了上面源程序代码以后，在同一目录下建立一个Acess 2000的数据库，命名为MY.MDB，然后在其中建立一张数据表，字段如下：name，HomePhone，WorkPhone，MobilePhone，City，Address，Email。此时运行编译后的程序就可以得到如下运行界面：<br />
<br />
<table width="600" align="center" border="0">
    <tbody>
        <tr>
            <td><img height="239" src="http://www.yesky.com/SoftChannel/72342380468109312/20011102/jt-2001-11-2-image002.jpg" width="554"  alt="" /><br />
            　　　　　　　　　图01：用ListView显示数据记录 </td>
        </tr>
    </tbody>
</table>
<img src ="http://www.blogjava.net/smildlzj/aggbug/216861.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-07-23 13:26 <a href="http://www.blogjava.net/smildlzj/articles/216861.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C#获取当前路径</title><link>http://www.blogjava.net/smildlzj/articles/216622.html</link><dc:creator>smildlzj</dc:creator><author>smildlzj</author><pubDate>Tue, 22 Jul 2008 07:24:00 GMT</pubDate><guid>http://www.blogjava.net/smildlzj/articles/216622.html</guid><wfw:comment>http://www.blogjava.net/smildlzj/comments/216622.html</wfw:comment><comments>http://www.blogjava.net/smildlzj/articles/216622.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/smildlzj/comments/commentRss/216622.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/smildlzj/services/trackbacks/216622.html</trackback:ping><description><![CDATA[<font color="#0000ff"><strong>
<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"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;str1&nbsp;</span><span style="color: #000000">=</span><span style="color: #000000">Process.GetCurrentProcess().MainModule.FileName;</span><span style="color: #008000">//</span><span style="color: #008000">可获得当前执行的exe的文件名。&nbsp;&nbsp;</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;str2</span><span style="color: #000000">=</span><span style="color: #000000">Environment.CurrentDirectory;</span><span style="color: #008000">//</span><span style="color: #008000">获取和设置当前目录（即该进程从中启动的目录）的完全限定路径。<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span></div>
<p dir="ltr" style="text-indent: 2em">//备注 按照定义，如果该进程在本地或网络驱动器的根目录中启动，则此属性的值为驱动器名称后跟一个尾部反斜杠（如&#8220;C:\&#8221;）。如果该进程在子目录中启动，则此属性的值为不带尾部反斜杠的驱动器和子目录路径（如&#8220;C:\mySubDirectory&#8221;）。</p>
<br />
<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"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;str3</span><span style="color: #000000">=</span><span style="color: #000000">Directory.GetCurrentDirectory();</span><span style="color: #008000">//</span><span style="color: #008000">获取应用程序的当前工作目录。</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;str4</span><span style="color: #000000">=</span><span style="color: #000000">AppDomain.CurrentDomain.BaseDirectory;</span><span style="color: #008000">//</span><span style="color: #008000">获取基目录，它由程序集冲突解决程序用来探测程序集。</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;str5</span><span style="color: #000000">=</span><span style="color: #000000">Application.StartupPath;</span><span style="color: #008000">//</span><span style="color: #008000">获取启动了应用程序的可执行文件的路径，不包括可执行文件的名称。</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;str6</span><span style="color: #000000">=</span><span style="color: #000000">Application.ExecutablePath;</span><span style="color: #008000">//</span><span style="color: #008000">获取启动了应用程序的可执行文件的路径，包括可执行文件的名称。</span><span style="color: #008000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #000000"><br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span><span style="color: #0000ff">string</span><span style="color: #000000">&nbsp;str7</span><span style="color: #000000">=</span><span style="color: #000000">AppDomain.CurrentDomain.SetupInformation.ApplicationBase;</span><span style="color: #008000">//</span><span style="color: #008000">获取或设置包含该应用程序的目录的名称。<br />
<img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align="top" /></span></div>
<br />
<p style="text-indent: 2em">1.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName</p>
<p style="text-indent: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获取模块的完整路径。</p>
<p style="text-indent: 2em">2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Environment.CurrentDirectory</p>
<p style="text-indent: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获取和设置当前目录(该进程从中启动的目录)的完全限定目录。</p>
<p style="text-indent: 2em">3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.IO.Directory.GetCurrentDirectory() </p>
<p style="text-indent: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获取应用程序的当前工作目录。这个不一定是程序从中启动的目录啊，有可能程序放在C:\www里,这个函数有可能返回C:\Documents and Settings\ZYB\,或者C:\Program Files\Adobe\,有时不一定返回什么东东，我也搞不懂了。</p>
<p style="text-indent: 2em">4.&nbsp;&nbsp;&nbsp;&nbsp; System.AppDomain.CurrentDomain.BaseDirectory</p>
<p style="text-indent: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获取程序的基目录。</p>
<p style="text-indent: 2em">5.&nbsp;&nbsp;&nbsp;&nbsp; System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase</p>
<p style="text-indent: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获取和设置包括该应用程序的目录的名称。</p>
<p style="text-indent: 2em">6.&nbsp;&nbsp;&nbsp;&nbsp; System.Windows.Forms.Application.StartupPath </p>
<p style="text-indent: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获取启动了应用程序的可执行文件的路径。效果和2、5一样。只是5返回的字符串后面多了一个"\"而已</p>
<p style="text-indent: 2em">7.&nbsp;&nbsp;&nbsp;&nbsp; System.Windows.Forms.Application.ExecutablePath</p>
<p style="text-indent: 2em">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获取启动了应用程序的可执行文件的路径及文件名，效果和1一样。 </p>
<p style="text-indent: 2em">对于Windows程序 和Web 应用程序来说,他们运行的路径是不一样的,所以关键是判断当前运行的程序是哪种程序.于是我们可以使用如下的代码 </p>
<p style="text-indent: 2em"><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" border="0" /> string path = "";</p>
<p style="text-indent: 2em"><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" border="0" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if (System.Environment.CurrentDirectory == AppDomain.CurrentDomain.BaseDirectory)//Windows应用程序则相等</p>
<p style="text-indent: 2em"><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" border="0" /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" border="0" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...{</p>
<p style="text-indent: 2em"><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" border="0" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; path = AppDomain.CurrentDomain.BaseDirectory;</p>
<p style="text-indent: 2em"><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" border="0" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="text-indent: 2em"><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" border="0" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;else</p>
<p style="text-indent: 2em"><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockStart.gif" border="0" /><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ContractedBlock.gif" border="0" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...{</p>
<p style="text-indent: 2em"><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/InBlock.gif" border="0" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; path = AppDomain.CurrentDomain.BaseDirectory + "Bin\";</p>
<p style="text-indent: 2em"><img alt="" src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/ExpandedBlockEnd.gif" border="0" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p style="text-indent: 2em">这样如果我们写了一个类库,类库中用到了Assembly.LoadFrom,由于是通用类库,所以可能用到Windows程序中也可能用到Web中,那么用上面的代码就很方便了.</p>
<p style="text-indent: 2em">1、Server.MapPath</p>
<p style="text-indent: 2em">2、System.Windows.Forms.StartupPath</p>
<p style="text-indent: 2em">3、Type.Assembly.Location</p>
<p style="text-indent: 2em">方法2可以应用于控制台应用程序，WinForm应用程序，Windows服务，方法1可以应用于Web应用程序，方法3都可以应用。</p>
<p style="text-indent: 2em">但方法3是加载应用程序的路径。如果是Web应用程序，取得的路径是C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\Temporary ASP.NET Files目录。所以Web项目还是使用Server.MapPath吧。否则建议使用方法2。如果自己新建类库。可以加入对System.Windows.Forms.StartupPath的引用后使用。</p>
</strong></font>
<img src ="http://www.blogjava.net/smildlzj/aggbug/216622.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/smildlzj/" target="_blank">smildlzj</a> 2008-07-22 15:24 <a href="http://www.blogjava.net/smildlzj/articles/216622.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>