Loading...

当前位置:资讯中心主页 >NET编程 >文章内容

  • 实现.net应用程式的自动更新 _asp.net技巧
  • 来源:作者: 发布时间:2007-12-24 17:05:52
    • 域名注册

    • 域名惊喜价格 cn域名1元注册
    • com域名39.9

      虚拟主机

    • 主机按月支付,低至19元/月
    • 超大流量,可开子站点

      VPS主机

    • 特惠VPS168元/月,4-8M独享带宽保证
    • 独立操作系统,无限开站点

    应用程式更新的方法一般有两种:一是通知用户(比如发E-mail),让用户到指定的网站地址下载更新的程式;二是将更新的职责从用户那边转移到应用程式自身,由应用程式自身取代用户获取并安装一个软件的更新,客户端应用程式自身负责从一个已知服务器下载并安装更新,用户唯一需要进行干预的是决定是否愿意目前或以后安装新的更新。显然,后者比前者更友好。你目前能看到类似后一种方法的实际产品,比如视窗系统 XP和Microsoft Money。本文所介绍的.NET应用程式更新组件就能提供类似的功能。

      一、.NET应用程式更新组件介绍

      .NET 应用程式更新组件AppUpdater 是使用.NET框架研发的。尽管AppUpdater 不是微软的产品,不过只要你在VS.NET工具栏中添加了该组件,就能象使用其他组件相同通过拖拽的方式将该组件从工具栏中拖放到你的应用程式中,并设置一些属性(比如获取更新的位置、频率等)之后就能使得你的客户端应用程式具有自动更新的功能。

      二、工作原理

      要深入理解.NET客户端应用程式更新组件的工作原理,需要仔细研究一下实现客户端应用程式更新有那些必须要做的事情。第一步需要做的是检查是否有更新;当发现有更新时,开始第二步工作??下载更新;当更新下载完成时,进行是最后一步的工作??实现更新。

      (一) 为更新做检查

      作为研发者,首先你得告诉应用程式到什么地方去做更新检查,否则他岂不是要大海捞针?其次,确定何时做更新检查。不可能用户每次一运行客户端程式,而他就在后台不停的进行更新检查,那多浪费资源!最后更有一项重要的事情需要解决,那就是怎么进行更新检查。.NET应用程式更新组件使用HTTP进行通讯,这就允许客户端应用程式穿透防火墙来进行更新。并且进行更新检查所需要的地址就成了已知的Web服务器的一个URL地址,第一个问题顺利解决。

      .NET应用程式更新组件在组件生成的基础上产生一个线程,该线程负责进行更新检查。该线程在大多数时间处于休眠状态,但会在设置好的间隔苏醒并实现一次更新检查。应用程式为新的更新所做的检查的频率依赖于各应用自身。进行更新检查的间隔常用值的范围一般是从一个小时到几天。这种轮询的基本方法并不适合于所有情况。比如Microsoft Money只是在用户让他去进行更新检查时他才去检查。在这种情况下,更新轮询线程可被禁用。

      通过用命令调用更新组件的CheckForUpdate()方法来实现更新检查。

      关于怎么进行更新检查的方法有这样几种:

      方法一:直接文件检查??使用HTTP来比较服务器和客户端应用程式的最后的修改日期/时间戳是否一致。如果服务器上有更新的文件,客户端就知道能更新自己了。对于Web浏览器来讲,也是同样的道理,他知道是否需要重新下载一个html页面或图片或是否能
    重复使用先前已下载的。当应用程式有一个新的版本可用时,管理员简单地拷贝一个更新的版本来覆盖Web服务器上的旧版本。这种方法的问题在于更新不是自动进行,由此会出现潜在的失败可能。比如,如果管理员正在更新Web服务器上的应用程式版本,同时有个客户正在下载更新之前的版本,那么这个客户的计算机上就会既存在更新之前的一些文件,也存在更新之后新版本的一些文件。基于上述原因,对于重要的应用程式不提倡使用直接文件检查来更新。

      方法二:显式检查??在服务器上使用一个显式的设置文件。一个可和.NET应用程式更新组件使用的有效服务器显式文件大致是这个样子:..

    <VersionConfig>
    <AvailableVersion>1.0.0.0</AvailableVersion>
    <ApplicationUrl>http://localhost/demos/selfupdate/V1/</
    ApplicationUrl>
    </VersionConfig>

      AvailableVersion指定最新的可用程式集的版本号。ApplicationURL属性指定该版本应用程式所在的URL地址。当管理员想要更新客户端应用程式时,他们就会将应用程式的新版本拷贝到Web服务器上并且适当地修改服务器显式文件。客户端自身会探测到服务器显式文件已被修改,然后下载显式文件。客户端随后比较显式文件中指定的程式集版本号和应用程式EXE文件的版本号。如果服务器显式文件中的可用版本号较新,应用程式就知道需要更新了。这种方法对大多数应用程式而言是推荐使用的方法。

      方法三:XML Web Service 检查??XML WebServices提供一种更高级的更新检查方式。比如,假定你希望在进行更新你的其他用户之前先对一系列早期用户进行更新,如果客户端应用程式调用一个XML WebService来检查一项更新是否可用,那个XML Web Service还能在数据库中查询该用户并判断该用户是否是早期用户。如果他们是早期用户,XML Web Service就返回一个值表示更新可用。如果不是,Web Service就返回一个值表示更新不可用。但本文介绍的.NET应用程式更新组件并不提供直接的XML Web Service支持。

      要采用XML Web Service来进行更新检查,首先建立 XML Web Service并挂钩一个OnCheckForUpdate事件。这样就允许你自己的自定义检查代替轮询者线程更新检查。OnCheckForUpdate事件有一个返回值,该值表示更新是否被检测到。

      (二) 下载更新

      当.NET应用程式更新组件检测到一项新的更新可用时他会自动启动另一个线程并开始异步后台下载更新。

      下载使用HTTP-DAV来完成。DAV 是一种扩展的HTTP,.. 他提供诸如目录和文件枚举这样的功能。一项完整的下载过程始于指定一个URL。采用URL来下载依赖于完成更新检查所使用的方式。比如,如果使用服务器显式文件,下载更新所用的URL通过在服务器显式文件 中的ApplicationURL属性指定。

      更新下载显然需要一定的健壮性。在下载和更新之后让客户端应用程式处于所有不稳定的状态是不可接受的。下载过程中所有问题可能都会出现:更新文件所属的Web 服务器可能会宕机,客户端机器可能会崩溃,或因为某种原因用户只是简单的关闭了应用程式。由于
    应用程式正在进行下载,如果他被关闭的话,下载将会停止。一种可选的设计方案是使用独立的系统服务来进行应用程式的下载和更新。使用系统服务,即便应用程式自身没有在运行,更新下载也会继续。实际上,视窗系统 XP就有一种称之为BITS的内建的下载服务,其目的即在此。BITS是视窗系统 XP用来对视窗系统自身进行下载更新的。想查看更多关于BITS的信息,请参阅http://msdn.microsoft.com/library/en-us/dnwxp/html/WinXP_BITS.asp。在.NET应用程式更新组件中没有使用这种服务,因此他能在不支持系统服务的视窗系统 9x中使用。

      (三) 实现更新

      .NET应用程式更新组件通过将下载和更新过程分为独立的两个阶段来获得健壮性。当每一阶段都完成时,在位于客户端应用程式目录下的一个更新显式文件(manifest file)中记载下来。如果下载或更新所有一个阶段中的过程被打断,他就会在下一次应用程式启动时从上一次完成的断点继续原来的工作。每一阶段都能重新运行,因此如果在一个阶段中间出现失败,重新运行该阶段就能成功。如果有错误发生,比如在下载过程中和服务器的链接丢失,.NET更新组件将会在稍后重试。如果报告了非常多的错误(例如web服务器再也没有回到在线状态),下载和更新将会被放弃并且报告出错误。

      我们的第一个方法是简单地启动一个独立的进程来实现更新。这个独立的进程将会首先关闭应用程式进程,实现更新(因为这时候已被解锁),重启应用程式进程并且在完成之后关闭自己。因此,这种设计存在三个基本的问题:

      . 在某些情况下他不起作用。在更新应用程式时,更新进程关闭原始的应用程式进程,更新进程自身也要被关闭,因此也就不会实现更新。

      . 我们希望能够自动更新所有要实现更新的代码。我们希望自动安装修补的能力不仅仅发生在应用程式上,而且.NET应用程式更新组件自身也能。使用这种模式,我们不能更新实现更新的进程。

      . 强制用户关闭应用程式并在使用过程中等待,这是非常不礼貌的。

      用来实现应用程式更新的最后一种方法是使用.NET框架并行程式集模式。作为试图更新应用程式自身的替代方案,生成一个比目前存在版本新的应用程式版本。

      新版本能通过合并目前现存的应用程式目录和下载的更新版本来生成。当新版本完成时,用户在下次重新打开应用程式时会自动使用新版本。原始应用程式的拷贝就能被移除了。棘手问题是弄清在某个指定时刻哪个版本该被载入。我们介绍一个名称为Appstart的应用程
    序。Appstart是进入你应用程式的入口点,使用这种模式,你的应用程式目录看起来是这个样子:..

    --> Program Files

    --> MyApp

    --> Appstart.exe

    --> Appstart.config

    --> V1 Folder

    --> MyApp.exe

    --> V1.1 Folder

    --> MyApp.exe

      要运行你的应用程式,你通常是启动Appstart.exe。如果你想在桌面上有个快捷键,那个快捷键必须应该指向Appstart而不是直接指向应用程式(注意,你能重命名AppStart.exe 为所有你想要的名字,例如YourApp.exe)Appstart.exe是个非常简单的程式,他读取Appstart.config文件并且载入指定的应用程式。一个有效Appstart.config文件如下所示:

    <Config>
     <AppFolderName>V1 Folder</AppFolderName>
     <AppExeName>MyApp.exe</AppExeName>
     <AppLaunchMode>appdomain</AppLaunchMode>
    </Config>

     

      AppFolderName指定包含当前要运行的应用程式版本的子目录。AppExeName包含在那个目录下要载入的exe文件名。当一个应用程式更新完成时,最后一步就是修改AppFolderName的值为指向应用程式的新版本。这样,下次用户运行应用程式时,就会运行新的应用程式更新后的版本。AppLaunchMode指定怎么加载应用程式。有两种方式加载应用程式:第一种方式是使用AppDomains。AppDomains是.NET框架公
    用语言运行时的特性,也是独立的逻辑单元和管理对象。公用语言运行时允许每个进程中存在多个应用程式域。这样Appstart.exe就能够在独立的AppDomain中同时却是相同的AppStart.exe进程中加载你的应用程式。尽管事实是两个不同的exe 程式在运行(即Appstart.exe和MyApp.exe),但只有一个进程在使用。对于大多数应用程式AppDomains会工作得非常好,当然,在一个独立的AppDomain中运行和在一个独立
    的进程中运行还是有些细微差别的。在这种情况下,AppLaunchMode能设置为“process”,这样就会使应用程式在独立进程中加载。

      一旦Appstart启动应用程式,他就会进入休眠状态等待应用程式终止。一旦应用程式终止,Appstart也会关闭。
    三、实例演练

      前面我们讨论了.NET应用程式更新是怎么工作的,目前我们来将他应用在实例中。

      第一步:建立应用程式来进行更新

      1. 使用VS.NET生成一个新的视窗系统应用项目,命名为"SampleApp"。

      2. 给窗体一个你选择的有趣的背景色。我们将使用背景色来和后面更新的版本差别。

      3. 目前让我们给这个应用程式增加一个细微的功能,首先给你的窗体增加一个按钮。压缩文件中包含一个拥有简单视窗系统窗体的程式集。给压缩文件中Samples\SampleApp\SimpleForm 程式集增加一个引用。然后在你的按钮事件句柄中添加两行代码:

     

    ..
    SimpleForm.Form1 F = new SimpleForm.Form1();
    F.Show();

     

      4. 将你的build标志从debug转换为RELEASE。这将允许我们避免稍后当我们生成一个应用程式的新版本而同时原始拷贝正在运行产生的pdb文件锁定问题。生成并测试你的应用程式。

      第二步:添加.NET应用程式更新组件

      1. 在VS.NET工具栏的组件标签上,右击选择“自定义工具栏”。选择“.NET框架组件”标签。点“浏览”并选择位于压缩文件中AppUpdater 项目下的AppUpdater.dll,单击OK。

      2. 一个AppUpdater图标目前应该出目前工具栏的组件列表的底部。将AppUpdater 组件拖放到SampleApp窗体上。一个名为appUpdater1的.NET应用程式更新组件的实例会出目前窗体的底部。

      第三步:设置.NET应用程式更新组件

      在这一步我们将设置.NET应用程式更新组件。注意这个示例你只需改动最开始的四个属性,其他的采用默认值。

      AppUpdater属性:这是.NET Application应用程式更新的核心,对于本程式需要做以下设置:

      (1)AutoFileLoad:这个控制后面要描述的命令下载特征,目前将他设置为true。

      (2)ChangeDetectionMode:该枚举决定怎么为更新进行检查。在该例中,我们将使用一个服务器显式检查,因此将这个值设置为“ServerManifestCheck ”。

      (3)ShowDefaultUI: .NET 应用程式更新组件具有一系列用户界面来通知用户一些事件,比如有一个新的更新能使用了或在更新期间发生错误等。这种用户界面能通过设置默认的用户界面为无效而用自定义应用程式指定的用户界面来代替他,挂钩适当的事件(比如
    OnUpdateComplete)并弹出自定义用户界面。对于该例我们将使用默认的用户界面,因此将这个值设置为true 。

      (4)UpdateUrl :UpdateUrl 是决定更新程式到何处去寻找更新的。在该例中我们使用一个服务器显式文件来检查更新,因此这个属性应当设置为服务器显式文件的URL 。

      在该例中将他设置为:http://yourWebserver/SampleApp_ServerSetup/UpdateVersion.xml。请用你的Web 服务器名
    称来代替“yourWebserver ”。

      Downloader 属性:AppUpdater 组件有两个子组件。第一个称之为Downloader,他控制组件的下载和Poller属性:AppUpdater的第二个子组件是Poller,Poller控制更新检查。

      (1)AutoStart:布尔值,在应用程式启动时控制Poller 是否应当开始轮询或他是否应当等待直到有计划的更新查询开始。

      (2)DownloadOnDetection:布尔值,控制Poller 在一个新的更新发现时是否即时开始下载更新,或是否通过调用DownloadUdpate() 方法开始显式下载。

      (3)InitialPollInterval:应用程式启动后在第一次执行更新检查前等待的秒数。

      (4)PollInterval:第一次更新检查之后,PollInterval 控制后续每次更新检查之间间隔的秒数,注意:默认为每30 秒进
    行一次检查;显然,你会希望你的应用程式减少更新检查的频率。

      所有这一切完成之后,你的属性表格看起来应当是下面这个样子:

     


    Samples\SampleApp\SampleApp_Complete目录包含应用程式正确安装的一个版本。

     

      安装:

      (1)DownloadRetryAttempts:在下载期间如果有错误发生(比如Web 服务器宕机)downloader 会稍后重试。这个属性控制downloader 认为是完全的应用程式更新错误之前重试网络请求的次数。

      (2)SecondsBeteweenDownloadRety:重试网络请求之前等待的秒数。

      (3)UpdateRetryAttempts: 在更新期间如果发生严重错误,(例如downloader 超过了试图重试的次数),就会产生一个应用程式更新错误。默认的,将会停止试图更新。不过在应用程式下一次启动时会试图恢复(比如更新Web 服务器可能会宕机好几天)。这个属性控制试图更新的次数。如果超过这个值,updater 就会取消更新,重置他的状态并返回更新检查。

      (4)ValidateAssemblies: 这个属性控制下载程式集有效完成的级别。更多信息参见这篇文章的安全一节。

      第四步:生成并在客户端部署应用程式V1版本。

      在SampleApp项目中,打开AssemblyInfo.cs文件。将AssemblyVersion的值从“1.0”修改为“1.0.0.0”。这会引起在生成程式集时获得值为“1.0.0.0”.. 的标记,该标记代替VS.NET通常指定为递增的值。

      1. 生成应用程式。

      2.从压缩文件中将Samples\SampleApp\SampleApp_ClientSetup目录拷贝到你的本地机器上。要注意此目录已包含了AppStart.exe。AppStart.config已设置为指向1.0.0.0目录并且启动SampleApp.exe。

      从SampleApp的release目录下拷贝SampleApp(Appupdater.dll,SimpleForm.dll和SampleApp.exe)

      到客户端SampleApp_ClientSetup\1.0.0.0目录下。至此,一个功能完整的应用程式版本已被“安装”到了客户端,能通过运行AppStart.exe来执行。

      第五步:安装Web服务器

      在这一步我们将安装Web服务器以提供更新轮询功能。.NET应用程式更新组件使用HTTP-DAV来下载应用程式更新,因此需要一个支持HTTP-DAV的Web服务器。视窗系统 2000上的IIS5.0和更新的操作系统都支持HTTP-DAV。

      1.将Samples/SampleApp_ServerSetup目录拷贝到你的Web服务器上的wwwroot目录下。

      2. 将SampleApp的V1版本拷贝到Web服务器的1.0.0.0目录。

      3. 在Web服务器上为SampleApp_ServerSetup目录启用IIS的“目录浏览”权限。

      第六步:自动更新应用程式

      OK,.. 目前是时间来通过自动安装一个新版本来看看以上这些艰苦工作的结果了。

      1. 如果你部署在客户端的SampleApp版本没有运行,加载他让他运行,记得使用AppStart.exe。

      2. 回到VS.NET并在SampleApp窗体中做一些能被注意到的修改(比如修改背景色)。

      3. 将AssemblyInfo.cs的版本信息改为2.0.0.0。

      4. 重新生成。

      5. 回到Web服务器并生成一个和1.0.0.0目录同等的目录2.0.0.0。从release生成目录下将新版本应用程式拷贝到Web服务器上新建的2.0.0.0目录下。

      6.打开UpdateVersion.xml 并修改AvailableVersion为2.0.0.0。修改ApplicationURL为指向新的2.0.0.0路径。

      7. 保存对UpdateVersion.xml所做的修改。

      一旦你保存了新的UpdateVersion.xml,在30秒之内,运行中的SampleApp拷贝将会探测到新的可用版本。
    四、按需安装、安全、可扩展性及调试

      (一)按需求安装

      所谓按需求安装,指只有主可执行程式被显式安装到客户机上。应用程式剩下的部分能根据基本需要自动下载和安装。

      通过.NET应用程式更新组件的AutoFileLoad属性来启动按需求安装。你必须仔细考虑在你的应用程式中程式集边界所处的位置及什么动作会引起程式集被下载。由于程式集的下载涉及到网络输入输出,因此下载所花费的时间是可变的。在程式集下载期间,应用程式会被冻结等待程式集下载完成。

      (二)部署安全

      自动安装应用程式更新的能力具有非常多好处,但他也伴随着一些潜在的危险。当你使得安装更新变得简单时,如果不小心,你也可能使得安装恶意代码变得简单。有两种危险,第一种危险是有人会用自己的Web服务器欺骗用来部署更新的Web服务器。他们可能会利用那台Web服务器在你的应用程式路径安装一个病毒程式。阻止欺骗或其他通过网络进行的不正当干预的最简单的方法是使用HTTPS。要和.NET应用程式更新组件一起使用HTTPS,能简单地用HTTPS URLs来代替HTTP URLs。当然,HTTPS 不是银弹。使用HTTPS有两个问题,第一是可伸缩性。使用HTTPS需要服务器加密所有从Web服务器上下载的文件。如果一个应用程式的更新文件非常大,加密更新文件的代价会使服务器的负担过重。使用HTTPS的另一个问题是他对第二种安全危险毫无益处。第二种危险是黑客既可能从内部也可能从外部来攻击你的服务器。一旦攻击成功,则有可能意味着成百上千的客户端也通过自动更新遭受连累,这种情况将是灾难性的。

      为解决这个问题,.NET应用程式更新组件使用给.NET程式集添加强名称的特性来验证所下载的程式集。如果.NET应用程式更新组件检测到下载期间一个程式集不是使用你的密钥签名的,下载就会取消。这意味着只有拥有你的应用程式私钥的人才能够建立可自动部署的更新文件。

      要验证程式集有效,.NET应用程式更新组件验证你当前安装的应用程式可执行程式的公钥和下载的更新的公钥是否匹配。如果两个程式集以相同且保密的私钥签名,那么嵌入的公钥也就相同。因为被CLR加载的程式集为了验证他的公钥,CLR计算他正常的哈希值检查来确保程式集实际上就是真正的程式集而不是被做了手脚的程式集。为了能够在下载时验证,能给你所有的应用程式集添加强名称并将.NET应用程式更新组件的ValidateAssemblies属性设置为true。

      在下载时进行程式集验证会起非常大的作用,但实际上,应用程式会经常有不同私钥签名的组件。比如,你的应用程式可能有两个文件:使用你的私钥签名的可执行程式集和另一个包含你购买的应用在你的应用程式中的第三方图表控件的dll程式集。第三方程式集可能使
    用第三方而不是你自己的私钥来签名。使情况变得更为复杂的是,在你的应用程式中用来签名程式集的有效私钥的设置随着版本号的改动可能会发生变化。你该怎么自动更新那些应用的类型?为解决这个问题,你能在你的应用程式中生成一个包含有效公钥的列表的程式集。将该程式集使用应用程式的主私钥(应用程式的exe文件签名的密钥)签名并把该程式集放到Web服务器上和应用程式更新文件一起的目录下。在更新下载过程开始之前,.NET应用程式更新组件将会检查Web服务器上应用程式更新目录下一个名为"AppUpdaterKeys.dll"的的程式集。如果存在,该程式集就会被下载。该程式集会被拿来和主应用程式的公钥对比验证。如果签名有效,密钥列表会被提取出来。从此之后,所有处于该列表中的密钥会被认为是更新文件的有效签名。

      有关安全方面推荐的方法是使用HTTPS URLs来实现更新检查。这会提供第一级别的欺骗保护。对于更新下载,最佳不要使用HTTPS RLs以避免使你Web服务器的负荷过重。而是给你的应用程式的程式集添加强名称并使用程式集验证特性。

      (三)可扩展性

      在这篇文章前面讲过的示例中我们简单地通过拖放一个组件到应用程式中并设置一些属性来实现自动部署。

      虽然这在许多应用程式中工作的非常好,但在一些应用程式中会需要高级别的控制,这只能通过写代码来获得。我们能编写自己的代码来替换掉.NET应用程式更新组件标准过程,使用重写的CheckForUpdate()和ApplyUpdate()方法来制定检查和更新行为。

      (四)调试

      这一节将指出一些最佳选择的调试选项,及描述使用该组件的用户大多数常见的问题。

      .NET应用程式更新器在和AppStart.exe相同的目录下生成一个名为AppUpdate.log的隐藏日志文件。

      所有的更新成功和失败信息都记录在该日志中。当有一个特别的客户端不能成功更新时日志文件会特别有用。

      你能使用日志来判断在什么时间及是怎么更新失败的。另外,.NET应用程式更新组件使用.NET框架的Debug类来输出大量有用的信息。如果你在调试器中运行你的应用程式,你会在输出窗口中看到这些信息。你能循着.NET应用程式更新器的记录重点观察并找到出
    问题的地方。

      如果由于某种原因,你无法使得.NET应用程式更新器工作,在你深入调试之前请确定以下几点,你遇见的问题非常可能就是如下之一:..

      . 你是否将IIS目录浏览给打开了?如果没有,更新器将不会下载安装所有文件。

      . 你是否正确的部署了一切并正确设置了URL?

      . 如果你的应用程式安装在program files目录下,确定你是该机的终极管理员或终极用户吗?如果不是,你将不会有写权限来更新应用程式。

      . 你是在应用程式的主用户界面线程中生成AppUpdater对象的吗?如果不是,更新器将不能显示用户界面并且在激发事件回到用户界面时失败。

      . 是否更新成功,但应用程式使用新的更新自动重启时失败?.NET 应用程式更新组件试图通过调用Application.Exit方法来退出应用程式。然而,该方法并不能确保关闭一个应用程式。如果你生成并遗留了独立的线程在运行,该方法就无法关闭进程。确保所有线程终止的解决的方案是通过调用Application.OnExit事件,或挂钩.NET应用程式更新器的OnUpdateComplete事件并自己处理关闭。

      五、总结

      客户端应用程式部署方便是.NET框架第一个版本的重要的目标。用.NET框架建立解决部署问题的客户端应用程式是一种非常好的技术。部署方便仍然是未来.NET框架新版本的一个重要目标。就方案而言,这里描述的.NET应用程式更新组件代表了我们的一些想法,在未来版本的.NET框架中我们将能直接使用。然而,在那个时候到来之前的这段期间,.NET应用程式更新组件不失为开始建立自动更新应用程式的一种重要的方法

    出自:csdn,在天极上看到的,还没仔细研究,留做以后参考

     


  • 以上内容由 华夏名网 搜集整理,如转载请注明原文出处,并保留这一部分内容。

      “华夏名网” http://www.sudu.cn 和 http://www.bigwww.com 是成都飞数科技有限公司的网络服务品牌,专业经营虚拟主机,域名注册,VPS,服务器租用业务。公司创建于2002年,经过6年的高速发展,“华夏名网”已经成为我国一家知名的互联网服务提供商,被国外权威机构webhosting.info评价为25大IDC服务商之一。

    华夏名网网址导航: 虚拟主机 双线主机 主机 域名注册 cn域名 域名 服务器租用 酷睿服务器 vps vps主机

  • (阅读次数:364)
  • 上一篇: .net下正则表达式应用的四个示例_asp.net技巧    下一篇: 使用asp.net进行多关键字查询的例子_asp.net技巧
  • [收藏] [推荐] [评论] [打印本页] [返回上一页][关闭窗口]
  • 昵称: (为空则显示guest)
  • 评论分数: ★ ★ ★★★ ★★★★ ★★★★★
  • 评论内容:(不能超过250字,需审核后才会公布,请自觉遵守互联网相关政策法规。