<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom"><title type="text">博客园_eaglet</title><subtitle type="text">本博专注于基于微软技术的搜索相关技术</subtitle><id>http://feed.cnblogs.com/blog/u/26415/rss</id><updated>2012-05-23T06:41:06Z</updated><author><name>eaglet</name><uri>http://www.cnblogs.com/eaglet/</uri></author><generator>feed.cnblogs.com</generator><link rel="alternate" type="text/html" href="http://www.cnblogs.com/eaglet/"/><link rel="self" type="application/atom+xml" href="http://feed.cnblogs.com/blog/u/26415/rss"/><entry><id>http://www.cnblogs.com/eaglet/archive/2012/05/23/2514769.html</id><title type="text">获取ALL USER 的特殊目录的类</title><summary type="text">.net 框架中提供的 System.Environment.GetFolderPath 只能获取当前用户的特殊目录，无法获取所有用户的特殊目录。我做了一个类，可以帮助获取所有用户的特殊目录。网上有很多相关的文章用的API是有些过时了，这篇文章中的API可以适用于windows 2000 后的任何操作系统。</summary><published>2012-05-23T06:39:00Z</published><updated>2012-05-23T06:39:00Z</updated><author><name>eaglet</name><uri>http://www.cnblogs.com/eaglet/</uri></author><link rel="alternate" href="http://www.cnblogs.com/eaglet/archive/2012/05/23/2514769.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/eaglet/archive/2012/05/23/2514769.html"/><content type="html">&lt;p&gt;.net 框架中提供的 System.Environment.GetFolderPath 只能获取当前用户的特殊目录，无法获取所有用户的特殊目录。我做了一个类，可以帮助获取所有用户的特殊目录。这个类调用SHGetFolderPath windows API 来获取ALL USER 的特殊目录路径，网上有很多相关的文章用的API是有些过时了，这篇文章中的API可以适用于windows 2000 后的任何操作系统。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;div class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Runtime.InteropServices;&amp;nbsp;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; MySystem{    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Environment    {        [DllImport(&lt;span class="str"&gt;"shell32.dll"&lt;/span&gt;)]        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; SHGetFolderPath(IntPtr hwndOwner, SpecialFolderCSIDL nFolder, IntPtr hToken,           &lt;span class="kwrd"&gt;uint&lt;/span&gt; dwFlags, [Out] StringBuilder pszPath);&amp;nbsp;        &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; MAX_PATH = 260;&amp;nbsp;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;enum&lt;/span&gt; SpecialFolderCSIDL : &lt;span class="kwrd"&gt;int&lt;/span&gt;        {            CSIDL_DESKTOP = 0x0000,    &lt;span class="rem"&gt;// &amp;lt;desktop&amp;gt;&lt;/span&gt;            CSIDL_INTERNET = 0x0001,    &lt;span class="rem"&gt;// Internet Explorer (icon on desktop)&lt;/span&gt;            CSIDL_PROGRAMS = 0x0002,    &lt;span class="rem"&gt;// Start Menu\Programs&lt;/span&gt;            CSIDL_CONTROLS = 0x0003,    &lt;span class="rem"&gt;// My Computer\Control Panel&lt;/span&gt;            CSIDL_PRINTERS = 0x0004,    &lt;span class="rem"&gt;// My Computer\Printers&lt;/span&gt;            CSIDL_PERSONAL = 0x0005,    &lt;span class="rem"&gt;// My Documents&lt;/span&gt;            CSIDL_FAVORITES = 0x0006,    &lt;span class="rem"&gt;// &amp;lt;user name&amp;gt;\Favorites&lt;/span&gt;            CSIDL_STARTUP = 0x0007,    &lt;span class="rem"&gt;// Start Menu\Programs\Startup&lt;/span&gt;            CSIDL_RECENT = 0x0008,    &lt;span class="rem"&gt;// &amp;lt;user name&amp;gt;\Recent&lt;/span&gt;            CSIDL_SENDTO = 0x0009,    &lt;span class="rem"&gt;// &amp;lt;user name&amp;gt;\SendTo&lt;/span&gt;            CSIDL_BITBUCKET = 0x000a,    &lt;span class="rem"&gt;// &amp;lt;desktop&amp;gt;\Recycle Bin&lt;/span&gt;            CSIDL_STARTMENU = 0x000b,    &lt;span class="rem"&gt;// &amp;lt;user name&amp;gt;\Start Menu&lt;/span&gt;            CSIDL_MYMUSIC = 0x000d, &lt;span class="rem"&gt;//&lt;/span&gt;            CSIDL_DESKTOPDIRECTORY = 0x0010,    &lt;span class="rem"&gt;// &amp;lt;user name&amp;gt;\Desktop&lt;/span&gt;            CSIDL_DRIVES = 0x0011,    &lt;span class="rem"&gt;// My Computer&lt;/span&gt;            CSIDL_NETWORK = 0x0012,    &lt;span class="rem"&gt;// Network Neighborhood&lt;/span&gt;            CSIDL_NETHOOD = 0x0013,    &lt;span class="rem"&gt;// &amp;lt;user name&amp;gt;\nethood&lt;/span&gt;            CSIDL_FONTS = 0x0014,    &lt;span class="rem"&gt;// windows\fonts&lt;/span&gt;            CSIDL_TEMPLATES = 0x0015,            CSIDL_COMMON_STARTMENU = 0x0016,    &lt;span class="rem"&gt;// All Users\Start Menu&lt;/span&gt;            CSIDL_COMMON_PROGRAMS = 0x0017,    &lt;span class="rem"&gt;// All Users\Programs&lt;/span&gt;            CSIDL_COMMON_STARTUP = 0x0018,    &lt;span class="rem"&gt;// All Users\Startup&lt;/span&gt;            CSIDL_COMMON_DESKTOPDIRECTORY = 0x0019,    &lt;span class="rem"&gt;// All Users\Desktop&lt;/span&gt;            CSIDL_APPDATA = 0x001a,    &lt;span class="rem"&gt;// &amp;lt;user name&amp;gt;\Application Data&lt;/span&gt;            CSIDL_PRINTHOOD = 0x001b,    &lt;span class="rem"&gt;// &amp;lt;user name&amp;gt;\PrintHood&lt;/span&gt;            CSIDL_LOCAL_APPDATA = 0x001c,    &lt;span class="rem"&gt;// &amp;lt;user name&amp;gt;\Local Settings\Applicaiton Data (non roaming)&lt;/span&gt;            CSIDL_ALTSTARTUP = 0x001d,    &lt;span class="rem"&gt;// non localized startup&lt;/span&gt;            CSIDL_COMMON_ALTSTARTUP = 0x001e,    &lt;span class="rem"&gt;// non localized common startup&lt;/span&gt;            CSIDL_COMMON_FAVORITES = 0x001f,            CSIDL_INTERNET_CACHE = 0x0020,            CSIDL_COOKIES = 0x0021,            CSIDL_HISTORY = 0x0022,            CSIDL_COMMON_APPDATA = 0x0023,    &lt;span class="rem"&gt;// All Users\Application Data&lt;/span&gt;            CSIDL_WINDOWS = 0x0024,    &lt;span class="rem"&gt;// GetWindowsDirectory()&lt;/span&gt;            CSIDL_SYSTEM = 0x0025,    &lt;span class="rem"&gt;// GetSystemDirectory()&lt;/span&gt;            CSIDL_PROGRAM_FILES = 0x0026,    &lt;span class="rem"&gt;// C:\Program Files&lt;/span&gt;            CSIDL_MYPICTURES = 0x0027,    &lt;span class="rem"&gt;// C:\Program Files\My Pictures&lt;/span&gt;            CSIDL_PROFILE = 0x0028,    &lt;span class="rem"&gt;// USERPROFILE&lt;/span&gt;            CSIDL_SYSTEMX86 = 0x0029,    &lt;span class="rem"&gt;// x86 system directory on RISC&lt;/span&gt;            CSIDL_PROGRAM_FILESX86 = 0x002a,    &lt;span class="rem"&gt;// x86 C:\Program Files on RISC&lt;/span&gt;            CSIDL_PROGRAM_FILES_COMMON = 0x002b,    &lt;span class="rem"&gt;// C:\Program Files\Common&lt;/span&gt;            CSIDL_PROGRAM_FILES_COMMONX86 = 0x002c,    &lt;span class="rem"&gt;// x86 Program Files\Common on RISC&lt;/span&gt;            CSIDL_COMMON_TEMPLATES = 0x002d,    &lt;span class="rem"&gt;// All Users\Templates&lt;/span&gt;            CSIDL_COMMON_DOCUMENTS = 0x002e,    &lt;span class="rem"&gt;// All Users\Documents&lt;/span&gt;            CSIDL_COMMON_ADMINTOOLS = 0x002f,    &lt;span class="rem"&gt;// All Users\Start Menu\Programs\Administrative Tools&lt;/span&gt;            CSIDL_ADMINTOOLS = 0x0030,    &lt;span class="rem"&gt;// &amp;lt;user name&amp;gt;\Start Menu\Programs\Administrative Tools&lt;/span&gt;            CSIDL_CONNECTIONS = 0x0031,    &lt;span class="rem"&gt;// Network and Dial-up Connections&lt;/span&gt;        };&amp;nbsp;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetAllUsersFolderPath(SpecialFolderCSIDL csidl)        {            StringBuilder path = &lt;span class="kwrd"&gt;new&lt;/span&gt; StringBuilder(MAX_PATH);            SHGetFolderPath(IntPtr.Zero, csidl, IntPtr.Zero, 0, path);            &lt;span class="kwrd"&gt;return&lt;/span&gt; path.ToString();        }&amp;nbsp;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; GetAllUsersFolderPath(System.Environment.SpecialFolder specialFolder)        {            SpecialFolderCSIDL csidl;&amp;nbsp;            &lt;span class="kwrd"&gt;switch&lt;/span&gt; (specialFolder)            {                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.ApplicationData:                    csidl = SpecialFolderCSIDL.CSIDL_APPDATA;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.CommonApplicationData:                    csidl = SpecialFolderCSIDL.CSIDL_COMMON_APPDATA;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.CommonProgramFiles:                    csidl = SpecialFolderCSIDL.CSIDL_COMMON_PROGRAMS;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.Cookies:                    csidl = SpecialFolderCSIDL.CSIDL_COOKIES;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.Desktop:                    csidl = SpecialFolderCSIDL.CSIDL_COMMON_DESKTOPDIRECTORY;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.DesktopDirectory:                    csidl = SpecialFolderCSIDL.CSIDL_COMMON_DESKTOPDIRECTORY;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.Favorites:                    csidl = SpecialFolderCSIDL.CSIDL_COMMON_FAVORITES;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.History:                    csidl = SpecialFolderCSIDL.CSIDL_HISTORY;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.InternetCache:                    csidl = SpecialFolderCSIDL.CSIDL_INTERNET_CACHE;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.LocalApplicationData:                    csidl = SpecialFolderCSIDL.CSIDL_LOCAL_APPDATA;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.MyComputer:                    csidl = SpecialFolderCSIDL.CSIDL_DRIVES;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.MyDocuments:                    csidl = SpecialFolderCSIDL.CSIDL_COMMON_DOCUMENTS;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.MyMusic:                    csidl = SpecialFolderCSIDL.CSIDL_MYMUSIC;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.MyPictures:                    csidl = SpecialFolderCSIDL.CSIDL_MYPICTURES;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.ProgramFiles:                    csidl = SpecialFolderCSIDL.CSIDL_PROGRAM_FILES;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.Programs:                    csidl = SpecialFolderCSIDL.CSIDL_COMMON_PROGRAMS;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.Recent:                    csidl = SpecialFolderCSIDL.CSIDL_RECENT;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.SendTo:                    csidl = SpecialFolderCSIDL.CSIDL_SENDTO;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.StartMenu:                    csidl = SpecialFolderCSIDL.CSIDL_COMMON_STARTMENU;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.Startup:                    csidl = SpecialFolderCSIDL.CSIDL_COMMON_STARTUP;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.System:                    csidl = SpecialFolderCSIDL.CSIDL_SYSTEM;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;case&lt;/span&gt; System.Environment.SpecialFolder.Templates:                    csidl = SpecialFolderCSIDL.CSIDL_COMMON_TEMPLATES;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;                &lt;span class="kwrd"&gt;default&lt;/span&gt;:                    csidl = SpecialFolderCSIDL.CSIDL_COMMON_DOCUMENTS;                    &lt;span class="kwrd"&gt;break&lt;/span&gt;;            }&amp;nbsp;            &lt;span class="kwrd"&gt;return&lt;/span&gt; GetAllUsersFolderPath(csidl);        }    }}&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt; &lt;img src="http://www.cnblogs.com/eaglet/aggbug/2514769.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/eaglet/archive/2012/05/23/2514769.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/eaglet/archive/2012/05/21/2511174.html</id><title type="text">i—比 i++ 快？</title><summary type="text">今天在微博上看到有人说 i—比 i++ 快，我用C写了个程序测试了一下，还真的是快，难道减法运算比加法快？从原理上分析感觉不可能啊，于是深入研究了一下，终于找到原因。</summary><published>2012-05-21T01:44:00Z</published><updated>2012-05-21T01:44:00Z</updated><author><name>eaglet</name><uri>http://www.cnblogs.com/eaglet/</uri></author><link rel="alternate" href="http://www.cnblogs.com/eaglet/archive/2012/05/21/2511174.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/eaglet/archive/2012/05/21/2511174.html"/><content type="html">&lt;p&gt;今天在微博上看到有人说 i&amp;#8212;比 i++ 快，我用C写了个程序测试了一下，还真的是快，难道减法运算比加法快？从原理上分析感觉不可能啊，于是深入研究了一下，终于找到原因。&lt;/p&gt; &lt;p&gt;先看一下测试代码：&lt;/p&gt;#include &amp;lt;stdio.h&amp;gt;&lt;br/&gt;#include &amp;lt;time.h&amp;gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; main()&lt;br/&gt;{&lt;br/&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; count = 1000000000;&lt;br/&gt;&lt;br/&gt;    clock_t cl = clock ();&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt; i = count; i &amp;gt; 0 ; i--)&lt;br/&gt;    {&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    printf(&lt;span class="str"&gt;"Elapse %u ms\r\n"&lt;/span&gt;, (clock () - cl));&lt;br/&gt;&lt;br/&gt;    cl = clock ();&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; count ; i++)&lt;br/&gt;    {&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    printf(&lt;span class="str"&gt;"Elapse %u ms\r\n"&lt;/span&gt;, (clock () - cl));&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;return&lt;/span&gt; 0;&lt;br/&gt;}&lt;br/&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;以上代码在VC 2008 下编译，编译时取消优化选项（如果不取消优化的话，上面两个循环语句由于什么都没干，会被编译器优化掉)。&lt;/p&gt;&lt;p&gt;运行后的结果是 &lt;br /&gt;Elapse 2267 ms&lt;br /&gt;Elapse 2569 ms&lt;/p&gt;&lt;p&gt;也就是说减法循环比加法循环10亿次时快300毫秒，超过10%。&lt;/p&gt;&lt;p&gt;从C语言层面上分析，这两个代码几乎是一样的，我一开始也是楞了1分多钟，后来仔细比较两个代码，感觉它们的差别主要在两个地方，一个是加法和减法的差别，一个是for循环的第二个语句中一个是和立即数比较一个是和变量比较。以我掌握的计算机硬件原理知识，我首先排除了第一个差别造成性能影响的可能，那么问题很可能就出在第二个差别上，因为我知道在汇编语言中两个内存变量是不能直接比较的，中间必须要通过寄存器转储一次。这样就会多出至少一个指令。问题可能就在这里。为了验证我的判断，我们来看一下上面代码的汇编语句到底是什么样子的：&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;int&lt;/span&gt; main()&lt;span class="lnum"&gt;   2:  &lt;/span&gt;{&lt;span class="lnum"&gt;   3:  &lt;/span&gt;00CC1000  push        ebp  &lt;span class="lnum"&gt;   4:  &lt;/span&gt;00CC1001  mov         ebp,esp &lt;span class="lnum"&gt;   5:  &lt;/span&gt;00CC1003  sub         esp,10h &lt;span class="lnum"&gt;   6:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;    &lt;span class="kwrd"&gt;int&lt;/span&gt; count = 1000000000;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;00CC1006  mov         dword ptr [count],3B9ACA00h &lt;span class="lnum"&gt;   9:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    clock_t cl = clock ();&lt;span class="lnum"&gt;  12:  &lt;/span&gt;00CC100D  call        dword ptr [__imp__clock (0CC209Ch)] &lt;span class="lnum"&gt;  13:  &lt;/span&gt;00CC1013  mov         dword ptr [cl],eax &lt;span class="lnum"&gt;  14:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt; i = count; i &amp;gt; 0 ; i--)&lt;span class="lnum"&gt;  16:  &lt;/span&gt;00CC1016  mov         eax,dword ptr [count] &lt;span class="lnum"&gt;  17:  &lt;/span&gt;00CC1019  mov         dword ptr [i],eax &lt;span class="lnum"&gt;  18:  &lt;/span&gt;00CC101C  jmp         main+27h (0CC1027h) &lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;00CC101E  mov         ecx,dword ptr [i] //把i的内存值拷贝到寄存器ecx中&lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;00CC1021  sub         ecx,1 //ecx 减1&lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;00CC1024  mov         dword ptr [i],ecx //把ecx 的值拷贝到i对应的内存地址,这里完成i--操作 &lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;00CC1027  cmp         dword ptr [i],0 //i对应的内存值和0进行比较 &lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;00CC102B  jle         main+2Fh (0CC102Fh) //如果小于等于0，跳转到98行&lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;    {&lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;    }&lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;00CC102D  jmp         main+1Eh (0CC101Eh)//如果大于0，跳转到19行，继续循环&lt;/font&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;    printf(&lt;span class="str"&gt;"Elapse %u ms"&lt;/span&gt;, (clock () - cl));&lt;span class="lnum"&gt;  29:  &lt;/span&gt;00CC102F  call        dword ptr [__imp__clock (0CC209Ch)] &lt;span class="lnum"&gt;  30:  &lt;/span&gt;00CC1035  sub         eax,dword ptr [cl] &lt;span class="lnum"&gt;  31:  &lt;/span&gt;00CC1038  push        eax  &lt;span class="lnum"&gt;  32:  &lt;/span&gt;00CC1039  push        offset ___xi_z+30h (0CC20F4h) &lt;span class="lnum"&gt;  33:  &lt;/span&gt;00CC103E  call        dword ptr [__imp__printf (0CC20A4h)] &lt;span class="lnum"&gt;  34:  &lt;/span&gt;00CC1044  add         esp,8 &lt;span class="lnum"&gt;  35:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;    cl = clock ();&lt;span class="lnum"&gt;  37:  &lt;/span&gt;00CC1047  call        dword ptr [__imp__clock (0CC209Ch)] &lt;span class="lnum"&gt;  38:  &lt;/span&gt;00CC104D  mov         dword ptr [cl],eax &lt;span class="lnum"&gt;  39:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; count ; i++)&lt;span class="lnum"&gt;  41:  &lt;/span&gt;00CC1050  mov         dword ptr [i],0 &lt;span class="lnum"&gt;  42:  &lt;/span&gt;00CC1057  jmp         main+62h (0CC1062h) &lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  43:  &lt;/span&gt;00CC1059  mov         edx,dword ptr [i]//把i的内存值拷贝到寄存器edx中 &lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  44:  &lt;/span&gt;00CC105C  add         edx,1 //edx 加 1 &lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  45:  &lt;/span&gt;00CC105F  mov         dword ptr [i],edx //将edx的值拷贝到i变量对应地址 &lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  46:  &lt;/span&gt;00CC1062  mov         eax,dword ptr [i] //将i变量值拷贝到寄存器eax中 &lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  47:  &lt;/span&gt;00CC1065  cmp         eax,dword ptr [count] //用eax 和 count地址上的值进行比较&lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  48:  &lt;/span&gt;00CC1068  jge         main+6Ch (0CC106Ch)//如果大于等于count，跳出循环 &lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  49:  &lt;/span&gt;    {&lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  50:  &lt;/span&gt;    }&lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  51:  &lt;/span&gt;00CC106A  jmp         main+59h (0CC1059h)//否则跳转到43行继续循环&lt;/font&gt;&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;我把汇编语句中的循环部分用红色标记出来，并加上注释。我们可以清楚的看到第二个循环中的汇编指令为7个，第一个为6个，也就是说第一个要比第二个要快 1/7 左右，这个和实际测试出来的结果基本上是吻合的。&lt;/p&gt;&lt;p&gt;那么我们再看看为什么编译器要多一个机器指令。原因是汇编语句不可能对两个内存值直接比较，内存值只能和寄存器进行比较，这个应该是计算机硬件结构决定的，这个问题就导致编译器必须要加一个指令来转储内存值到寄存器中。&lt;/p&gt;&lt;p&gt;再进一步，我们发现编译器似乎很蠢，如果在循环之前把 dword ptr[count] 拷贝到一个寄存器中，比如 ecx ，然后在46 行直接 cmp ecx, dword ptr [i] ，就不需要第47行这个指令了。但事实上编译器可能并没有蠢到这个地步，本文前面说过，我将编译器的优化给禁用了，因为如果优化的话，上面两个for循环将被完全忽略掉，根本不会执行，测试出来的时间为0秒。那么既然我们告诉编译器不优化，编译器也就不会优化这个指令，如果真的按照上面方法优化了，那么在调试环境下，如果我们想在循环中更改 count 的值就比较困难了，需要调试器来做一些编译器要做的事情。&lt;/p&gt;&lt;p&gt;再深入一点，我们还会发现这个汇编语句中还有一个地方可以优化，就是 &lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;00CC1024  mov         dword ptr [i],ecx //把ecx 的值拷贝到i对应的内存地址,这里完成i--操作 &lt;/font&gt;&lt;font color="#ff0000"&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;00CC1027  cmp         dword ptr [i],0 //i对应的内存值和0进行比较 &lt;/font&gt;&lt;p&gt;第22行这个地方完全可以优化为 cmp ecx, 0 &lt;/p&gt;&lt;p&gt;我们知道对寄存器的读写是最快的，其次是一级缓存，二级缓存，三级缓存，然后才是内存，最后是磁盘。&lt;/p&gt;&lt;p&gt;如果22行优化为 cmp ecx, 0 其运行速度肯定要比 cmp dword ptr[i], 0 要快，因为后面的语句要进行一次寻址，从缓存中读取数据（如果CPU有缓存的话），如果没缓存，就是从内存读一次，那就更慢了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;最后我们把i++那个循环改成&lt;/p&gt;&lt;p&gt;for(int i = 0; i &amp;lt; 1000000000 ; i++) 再测一次，结果为&lt;/p&gt;&lt;p&gt;Elapse 2334 ms&lt;br /&gt;Elapse 2290 ms&lt;/p&gt;&lt;p&gt;可以看出两个循环的用时基本上相等了&lt;/p&gt;    &lt;span class="kwrd"&gt;for&lt;/span&gt;(&lt;span class="kwrd"&gt;int&lt;/span&gt; i = 0; i &amp;lt; 1000000000 ; i++)&lt;br/&gt;01201050  mov         dword ptr [i],0 &lt;br/&gt;01201057  jmp         main+62h (1201062h) &lt;br/&gt;&lt;font color="#ff0000"&gt;01201059  mov         edx,dword ptr [i] &lt;br/&gt;0120105C  add         edx,1 &lt;br/&gt;0120105F  mov         dword ptr [i],edx &lt;br/&gt;01201062  cmp         dword ptr [i],3B9ACA00h &lt;br/&gt;01201069  jge         main+6Dh (120106Dh) &lt;br/&gt;    {&lt;br/&gt;    }&lt;br/&gt;0120106B  jmp         main+59h (1201059h)&lt;/font&gt; &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;看一下汇编语句，for 循环的第二句改成立即数比较后，汇编语句变成了6个指令了。所以用时也基本相同了。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;结论：&lt;/p&gt;&lt;p&gt;i++ 和 i-- 性能是没有区别的，之所以我们感觉i--快，是因为在汇编层面上，i++ 那个循环中多了一个机器指令造成的。另外通过本文，我们也了解了一些关于汇编的指令优化的知识，希望对大家能有帮助。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;微博： &lt;a href="http://weibo.com/hubbledotnet"&gt;http://weibo.com/hubbledotnet&lt;/a&gt;&lt;/p&gt; &lt;img src="http://www.cnblogs.com/eaglet/aggbug/2511174.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/eaglet/archive/2012/05/21/2511174.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/eaglet/archive/2012/05/18/2507179.html</id><title type="text">多线程环境下调用 HttpWebRequest 并发连接限制</title><summary type="text">.net 的 HttpWebRequest 或者 WebClient 在多线程情况下存在并发连接限制，这个机制会大大影响网络应用程序性能,本文讲述如何修改这个并发连接限制。</summary><published>2012-05-18T00:54:00Z</published><updated>2012-05-18T00:54:00Z</updated><author><name>eaglet</name><uri>http://www.cnblogs.com/eaglet/</uri></author><link rel="alternate" href="http://www.cnblogs.com/eaglet/archive/2012/05/18/2507179.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/eaglet/archive/2012/05/18/2507179.html"/><content type="html">&lt;p&gt;.net 的 HttpWebRequest 或者 WebClient 在多线程情况下存在并发连接限制，这个限制在桌面操作系统如 windows xp , windows&amp;nbsp; 7 下默认是2，在服务器操作系统上默认为10. 如果不修改这个并发连接限制，那么客户端同时可以建立的 http 连接数就只有2个或10个。对于一些诸如浏览器或网络蜘蛛的应用，2个或10个并发数量实在太少，大大影响应用的性能。之所以有这个并发连接限制，是因为 http 1.0 和 http 1.1 标准规定并发连接数最大为2. 不过目前主流的浏览器都已经不遵循这个规则了，但 .net framework 依然默认遵循这个规则。&lt;/p&gt; &lt;p&gt;很多文章说用异步方式访问 HttpWebRequest 可以提高并发性能，但我测试下来，如果不修改这个默认并发连接数，同步或异步方式访问性能都很不好。&lt;/p&gt; &lt;p&gt;调整这个默认并发连接限制的方法很简单&lt;/p&gt; &lt;p&gt;只要在程序中设置：&lt;/p&gt; &lt;p&gt;System.Net.ServicePointManager.DefaultConnectionLimit = 512;&lt;/p&gt; &lt;p&gt;这个值最好不要超过1024。&lt;/p&gt; &lt;p&gt;我们也可以在app.config 中对最大并发连接数进行设置，方法如下：&lt;/p&gt; &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;system.net&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;connectionManagement&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;address&lt;/span&gt; = &lt;span class="kwrd"&gt;"http://www.google.com"&lt;/span&gt; &lt;span class="attr"&gt;maxconnection&lt;/span&gt; = &lt;span class="kwrd"&gt;"512"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;address&lt;/span&gt; = &lt;span class="kwrd"&gt;"*"&lt;/span&gt; &lt;span class="attr"&gt;maxconnection&lt;/span&gt; = &lt;span class="kwrd"&gt;"512"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;connectionManagement&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;system.net&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;configuration&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;span class="kwrd"&gt;&lt;/span&gt; &lt;p&gt;修改了这个设置后，并发性能明显提高，从原来每秒钟20次直接上升到每秒钟1000多次。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt; &lt;img src="http://www.cnblogs.com/eaglet/aggbug/2507179.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/eaglet/archive/2012/05/18/2507179.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/eaglet/archive/2012/05/10/2494073.html</id><title type="text">HubbleDotNet+Mongodb 构建高性能搜索引擎--概述</title><summary type="text">HubbleDotNet 通过支持 Mongodb 也使其本身同时具备了 no-sql 的解决方案。本文将重点概述Hubble+Mongodb 的功能以及和hubble+sql, lucene.net 的一些性能测试对比。</summary><published>2012-05-10T04:01:00Z</published><updated>2012-05-10T04:01:00Z</updated><author><name>eaglet</name><uri>http://www.cnblogs.com/eaglet/</uri></author><link rel="alternate" href="http://www.cnblogs.com/eaglet/archive/2012/05/10/2494073.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/eaglet/archive/2012/05/10/2494073.html"/><content type="html">&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HubbleDotNet 从 1.2.3 版本以后开始在官方代码中支持和 Mongodb 对接，Mongodb 是10gen 公司开发的 no-sql 数据库，其读写性能比传统关系数据库要快很多，而且可以非常方便的分布式部署。HubbleDotNet 通过支持 Mongodb 也使其本身同时具备了 no-sql 的解决方案。本文将重点概述Hubble+Mongodb 的功能以及和hubble+sql , lucene.net 的一些性能测试对比。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Mongodb 的安装&lt;/strong&gt;&lt;/p&gt; &lt;blockquote style='border:2px solid #EFEFEF;color:#333333;padding:5px 10px;'&gt;&lt;/blockquote&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在开始本文之前，我们简单介绍一下 Mongodb 在 windows 下的安装，其他操作系统下的安装也是类似的。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 首先在这个链接 &lt;a title="http://www.mongodb.org/downloads" href="http://www.mongodb.org/downloads"&gt;http://www.mongodb.org/downloads&lt;/a&gt; 找到对应操作系统的版本，下载下来后解压。我们假设解压到 C:\mongodb &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们在 c:\mongodb 下建立一个 data 目录和 一个 log 目录。下面是目录结构：&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://images.cnblogs.com/cnblogs_com/eaglet/201205/20120510120057883.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline;background-image: none;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/eaglet/201205/201205101200591208.png" border="0" height="248" width="369" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 然后我们在run 中运行 cmd ，然后执行 cd c:\mongodb\bin 进入mongodb可执行程序目录&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 接下来执行 mongod --dbpath ../data --logpath ../log/mongodb.log&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 完成上述步骤后，mongodb 的服务程序就启动了。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt; &lt;p&gt;&lt;strong&gt; 默认端口&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果要远程访问 mongodb ，我们需要在防火墙中将 mongodb 的默认端口打开，下面是 mongodb 相关服务的默认端口：&lt;/p&gt; &lt;ul&gt;&lt;li&gt;Standalone &lt;tt&gt;mongod&lt;/tt&gt; : 27017&lt;/li&gt;&lt;li&gt;&lt;tt&gt;mongos&lt;/tt&gt; : 27017&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.mongodb.org/display/DOCS/Architecture+and+Components"&gt;shard server&lt;/a&gt; (&lt;tt&gt;mongod --shardsvr&lt;/tt&gt;) : 27018&lt;/li&gt;&lt;li&gt;config server (&lt;tt&gt;mongod --configsvr&lt;/tt&gt;) : 27019&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.mongodb.org/display/DOCS/Http+Interface"&gt;web stats page&lt;/a&gt; for &lt;tt&gt;mongod&lt;/tt&gt; : add 1000 to port number (28017, by default) &lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;strong&gt;&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;安装为服务&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 上面说的命令行只是用于调试用的，如果要正式在服务器上部署，我们需要将 mongodb 安装为服务来运行。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在windows 下安装mongodb服务的命令行如下:&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C:\mongodb\bin&amp;gt;mongod --dbpath c:\mongodb\data --logpath c:\mongodb\log\mongodb.log --logappend &amp;#8211;install&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这里我们需要注意下面两点：&lt;/p&gt; &lt;ol&gt;&lt;li&gt;&lt;font color="#ff0000"&gt;命令行中的路径必须是绝对路径，如果输入相对路径，需要修改服务的启动路径，否则服务无法运行。&lt;/font&gt;&lt;/li&gt;&lt;li&gt;&lt;font color="#ff0000"&gt;如果是在 windows 7 或者 windows 2008 server 操作系统下安装，必须以 administrator 方式运行 cmd 才行。&lt;/font&gt;&lt;/li&gt;&lt;/ol&gt; &lt;p&gt;&lt;strong&gt;卸载服务&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 如果我们不想要mongodb 了，我们可以通过如下命令行卸载服务：&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; C:\mongodb\bin&amp;gt;mongod --remove&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Hubble中mongodb 数据库适配器的连接字符串&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在HubbleDotNet 中，没有采用 mongodb 默认的连接字符串来连接mongodb，而是用了标准的连接字符串来连接&lt;/p&gt; &lt;p&gt;&lt;strong&gt;无用户名和密码连接 mongodb &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个是mongodb没有设置用户名和密码时通过 hubbledotnet 连接mongodb 数据库适配器的连接字符串&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Data Source=127.0.0.1;Initial Catalog=News;Integrated Security=True&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 我们只要指定服务器IP地址 Data Soruce 和 数据库名 Initial Catalog 就可以了&lt;/p&gt; &lt;p&gt;&lt;strong&gt; 通过用户名和密码连接 mongodb &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 这个是mongodb设置用户名和密码时通过 hubbledotnet 连接mongodb 数据库适配器的连接字符串&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Data Source=127.0.0.1;Initial Catalog=News;User Id=myUsername;Password=myPassword;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;HubbleDotNet+Mongodb 功能一览&lt;/strong&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;支持标准的数据类型如 int, string, double,datetime 等&lt;/li&gt;&lt;li&gt;支持对mongodb的指定字符串字段进行全文索引和查询。mongodb 本身不支持全文查询，hubbledotnet 通过配置后可以支持对mongodb进行全文查询，查询语法和与其他数据库类型的语法相同。这个是hubble+mongodb 的核心功能。&lt;/li&gt;&lt;li&gt;支持主库为关系数据库，比如 sql server ，镜像表用 mongodb。这个是推荐方式，可以做到数据的读写分离和分布式部署。 &lt;/li&gt;&lt;li&gt;支持 mongodb 作为主库的主动模式索引，这种模式对于实时索引将会比较有用&lt;/li&gt;&lt;li&gt;支持 mongodb 作为主库的被动模式索引。这种模式目前还不支持通过hubble来同步索引，需要自己写代码手工同步。原因是mongodb 不支持触发器。&lt;/li&gt;&lt;li&gt;支持通过 mongodb 实现数据的分布式部署&lt;/li&gt;&lt;li&gt;支持用SQL语句对mongodb进行非全文查询。如 select top 10 * from table where price &amp;gt; 100 and price &amp;lt; 200 order by price。这个是 hubbleDotNet 特有的功能。hubbledotnet 实现了一个sql 到 bson 的语法转换，调用者可以像访问sql server 那样来通过标准sql语句访问 mongodb ，这为不喜欢 bson 查询的开发者提供了很大的便利。&lt;/li&gt;&lt;li&gt;支持通过bson 语句访问或配置 mongodb。 hubbledotnet 提供了两个存储过程 sp_excutesql 和 sp_querysql 来方便用户通过hubble直接用 bson 操作mongodb&lt;/li&gt;&lt;li&gt;对不完整文档的支持。Mongodb 是文档型数据库，它并不强制每条记录的字段像关系数据库那样是固定不变的，可能每条记录的字段都不一样。HubbleDotNet 支持这种设计，对于在记录中没有出现的字段，作为NULL来处理，如果指定了默认值，则按默认值处理。&lt;/li&gt;&lt;li&gt;对 sub-field 的支持。mongodb 是文档型数据，支持子字段。hubble 将在后续版本中对子字段进行支持。&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&lt;strong&gt;性能测试&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;测试环境：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 软件版本&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HubbleDotNet 版本 1.2.5.0&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Mongodb 版本 2.0.5&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SQL SERVER 2008&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Lucene.net 2.9.4&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 系统环境&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Intel i5 2430M 2.40GHz 8GB windows 7 64bit&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 7800 转机械硬盘 &lt;/p&gt; &lt;p&gt;&lt;strong&gt;测试数据 &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 测试数据为2000万行互联网网页数据。数据文件大小为4GB。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;测试目标：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 测试hubble+sqlserver, Hubble+Mongodb 以及 lucene.net 在单机系统高并发时的性能比较。 &lt;/p&gt; &lt;p&gt;&lt;strong&gt;测试方法： &lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 通过测试代码每秒钟查询10次，查询840个常用英文单词的搜索，返回前10条 title 和 content ，按匹配度排序&lt;/p&gt; &lt;p&gt;&lt;strong&gt;测试用例1：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 在这个测试用例中，我们取消 hubbledotnet 所有的缓存，让 hubbledotnet 每次都从硬盘读索引，lucene.net 也设置为从文件读取。对840个英文单词的查询全部是首次查询。而且每次测试前重启计算机以清除操作系统的文件缓存。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 测试结果如下：&lt;/p&gt; &lt;table style="color: #000000;" border="0" cellpadding="0" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="bottom" width="160"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="bottom" width="72"&gt; &lt;p&gt;每秒钟查询次数&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="87"&gt; &lt;p&gt;最大查询时间(ms)&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;平均查询时间(ms)&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="67"&gt; &lt;p&gt;最小查询时间(ms)&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="bottom" width="160"&gt; &lt;p&gt;Hubble+Mongodb&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="72"&gt; &lt;p&gt;10&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="87"&gt; &lt;p&gt;1573&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;431&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="67"&gt; &lt;p&gt;3&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="bottom" width="160"&gt; &lt;p&gt;Hubble+SQL SERVER&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="72"&gt; &lt;p&gt;10&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="87"&gt; &lt;p&gt;8997&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;931&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="67"&gt; &lt;p&gt;4&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="bottom" width="160"&gt; &lt;p&gt;Lucene.net&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="72"&gt; &lt;p&gt;10&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="87"&gt; &lt;p&gt;209196&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;108665&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="67"&gt; &lt;p&gt;9430&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/eaglet/201205/201205101201013518.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline;background-image: none;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/eaglet/201205/201205101201033287.png" border="0" height="296" width="490" /&gt;&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;从这个测试看冷启动情况下， hubbledotnet+mongodb 的性能是最佳的，而lucene.net 几乎比 hubbledotnet+mongodb 慢200多倍。lucene.net 比 hubbledotnet 慢这么多的原因主要是lucene.net 访问IO 的速度较慢，以及lucene.net 的索引大小比hubbledotnet 大4倍多。lucene.net 的索引大小是 3.6GB 而 hubbledotnet 只有 800MB 。HubbleDotNet 1.2.5.0 对于首次查询的磁盘IO做了一定的优化，也是 hubbledotnet 比 lucene.net 性能高这么的主要原因。&lt;/p&gt; &lt;p&gt;&lt;strong&gt;测试用例2：&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;在这个测试用例中，我们在 hubbledotnet 中指定RamIndex 为Full，即将索引全部加载到内存，lucene.net 也设置为内存索引。这个测试主要是测试内存索引的性能。&lt;/p&gt; &lt;p&gt;测试结果如下：&lt;/p&gt; &lt;table style="color: #000000;" border="0" cellpadding="0" cellspacing="0"&gt; &lt;tbody&gt; &lt;tr&gt; &lt;td valign="bottom" width="160"&gt;&amp;nbsp;&lt;/td&gt; &lt;td valign="bottom" width="72"&gt; &lt;p&gt;每秒钟查询次数&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="87"&gt; &lt;p&gt;最大查询时间(ms)&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;平均查询时间(ms)&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="67"&gt; &lt;p&gt;最小查询时间(ms)&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;内存(MB)&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="bottom" width="160"&gt; &lt;p&gt;Hubble+Mongodb&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="72"&gt; &lt;p&gt;10&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="87"&gt; &lt;p&gt;148&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;5.53&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="67"&gt; &lt;p&gt;1&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;1,164&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="bottom" width="160"&gt; &lt;p&gt;Hubble+SQL SERVER&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="72"&gt; &lt;p&gt;10&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="87"&gt; &lt;p&gt;157&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;6.17&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="67"&gt; &lt;p&gt;0&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;1,170&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td valign="bottom" width="160"&gt; &lt;p&gt;Lucene.net&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="72"&gt; &lt;p&gt;10&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="87"&gt; &lt;p&gt;230&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;3.58&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="67"&gt; &lt;p&gt;0&lt;/p&gt;&lt;/td&gt; &lt;td valign="bottom" width="64"&gt; &lt;p&gt;3,611&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt; &lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/eaglet/201205/201205101201051137.png"&gt;&lt;img style="border: 0px currentColor; padding-top: 0px; padding-right: 0px; padding-left: 0px; display: inline;background-image: none;" title="image" alt="image" src="http://images.cnblogs.com/cnblogs_com/eaglet/201205/201205101201072334.png" border="0" height="306" width="507" /&gt;&lt;/a&gt;&lt;/p&gt;  &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;从这个测试结果看，平均查询时间上 lucene.net 要比 hubbledotnet 略快，最大查询时间上 hubbledotnet 比 lucene.net 快。平均查询时间 lucene.net 快的原因，我分析是这样的，lucene.net 是单进程运行，而 hubbledotnet 是3个进程互动，即测试进程，hubble 服务进程 和 mongodb 进程（或 sql server 进程) 。三个进程互动时，每次查询都会触发进程的切换，这个过程会消耗一定的系统资源，特别是在查询时间为微妙级时，这个性能的损耗就会比较突出一些。不过这个查询速度无论对于那种环境来说都已经足够，从这个测试来看，如果要达到系统的满负荷，hubbledotnet 大概可以支持到每秒钟200次查询左右，相当于每天查询1600万次，这个对于单机系统性能已经非常高了，如果一个网站的访问量达到这么大，一半是需要考虑分布式解决方案了。&lt;/p&gt; &lt;p&gt;而最大查询时间hubble比lucene快将近1倍，这个基本反映出查询算法性能的优劣。这个和我的另外的测试结果(另文阐述)基本是吻合的，即按照score 排序，hubble 的查询速度大概是 lucene.net 的2倍，按其它字段排序，大概为5倍左右。&lt;/p&gt; &lt;p&gt;内存占用方法，Lucene.net 占用3.6GB内存，hubbledotnet占用 1.1 GB 内存，这个主要是因为 hubbledotnet 的索引比 lucene.net 要小的缘故。HubbleDotNet 的内存占用还可以优化，优化后对于本例来说应该可以减少到800MB 左右。&lt;/p&gt; &lt;p&gt;持久化方面，hubbledotnet的内存索引是可以自动持久化的，就是说运行过程中的增删改的变化会自动存储到文件介质中，并更新到内存中，这样即使机器重启也不会丢失数据。lucene.net 的内存索引方案是无法自动持久化的，需要另外写程序持久化。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HubbleDotNet 首页： &lt;a href="http://hubbledotnet.codeplex.com/"&gt;http://hubbledotnet.codeplex.com/&lt;/a&gt;&lt;/p&gt;&lt;a href="http://www.cnblogs.com/eaglet/archive/2010/04/07/1706305.html"&gt;HubbleDotNet开源全文搜索数据库项目--技术详解&lt;/a&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; HubbleDotNet 微博： &lt;a href="http://weibo.com/hubbledotnet"&gt;http://weibo.com/hubbledotnet&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/eaglet/aggbug/2494073.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/eaglet/archive/2012/05/10/2494073.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/eaglet/archive/2012/04/13/2445674.html</id><title type="text">C# 重启计算机的问题</title><summary type="text">C# 程序重启计算机的方法很多，网上也有不少这方面的文章，不过很多网上提供的方法在某些情况下无法获取重启计算机的权限导致重启失败。本文对这些方法做一些简单的讨论。</summary><published>2012-04-13T05:54:00Z</published><updated>2012-04-13T05:54:00Z</updated><author><name>eaglet</name><uri>http://www.cnblogs.com/eaglet/</uri></author><link rel="alternate" href="http://www.cnblogs.com/eaglet/archive/2012/04/13/2445674.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/eaglet/archive/2012/04/13/2445674.html"/><content type="html">&lt;p&gt;C# 程序重启计算机的方法很多，网上也有不少这方面的文章，不过很多网上提供的方法在某些情况下无法获取重启计算机的权限导致重启失败。本文对这些方法做一些简单的讨论。&lt;/p&gt; &lt;p&gt;作者:eaglet&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;网上介绍最多的两种方法分别是：&lt;/p&gt;System.Diagnostics.Process.Start(&lt;span class="str"&gt;"shutdown"&lt;/span&gt;,&lt;span class="str"&gt;@"/r"&lt;/span&gt;);&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;p&gt;和 &lt;/p&gt;    [DllImport(&lt;span class="str"&gt;"user32.dll"&lt;/span&gt;)]&lt;br/&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; ExitWindowsEx(ExitWindows uFlags, ShutdownReason dwReason);&lt;br/&gt;&lt;br/&gt;        [STAThread]&lt;br/&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)&lt;br/&gt;        {&lt;br/&gt;            ExitWindowsEx(ExitWindows.LogOff, ShutdownReason.MajorOther &amp;amp; ShutdownReason.MinorOther);&lt;br/&gt;            &lt;span class="rem"&gt;//这个语句将实现计算机注销操作   &lt;/span&gt;&lt;br/&gt;         }&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;这两种方法在通常情况下工作是没有问题的，但在某些特殊情况下，比如桌面被其它用户锁定时就无法重启计算机。本人在实际工作中遇到过当当前屏幕被远程控制软件锁定后，我做的后台守护进程试图重启计算机,结果用上述两种方法都无法成功。分析原因，应该是远程控制软件用另外的帐号锁定了屏幕（通常应该是windows service 或者 network service)，这时守护进程用当前帐号重启计算机就因为没有权限而失败。&lt;/p&gt;&lt;p&gt;要解决这个问题，我们必须要给进程赋予足够的权限才行，于是我在调用 ExitWindowsEx 前运行了如下代码来赋予当前进程关闭计算机权限&lt;/p&gt;&lt;p&gt;&amp;nbsp; &lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;&lt;div class="csharpcode"&gt;&amp;nbsp;        &lt;span class="rem"&gt;//give current process SeShutdownPrivilege&lt;/span&gt;        TokPriv1Luid tp;&amp;nbsp;        IntPtr hproc = GetCurrentProcess();&amp;nbsp;        IntPtr htok = IntPtr.Zero;&amp;nbsp;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &lt;span class="kwrd"&gt;ref&lt;/span&gt; htok))        {            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&lt;span class="str"&gt;"Open Process Token fail"&lt;/span&gt;);        }&amp;nbsp;        tp.Count = 1;&amp;nbsp;        tp.Luid = 0;&amp;nbsp;        tp.Attr = SE_PRIVILEGE_ENABLED;&amp;nbsp;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!LookupPrivilegeValue(&lt;span class="kwrd"&gt;null&lt;/span&gt;, SE_SHUTDOWN_NAME, &lt;span class="kwrd"&gt;ref&lt;/span&gt; tp.Luid))        {            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&lt;span class="str"&gt;"Lookup Privilege Value fail"&lt;/span&gt;);        }&amp;nbsp;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!AdjustTokenPrivileges(htok, &lt;span class="kwrd"&gt;false&lt;/span&gt;, &lt;span class="kwrd"&gt;ref&lt;/span&gt; tp, 0, IntPtr.Zero, IntPtr.Zero))        {            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&lt;span class="str"&gt;"Adjust Token Privileges fail"&lt;/span&gt;);        }&lt;/div&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;&lt;p&gt;上面代码为当前进程赋予了关闭计算机的权限。这里需要注意的是上述代码要执行成功同样需要足够的权限，通常当前进程需要以拥有至少是系统管理员权限的账户运行。如果没有足够权限，需要用程序模拟系统管理员权限，模拟其它帐号权限的问题不在本文讨论范围内。&lt;/p&gt;&lt;p&gt;加上如上代码后，在其他用户锁定机器后，重启计算机成功。&lt;/p&gt;&lt;p&gt;下面给出完整代码&lt;/p&gt;&lt;div class="csharpcode"&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Runtime.InteropServices;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Threading;&amp;nbsp;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; ExitWindows{    &lt;span class="preproc"&gt;#region&lt;/span&gt; win32 api    [StructLayout(LayoutKind.Sequential, Pack = 1)]&amp;nbsp;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;struct&lt;/span&gt; TokPriv1Luid    {&amp;nbsp;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Count;&amp;nbsp;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;long&lt;/span&gt; Luid;&amp;nbsp;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; Attr;&amp;nbsp;    }&amp;nbsp;    [DllImport(&lt;span class="str"&gt;"kernel32.dll"&lt;/span&gt;, ExactSpelling = &lt;span class="kwrd"&gt;true&lt;/span&gt;)]    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; IntPtr GetCurrentProcess();&amp;nbsp;    [DllImport(&lt;span class="str"&gt;"advapi32.dll"&lt;/span&gt;, ExactSpelling = &lt;span class="kwrd"&gt;true&lt;/span&gt;, SetLastError = &lt;span class="kwrd"&gt;true&lt;/span&gt;)]    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; OpenProcessToken(IntPtr h, &lt;span class="kwrd"&gt;int&lt;/span&gt; acc, &lt;span class="kwrd"&gt;ref&lt;/span&gt; IntPtr phtok);&amp;nbsp;    [DllImport(&lt;span class="str"&gt;"advapi32.dll"&lt;/span&gt;, SetLastError = &lt;span class="kwrd"&gt;true&lt;/span&gt;)]    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; LookupPrivilegeValue(&lt;span class="kwrd"&gt;string&lt;/span&gt; host, &lt;span class="kwrd"&gt;string&lt;/span&gt; name, &lt;span class="kwrd"&gt;ref&lt;/span&gt; &lt;span class="kwrd"&gt;long&lt;/span&gt; pluid);&amp;nbsp;    [DllImport(&lt;span class="str"&gt;"advapi32.dll"&lt;/span&gt;, ExactSpelling = &lt;span class="kwrd"&gt;true&lt;/span&gt;, SetLastError = &lt;span class="kwrd"&gt;true&lt;/span&gt;)]    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; AdjustTokenPrivileges(IntPtr htok, &lt;span class="kwrd"&gt;bool&lt;/span&gt; disall,        &lt;span class="kwrd"&gt;ref&lt;/span&gt; TokPriv1Luid newst, &lt;span class="kwrd"&gt;int&lt;/span&gt; len, IntPtr prev, IntPtr relen);&amp;nbsp;    [DllImport(&lt;span class="str"&gt;"user32.dll"&lt;/span&gt;, ExactSpelling = &lt;span class="kwrd"&gt;true&lt;/span&gt;, SetLastError = &lt;span class="kwrd"&gt;true&lt;/span&gt;)]    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;extern&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; ExitWindowsEx(&lt;span class="kwrd"&gt;int&lt;/span&gt; flg, &lt;span class="kwrd"&gt;int&lt;/span&gt; rea);&amp;nbsp;    &lt;span class="preproc"&gt;#endregion&lt;/span&gt;&amp;nbsp;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; SE_PRIVILEGE_ENABLED = 0x00000002;&amp;nbsp;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; TOKEN_QUERY = 0x00000008;&amp;nbsp;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; TOKEN_ADJUST_PRIVILEGES = 0x00000020;&amp;nbsp;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; SE_SHUTDOWN_NAME = &lt;span class="str"&gt;"SeShutdownPrivilege"&lt;/span&gt;;&amp;nbsp;    &lt;span class="preproc"&gt;#region&lt;/span&gt; Exit Windows Flags    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; EWX_LOGOFF = 0x00000000;&amp;nbsp;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; EWX_SHUTDOWN = 0x00000001;&amp;nbsp;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; EWX_REBOOT = 0x00000002;&amp;nbsp;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; EWX_FORCE = 0x00000004;&amp;nbsp;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; EWX_POWEROFF = 0x00000008;&amp;nbsp;    &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;int&lt;/span&gt; EWX_FORCEIFHUNG = 0x00000010;&amp;nbsp;    &lt;span class="preproc"&gt;#endregion&lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; DoExitWin(&lt;span class="kwrd"&gt;int&lt;/span&gt; flg)    {&amp;nbsp;        &lt;span class="rem"&gt;//give current process SeShutdownPrivilege&lt;/span&gt;        TokPriv1Luid tp;&amp;nbsp;        IntPtr hproc = GetCurrentProcess();&amp;nbsp;        IntPtr htok = IntPtr.Zero;&amp;nbsp;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!OpenProcessToken(hproc, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &lt;span class="kwrd"&gt;ref&lt;/span&gt; htok))        {            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&lt;span class="str"&gt;"Open Process Token fail"&lt;/span&gt;);        }&amp;nbsp;        tp.Count = 1;&amp;nbsp;        tp.Luid = 0;&amp;nbsp;        tp.Attr = SE_PRIVILEGE_ENABLED;&amp;nbsp;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!LookupPrivilegeValue(&lt;span class="kwrd"&gt;null&lt;/span&gt;, SE_SHUTDOWN_NAME, &lt;span class="kwrd"&gt;ref&lt;/span&gt; tp.Luid))        {            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&lt;span class="str"&gt;"Lookup Privilege Value fail"&lt;/span&gt;);        }&amp;nbsp;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!AdjustTokenPrivileges(htok, &lt;span class="kwrd"&gt;false&lt;/span&gt;, &lt;span class="kwrd"&gt;ref&lt;/span&gt; tp, 0, IntPtr.Zero, IntPtr.Zero))        {            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&lt;span class="str"&gt;"Adjust Token Privileges fail"&lt;/span&gt;);        }&amp;nbsp;        &lt;span class="rem"&gt;//Exit windows&lt;/span&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (!ExitWindowsEx(flg, 0))        {            &lt;span class="kwrd"&gt;throw&lt;/span&gt; &lt;span class="kwrd"&gt;new&lt;/span&gt; Exception(&lt;span class="str"&gt;"Exit Windows fail"&lt;/span&gt;);        }    }&amp;nbsp;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;    &lt;span class="rem"&gt;/// Reboot computer&lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="force"&amp;gt;force reboot&amp;lt;/param&amp;gt;&lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Reboot(&lt;span class="kwrd"&gt;bool&lt;/span&gt; force)    {        &lt;span class="kwrd"&gt;if&lt;/span&gt; (force)        {            DoExitWin(EWX_REBOOT | EWX_FORCE);        }        &lt;span class="kwrd"&gt;else&lt;/span&gt;        {            DoExitWin(EWX_REBOOT | EWX_FORCEIFHUNG);        }    }&amp;nbsp;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;    &lt;span class="rem"&gt;/// Reboot computer force if hung&lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Reboot()    {        Reboot(&lt;span class="kwrd"&gt;false&lt;/span&gt;);    }&amp;nbsp;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;    &lt;span class="rem"&gt;/// Shut down computer&lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="force"&amp;gt;force shut down&amp;lt;/param&amp;gt;&lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Shutdown(&lt;span class="kwrd"&gt;bool&lt;/span&gt; force)    {        &lt;span class="kwrd"&gt;if&lt;/span&gt; (force)        {            DoExitWin(EWX_SHUTDOWN | EWX_FORCE);        }        &lt;span class="kwrd"&gt;else&lt;/span&gt;        {            DoExitWin(EWX_SHUTDOWN | EWX_FORCEIFHUNG);        }    }&amp;nbsp;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;    &lt;span class="rem"&gt;/// Shut down computer force if hung&lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Shutdown()    {        Shutdown(&lt;span class="kwrd"&gt;false&lt;/span&gt;);    }&amp;nbsp;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;    &lt;span class="rem"&gt;/// Log off&lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;param name="force"&amp;gt;force logoff&amp;lt;/param&amp;gt;&lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Logoff(&lt;span class="kwrd"&gt;bool&lt;/span&gt; force)    {        &lt;span class="kwrd"&gt;if&lt;/span&gt; (force)        {            DoExitWin(EWX_LOGOFF | EWX_FORCE);        }        &lt;span class="kwrd"&gt;else&lt;/span&gt;        {            DoExitWin(EWX_LOGOFF | EWX_FORCEIFHUNG);        }    }&amp;nbsp;    &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;    &lt;span class="rem"&gt;/// logoff computer force if hung&lt;/span&gt;    &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Logoff()    {        Logoff(&lt;span class="kwrd"&gt;false&lt;/span&gt;);    }}&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt; &lt;img src="http://www.cnblogs.com/eaglet/aggbug/2445674.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/eaglet/archive/2012/04/13/2445674.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/eaglet/archive/2012/02/15/2352094.html</id><title type="text">HubbleDotNet 索引分词的测试方法和分词技巧</title><summary type="text">在中文搜索中，分词技术是一个比较关键的技术，我们往往会遇到查询某个关键字无法匹配到相应文档的问题，这种问题往往都是索引的分词不理想造成的，倒排索引的技术特点决定了如果查询的关键字不在索引的分词中，则无法查出相应的文档。为了帮助使用者分析分词问题，hubbledotnet 专门提供几个存储过程来帮助检查索引分词的情况。</summary><published>2012-02-15T01:27:00Z</published><updated>2012-02-15T01:27:00Z</updated><author><name>eaglet</name><uri>http://www.cnblogs.com/eaglet/</uri></author><link rel="alternate" href="http://www.cnblogs.com/eaglet/archive/2012/02/15/2352094.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/eaglet/archive/2012/02/15/2352094.html"/><content type="html">&lt;p&gt;在中文搜索中，分词技术是一个比较关键的技术，我们往往会遇到查询某个关键字无法匹配到相应文档的问题，这种问题往往都是索引的分词不理想造成的，倒排索引的技术特点决定了如果查询的关键字不在索引的分词中，则无法查出相应的文档。为了帮助使用者分析分词问题，hubbledotnet 专门提供几个存储过程来帮助检查索引分词的情况。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;分词的测试方法&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;首先要找到要测试的原始文本&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;我们往往发现某些记录包含有查询关键字，但查不出来，这个时候我们需要先找到这个出问题的记录的原始文本。查找原始文本的方法很多，你可以通过 docid 或者id 或者其他条件来查找。&lt;/p&gt;&lt;p&gt;下面给出一个通过 id 来查找的示例。如果我们发现id = 1 的记录 title 无法匹配出来，我们可以执行&lt;/p&gt;&lt;p&gt;select * from table where id = 1 找到记录的原始文本。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/eaglet/201202/20120215092621825.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/eaglet/201202/201202150926244710.png" width="755" height="245" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;找到原始文本后我们有两种方法来查看记录在索引中的分词情况。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;方法1： SP_TestAnalyzer &lt;/strong&gt;&lt;/p&gt;&lt;p&gt;SP_TestAnalyzer 这个存储过程用于测试分词器的分词结果，它的作用是在服务器侧执行分词器的 Tokenize 方法。 &lt;p&gt;这个存储过程有两个参数，第一个参数为分词器名字，这里我们输入 &amp;#8216;PanguSegment&amp;#8217;，第二个参数是要测试的句子。 &lt;p&gt;下面我们执行如下语句，看看效果SP_TestAnalyzer 'PanguSegment', '六方会谈无核化工作组会议将在沈阳召开'&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/eaglet/201202/2012021509262724.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/eaglet/201202/201202150926307846.png" width="621" height="456" /&gt;&lt;/a&gt; &lt;p&gt;如上图所示，执行后，可以看到分词的结果。从这个分词结果可以看到原始文本的分词有一些问题，比如无核化和工作组这两个词没有分出来，这时如果搜索&amp;#8221;工作组&amp;#8221;这个词，则无法匹配到这条记录。我们需要把无核化和工作组两个词加入到盘古的字典中再测试，如果分词正确了，重新索引后，问题就可以解决。 &lt;p&gt;&amp;nbsp; &lt;p&gt;&lt;strong&gt;方法2：SP_FieldAnalyze&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;SP_FieldAnalyze 这个存储过程是针对指定表的指定字段的分词器来分词 &lt;p&gt;它有4个参数，参数1为表名，参数2为字段名，参数3为要分词的句子，参数4指定是用 Tokenize 函数还是 TokenizedForSqlClient 函数来分词。第4个参数为可选参数， &lt;p&gt;如果不输入，就是以 Tokenize 函数分词，如果输入 &amp;#8216;SqlClient&amp;#8217; 就是以 TokenizedForSqlClient 函数来分词 &lt;p&gt;下面我们首先执行默认的情况，即用 Tokenize 函数分词SP_FieldAnalyze 'VNews', 'Title', '六方会谈无核化工作组会议将在沈阳召开'这个语句是采用 VNews 表的 Title 字段的分词器来对 '六方会谈无核化工作组会议将在沈阳召开' 这个句子进行分词，我们可以看出，分词的结果和方法1是一样的。&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/eaglet/201202/201202150926339015.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/eaglet/201202/201202150926363457.png" width="674" height="462" /&gt;&lt;/a&gt; &lt;p&gt;我们加上 SqlClient 参数后来分词看看效果：SP_FieldAnalyze 'VNews', 'Title', '六方会谈无核化工作组会议将在沈阳召开','SqlClient'&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/eaglet/201202/201202150926394626.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/eaglet/201202/201202150926422971.png" width="672" height="391" /&gt;&lt;/a&gt; &lt;p&gt;可以看到后面加了 SqlClient 后，分词结果不同了，这是因为 SqlClient 采用了不同的分词参数。对于盘古分词来说，如果调用 SqlClient 来分词，则服务器侧调用的是program/hubbledotnet/default/PanGuSqlClient.xml 这个配置文件来对文本进行分词，如果不加 SqlClient 参数，则是调用program/hubbledotnet/default/PanGu.xml 这个配置文件分词。 &lt;p&gt;SqlClient 的功能主要是帮助进行查询字符串的分词，HubbleCommand 这个类中有一个函数 GetKeywordAnalyzerStringFromServer 就是用于对查询字符串进行分词的，hubble 的示例代码中也是调用的这个函数，这个函数的里面实际上就是调用 SP_FieldAnalyze&amp;nbsp; 这个存储过程加 SqlClient 来分词。当然在实际项目中，使用着并不是必须要调用这个函数来对查询字符串进行分词，使用者可以用自己的程序对查询字符串分词。 &lt;p&gt;&lt;strong&gt;分词的技巧&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;对于搜索来说，查全率和查准率是一对矛盾，为了尽量平衡这对矛盾，我们在索引和查询时可以采用一些技巧。 &lt;p&gt;技巧1. &lt;p&gt;索引时最大化分词，如果是用盘古分词进行索引，索引时打开多元分词和强制一元分词。但对查询字符串的分词则采用精确分词，这样可以保证查准的情况下获得较大的查全率。 &lt;p&gt;技巧2. &lt;p&gt;同义词分词。对于同义词的分词，我们不要在索引中分词，而是在查询字符串中增加同义词的分解，这样可以使查询更灵活，并且可以在查询时设置原词和同义词不同的权重以影响得分排名。 &lt;p&gt;技巧3. &lt;p&gt;全部一元分词，然后通过索引组件来实现匹配，类似 like &amp;#8216;%xxx%&amp;#8217; 这样的功能。由于索引组件知道单词在原文本中的位置，所以理论上可以实现类似 like &amp;#8216;%xxx%&amp;#8217; 这样的功能，这种功能对于短文本的搜索比较有效，而且不需要关心中文的分词。hubbledotnet 将在未来的版本中提供这种方式的快速解决方案，目前版本提供了 like &amp;#8216;*xxx*&amp;#8217; 的功能，但这个功能还不够完善，速度比较慢。 &lt;p&gt;&lt;strong&gt;注意事项&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;索引分词的检查功能，实际上只是在server 端执行了对应的分词器来进行分词，并不是从倒排索引中查询出对应文本的分词结果。从倒排索引中获取分词结果需要遍历整个倒排索引，效率很低，所以hubble 没有提供这样的功能。由于是动态执行分词器分词，如果在索引过程中分词参数或字典调整过，则得到的结果有可能不是实际索引中的分词结果。&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;返回 &lt;a href="http://www.cnblogs.com/eaglet/archive/2010/04/07/1706305.html"&gt;Hubble.net 技术详解&lt;/a&gt; &lt;/p&gt;&lt;img src="http://www.cnblogs.com/eaglet/aggbug/2352094.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/eaglet/archive/2012/02/15/2352094.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/eaglet/archive/2012/02/14/2350501.html</id><title type="text">Windows 启动顺序详解</title><summary type="text">本文详细阐述 windows 操作系统的启动顺序，以方便IT从业者对windows 启动问题的分析和解决。</summary><published>2012-02-14T02:22:00Z</published><updated>2012-02-14T02:22:00Z</updated><author><name>eaglet</name><uri>http://www.cnblogs.com/eaglet/</uri></author><link rel="alternate" href="http://www.cnblogs.com/eaglet/archive/2012/02/14/2350501.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/eaglet/archive/2012/02/14/2350501.html"/><content type="html">&lt;p&gt;本文详细阐述 windows 操作系统的启动顺序，以方便IT从业者对windows 启动问题的分析和解决。&lt;/p&gt;&lt;p&gt;windows 的启动过程包括以下几个阶段：&lt;/p&gt;&lt;p&gt;&lt;strong&gt;启动自检阶段&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个阶段主要是读取 BIOS ，然后内存，CPU，硬盘，键盘等设备进行自检。这个阶段在屏幕上显示就是自检的那些打印信息。&lt;/p&gt;&lt;p&gt;&lt;font color="#0080ff"&gt;屏幕显示：自检的打印信息&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;初始化启动阶段&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个阶段根据 BIOS 指定的启动顺序，找到可以启动的优先启动设备，比如本地磁盘，CD Driver ， USB 设备等等，然后准备从这些设备启动系统。&lt;/p&gt;&lt;p&gt;&lt;font color="#0080ff"&gt;屏幕显示：黑屏&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Boot 加载阶段&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个阶段首先从启动分区(比如 C 盘) 加载 Ntldr ，然后Ntldr 做如下设置：&lt;/p&gt;&lt;ol&gt;&lt;li&gt;设置内存模式，如果是 x86 的处理器，并且操作系统是 32位，则设置为 32-bit flat memory mode, 如果是 64 位操作系统 + 64位处理器，则设置为64位内存模式。&lt;/li&gt;&lt;li&gt;启动文件系统&lt;/li&gt;&lt;li&gt;读取 boot.ini 文件&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;font color="#0080ff"&gt;屏幕显示：黑屏，如果按F8或者多系统时会显示启动选项菜单。&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt;&lt;p&gt;&lt;strong&gt;检测和配置硬件阶段&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个阶段检查和配置一些硬件设备，它们分别是：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;系统固件，比如时间和日期&lt;/li&gt;&lt;li&gt;总线和适配器&lt;/li&gt;&lt;li&gt;显示适配器&lt;/li&gt;&lt;li&gt;键盘&lt;/li&gt;&lt;li&gt;通讯端口&lt;/li&gt;&lt;li&gt;磁盘&lt;/li&gt;&lt;li&gt;软盘&lt;/li&gt;&lt;li&gt;输入设备（如鼠标)&lt;/li&gt;&lt;li&gt;并口&lt;/li&gt;&lt;li&gt;在ISA总线上运行的设备&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;font color="#0080ff"&gt;屏幕显示：黑屏&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&lt;font color="#0080ff"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;内核加载阶段&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;在内核加载阶段，Ntldr 将首先加载windows 内核 Ntoskrnl.exe 和 硬件抽象层 (HAL). HAL 有点类似于嵌入式操作系统下的BSP（Borad support package)，这个抽象层对硬件底层的特性进行隔离，对操作系统提供统一的调用接口，操作系统移植到不同硬件时只要改变相应的 HAL 就可以，其它的内核组件不需要修改，这个是操作系统通常的设计模式。&lt;/p&gt;&lt;p&gt;接下来Ntldr 从HKEY_LOCAL_ MACHINE\SYSTEM\CurrentControlSet 下读取这台机器安装的驱动程序，然后依次加载驱动程序。&lt;/p&gt;&lt;p&gt;驱动程序加载完成后，windows 做如下设置：&lt;/p&gt;&lt;p&gt;1. 创建系统环境变量&lt;/p&gt;&lt;p&gt;2. 启动 win32.sys ，这个是windows 子系统的内核模式部分。&lt;/p&gt;&lt;p&gt;3. 启动 csrss.exe，这个是windows 子系统的用户模式部分。&lt;/p&gt;&lt;p&gt;4. 启动 winlogon.exe&lt;/p&gt;&lt;p&gt;5. 创建虚拟内存页面文件&lt;/p&gt;&lt;p&gt;6. 对一些必要的文件进行改名，（主要是驱动文件，如果更新后，需要在下次重启前改名)&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;font color="#0080ff"&gt;屏幕显示：显示windows logo 界面和进度条&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;strong&gt;登录阶段&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这个阶段会做如下几件事：&lt;/p&gt;&lt;p&gt;1. 启动机器上安装的所有需要自动启动的 windows 服务&lt;/p&gt;&lt;p&gt;2. 启动本地安全认证 Lsass.exe&lt;/p&gt;&lt;p&gt;3. 显示登录界面&lt;/p&gt;&lt;p&gt;&lt;font color="#0080ff"&gt;屏幕显示：显示登录界面&lt;/font&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;本文参考如下文档： &lt;/p&gt;&lt;p&gt;&lt;a href="http://technet.microsoft.com/en-us/library/bb457123.aspx"&gt;Troubleshooting the Startup Process&lt;/a&gt;&lt;/p&gt;&lt;img src="http://www.cnblogs.com/eaglet/aggbug/2350501.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/eaglet/archive/2012/02/14/2350501.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/eaglet/archive/2012/02/13/2348603.html</id><title type="text">记录windows操作系统启动日志</title><summary type="text">在一些基于windows的设备中，我们希望在程序控制windows重启时，windows每次都能正常启动，但有时候windows会遇到种种原因无法启动，这时我们需要定位到底是在启动什么步骤时出错，为了定位故障原因，我们需要将windows 的启动日志记录下来。 记录启动日志的方式是 在 boot.ini 中加一个 /bootlog 的参数，加了这个参数后，机器重启后，会自动把启动的日志记录在 c:...</summary><published>2012-02-12T23:04:00Z</published><updated>2012-02-12T23:04:00Z</updated><author><name>eaglet</name><uri>http://www.cnblogs.com/eaglet/</uri></author><link rel="alternate" href="http://www.cnblogs.com/eaglet/archive/2012/02/13/2348603.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/eaglet/archive/2012/02/13/2348603.html"/><content type="html">&lt;p&gt;在一些基于windows的设备中，我们希望在程序控制windows重启时，windows每次都能正常启动，但有时候windows会遇到种种原因无法启动，这时我们需要定位到底是在启动什么步骤时出错，为了定位故障原因，我们需要将windows 的启动日志记录下来。&lt;/p&gt; &lt;p&gt;记录启动日志的方式是&lt;/p&gt; &lt;p&gt;在 boot.ini 中加一个 &lt;strong&gt;/bootlog&lt;/strong&gt; 的参数，加了这个参数后，机器重启后，会自动把启动的日志记录在 c:\windows 目录下的 ntbtlog.txt 文件中。通过查看这个日志文件，我们可以了解windows启动过程中的一些详细情况。&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;下面列出boot.ini 的所有参数：&lt;/p&gt; &lt;p&gt;转自：&lt;a href="http://support.microsoft.com/kb/833721"&gt;Windows XP 和 Windows Server 2003 的 Boot.ini 文件的可用开关选项&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;/basevideo&lt;/strong&gt;&lt;/p&gt;&lt;b&gt;/basevideo&lt;/b&gt; 开关通过使用与所有视频适配器都兼容的视频驱动程序来强制系统进入标准 640x480 16 色 VGA 模式。该开关允许您在选择了错误的视频分辨率或刷新频率时加载系统。请将该开关与 &lt;b&gt;/sos&lt;/b&gt; 开关一起使用。如果安装了新的视频驱动程序，而该驱动程序工作不正常，则可使用该参数来启动操作系统。然后可以删除、更新或回滚到有问题的视频驱动程序。  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/baudrate=&lt;var&gt;number&lt;/var&gt;&lt;/strong&gt;&lt;/p&gt;该开关设置用于内核调试的调试端口的波特率。例如，可键入 /baudrate=9600。在连接有调制解调器时，默认的波特率是每秒 9600 千位 (Kbps)。当使用假调制解调器电缆连接时，默认的波特率是 115,200 Kbps。9,600 是通过调制解调器进行远程调试的正常速率。如果在 Boot.ini 文件中存在该开关，则自动启用 &lt;b&gt;/debug&lt;/b&gt; 开关。 &lt;br&gt;有关调制解调器配置的其他信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/148954"&gt;148954&lt;/a&gt;&amp;nbsp; 如何使用调制解调器设置远程调试会话  &lt;p&gt;有关无调制解调器配置的其他信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/151981"&gt;151981&lt;/a&gt;&amp;nbsp; 如何使用无调制解调器电缆设置远程调试会话  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/crashdebug&lt;/strong&gt;&lt;/p&gt;该开关在启动操作系统时加载内核调试程序。该开关将保持非活动状态直到出现 Stop 错误消息。&lt;b&gt;/crashdebug&lt;/b&gt; 开关对于处理随机性内核错误非常有用。使用该开关，可在 Windows 运行时照常使用 COM 端口。当 Windows 出现故障时，该开关将把该端口转换为调试端口。（该操作将启动远程调试。） &lt;br&gt;有关更多信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/151981"&gt;151981&lt;/a&gt;&amp;nbsp; 如何使用无调制解调器电缆设置远程调试会话  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/debug&lt;/strong&gt;&lt;/p&gt;该开关在启动 Windows 时打开内核调试程序。如果想要通过 COM 端口打开 Windows 系统实时远程调试功能，则该开关可随时通过连接到计算机的主机调试程序激活。与 &lt;b&gt;/crashdebug&lt;/b&gt; 开关不同，&lt;b&gt;/debug&lt;/b&gt; 无论是否正在调试都将使用 COM 端口。当您在调试有规律地重复出现的问题时可使用该开关。 &lt;br&gt;有关远程调试的更多信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/121543"&gt;121543&lt;/a&gt;&amp;nbsp; 设置远程调试  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/debugport=com&lt;var&gt;number&lt;/var&gt;&lt;/strong&gt;&lt;/p&gt;该开关指定用作调试端口的通信端口，其中 &lt;var&gt;number&lt;/var&gt; 是要使用的通信端口，例如 COM1。默认情况下，如果 COM2 端口存在，则 &lt;b&gt;/debugport&lt;/b&gt; 将使用 COM2 端口。否则，该开关将使用 COM1。如果在 Boot.ini 文件中包含该开关，&lt;b&gt;/debug&lt;/b&gt; 开关将会被激活。 &lt;br&gt;有关其他信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/151981"&gt;151981&lt;/a&gt;&amp;nbsp; 如何使用无调制解调器电缆设置远程调试会话  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/maxmem=&lt;var&gt;number&lt;/var&gt;&lt;/strong&gt;&lt;/p&gt;该开关指定 Windows 可以使用的 RAM 数量（以字节为单位）。例如，如果您希望 Windows 使用少于 64 MB 的内存，则使用 &lt;b&gt;/maxmem=64&lt;/b&gt; 开关。 &lt;br&gt;但是，&lt;b&gt;/maxmem&lt;/b&gt; 开关不将内存空洞计算在内。 因此，我们建议您改为使用 &lt;b&gt;/burnmemory&lt;/b&gt; 开关。&lt;b&gt;/burnmemory&lt;/b&gt; 开关会将内存空洞计算在内。&lt;br&gt;例如，如果您使用 &lt;b&gt;/Maxmem=64&lt;/b&gt; 开关，而系统需要 64 MB 的内存才能加载，则由于存在内存空洞，系统实际可用的内存可能不足 64 MB。在这种情况下，Windows 将不会启动。 &lt;br&gt;有关更多信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/108393"&gt;108393&lt;/a&gt;&amp;nbsp; Windows Boot.ini 文件中的 /maxmem 开关  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/noguiboot&lt;/strong&gt;&lt;/p&gt;该开关禁用 Windows 启动时显示进度栏的位图。（进度栏就出现在登录提示之前。）  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/nodebug&lt;/strong&gt;&lt;/p&gt;该开关用于关闭调试功能。如果在某个程序软件中有硬件调试断点，这种情况可能导致出现 Stop 错误。  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/numproc=&lt;var&gt;number&lt;/var&gt;&lt;/strong&gt;&lt;/p&gt;该开关设置 Windows 启动时使用的处理器数。使用此开关，可以强制多处理器系统仅使用指定数量的处理器 (&lt;var&gt;number&lt;/var&gt;)。该开关可帮助您解决性能问题和有缺陷的 CPU 的问题。  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/pcilock&lt;/strong&gt;&lt;/p&gt;对于基于 x86 的系统，该开关阻止操作系统为 Peripheral Connect Interface (PCI) 设备动态分配硬件输入、硬件输出和中断请求资源。使用该开关，BIOS 可以配置这些设备。  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/fastdetect:com&lt;var&gt;number&lt;/var&gt;&lt;/strong&gt;&lt;/p&gt;该开关将关闭 Ntdetect.com 文件对指定端口上串行鼠标和总线鼠标的检测功能。如果在启动过程中您在串行端口上连接了除鼠标以外的组件，则可使用该开关。例如，键入 /fastdetect:com&lt;var&gt;number&lt;/var&gt;，其中 &lt;var&gt;number&lt;/var&gt; 是串行端口号。可使用逗号分隔多个端口号以关闭一个以上的端口。如果使用 &lt;b&gt;/fastdetect&lt;/b&gt; 但未指定通信端口，则将关闭所有通信端口上的串行鼠标检测功能。 &lt;br&gt;&lt;b&gt;注意&lt;/b&gt;：在包括 Windows NT 4.0 在内的 Windows 早期版本中，该开关被命名为 &lt;b&gt;/noserialmice&lt;/b&gt;。 &lt;br&gt;有关更多信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/131976"&gt;131976&lt;/a&gt;&amp;nbsp; 如何禁用串行端口上的设备检测  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/sos&lt;/strong&gt;&lt;/p&gt;&lt;b&gt;/sos&lt;/b&gt; 开关在设备驱动程序被加载时显示其名称。默认情况下，Windows Loader 屏幕仅显示进度点。可将该开关与 &lt;b&gt;/basevideo&lt;/b&gt; 开关一起使用以确定引发故障的驱动程序。 &lt;br&gt;有关更多信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/99743"&gt;99743&lt;/a&gt;&amp;nbsp; Windows 2000 或 Windows NT 中 BOOT.INI 文件的功能  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/PAE&lt;/strong&gt;&lt;/p&gt;在 Boot.ini 中使用 /PAE 开关及相应的条目可允许支持物理地址扩展 (PAE) 模式的计算机正常启动。在安全模式下，即使指定了 /PAE 开关，计算机也使用正常内核启动。  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/HAL=filename&lt;/strong&gt;&lt;/p&gt;使用该开关，可定义在启动过程中实际加载的硬件抽象层 (HAL)。例如，键入 /HAL=halmps.dll 加载 System32 文件夹中的 Halmps.dll。 该开关可用于在将该文件重命名为 Hal.dll 之前测试一个不同的 HAL。此外，该开关在您尝试在多处理器模式启动和单处理器模式启动之间进行切换时也很有用。为此，请将该开关与 &lt;b&gt;/kernel&lt;/b&gt; 开关一起使用。  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/kernel=filename&lt;/strong&gt;&lt;/p&gt;使用该开关，您可以定义在启动过程中实际加载的内核。例如，键入 /kernel=ntkrnlmp.exe 加载 System32 文件夹中的 Ntkrnlmp.exe。 使用该开关，您可以在启用了调试功能的满载调试代码的内核与正常内核之间进行切换。  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/bootlog&lt;/strong&gt;&lt;/p&gt;该开关打开启动日志记录功能，启动日志被记录到 &lt;var&gt;systemroot&lt;/var&gt;\Ntbtlog.txt 文件中。有关启动日志的更多信息，请参见 Windows 帮助。  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/burnmemory=&lt;var&gt;number&lt;/var&gt;&lt;/strong&gt;&lt;/p&gt;该开关指定 Windows 不能使用的内存数（以兆字节为单位）。可使用该参数来确定性能问题或其他与 RAM 消耗有关的问题。例如，键入 /burnmemory=128 将 Windows 可用的物理内存减少 128 MB。  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/3GB&lt;/strong&gt;&lt;/p&gt;该开关强制基于 x86 的系统为程序分配 3 GB 的虚拟地址空间，为内核及可执行组件分配 1 GB 的虚拟地址空间。程序在设计上必须能够利用额外的内存地址空间。使用该开关，用户模式程序能够访问 3 GB 的内存而不是通常 Windows 分配给用户模式程序的 2 GB 的内存。该开关将内核的内存起始位置移至 3 GB 处。某些 Microsoft Exchange Server 2003 和 Microsoft Windows Server 2003 的配置可能需要使用该开关。&lt;br&gt;有关更多信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/823440"&gt;823440&lt;/a&gt;&amp;nbsp; 在基于 Windows Server 2003 的系统上的 Exchange Server 2003 中使用 /3GB 开关  &lt;p&gt;有关更多信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/171793"&gt;171793 &lt;/a&gt;&amp;nbsp; 有关应用程序使用 4GT RAM 调节的信息  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/safeboot:&lt;var&gt;parameter&lt;/var&gt;&lt;/strong&gt;&lt;/p&gt;该开关使 Windows 以安全模式启动。该开关使用以下参数：  &lt;ul&gt; &lt;li&gt;minimal  &lt;li&gt;network  &lt;li&gt;safeboot:minimal(alternateshell)&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;/safeboot:parameter&lt;/b&gt; 参数可与其他 Boot.ini 参数结合使用。下面的示例给出了当从启动恢复菜单中选择一个安全模式选项时实际使用的参数。  &lt;ul&gt; &lt;li&gt;&lt;b&gt;带网络连接的安全模式&lt;/b&gt;&lt;br&gt;/safeboot:minimal /sos /bootlog /noguiboot  &lt;li&gt;&lt;b&gt;带网络连接的安全模式&lt;/b&gt;&lt;br&gt;/safeboot:network /sos /bootlog /noguiboot  &lt;li&gt;&lt;b&gt;带命令提示的安全模式&lt;/b&gt;&lt;br&gt;/safeboot:minimal(alternateshell) /sos /bootlog /noguiboot&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;注意&lt;/b&gt;：&lt;b&gt;/sos&lt;/b&gt;、&lt;b&gt;/bootlog&lt;/b&gt; 和 &lt;b&gt;/noguiboot&lt;/b&gt; 开关在这些设置中并不是必需的，但这些开关会有助于排除故障。当您按 F8 并选择一种模式后，这些开关会被采用。  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/userva &lt;/strong&gt;&lt;/p&gt;可使用该开关自定义当使用 /3GB 开关时分配给进程的内存量。该开关允许更多的页表项目 (PTE) 内核内存，同时仍然保留将近 3 GB 的进程内存空间。 &lt;br&gt;&lt;b&gt;注意&lt;/b&gt;：Microsoft 产品支持服务极力建议将对 /USERVA 开关使用的内存范围限制在 2900-3030 内。此范围足以为当前发现的所有问题提供足够大的系统页表项目池。通常，设置为 /userva=2900 时提供的数量与系统页表项目的最大可用数接近。&lt;br&gt;有关如何使用 /USERVA 开关的更多信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/316739"&gt;316739&lt;/a&gt;&amp;nbsp; 如何使用 /userva 和 /3GB 开关将用户模式空间调整为介于 2 GB 和 3 GB 之间的值  &lt;p&gt;有关更多信息，请单击下面的文章编号，以查看 Microsoft 知识库中相应的文章：  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/810371"&gt;810371&lt;/a&gt;&amp;nbsp; 在运行 Exchange Server 的基于 Windows Server 2003 的计算机上使用 /Userva 开关  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/323427"&gt;323427&lt;/a&gt;&amp;nbsp; 如何在 Windows Server 2003 环境中手动编辑 Boot.ini 文件  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/317526"&gt;317526&lt;/a&gt;&amp;nbsp; 如何在 Windows Server 2003 中编辑 Boot.ini 文件  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/317521"&gt;317521&lt;/a&gt;&amp;nbsp; BOOTCFG 命令及其用法说明  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/289022"&gt;289022&lt;/a&gt;&amp;nbsp; 如何在 Windows XP 中编辑 Boot.ini 文件  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/291980"&gt;291980&lt;/a&gt;&amp;nbsp; Bootcfg 命令及其用法讨论  &lt;p&gt;&lt;a href="http://support.microsoft.com/kb/833721#top"&gt;&lt;img alt="" src="http://support.microsoft.com/library/images/support/en-us/uparrow.gif"&gt;回到顶端&lt;/a&gt; &lt;p&gt;&lt;strong&gt;/redirect&lt;/strong&gt;&lt;/p&gt;可使用该开关在基于 Windows Server 2003 Enterprise Edition 的计算机上启用紧急管理服务 (EMS)。有关 EMS 的其他信息，请在“Windows 帮助和支持”中搜索“紧急管理服务”。 &lt;br&gt;要在基于 x86 的计算机上通过编辑 Boot.ini 来启用 EMS，需要编辑 Boot.ini 文件的“[boot loader]”和“[operating systems]”部分。为此，请配置下列条目： &lt;img src="http://www.cnblogs.com/eaglet/aggbug/2348603.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/eaglet/archive/2012/02/13/2348603.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/eaglet/archive/2011/12/05/2276668.html</id><title type="text">C# 程序自动批量生成 google maps 的KML文件</title><summary type="text">google maps 的 KML 文件可以用于静态的地图标注，在某些应用中，我们手上往往有成百上千个地址，我们需要把这些地址和描述批量标注到 google maps 上去，如果手工来做，太耗时间，在这里我写了一个程序批量来生成这个 KML 文件。</summary><published>2011-12-05T04:59:00Z</published><updated>2011-12-05T04:59:00Z</updated><author><name>eaglet</name><uri>http://www.cnblogs.com/eaglet/</uri></author><link rel="alternate" href="http://www.cnblogs.com/eaglet/archive/2011/12/05/2276668.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/eaglet/archive/2011/12/05/2276668.html"/><content type="html">&lt;p&gt;google maps 的 KML 文件可以用于静态的地图标注，在某些应用中，我们手上往往有成百上千个地址，我们需要把这些地址和描述批量标注到 google maps 上去，如果手工来做，太耗时间，在这里我写了一个程序批量来生成这个 KML 文件。&lt;/p&gt; &lt;p&gt;首先看一下 KML 文件的格式：&lt;/p&gt;&lt;span class="kwrd"&gt;&amp;lt;?&lt;/span&gt;&lt;span class="html"&gt;xml&lt;/span&gt; &lt;span class="attr"&gt;version&lt;/span&gt;&lt;span class="kwrd"&gt;="1.0"&lt;/span&gt; &lt;span class="attr"&gt;encoding&lt;/span&gt;&lt;span class="kwrd"&gt;="UTF-8"&lt;/span&gt;?&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;kml&lt;/span&gt; &lt;span class="attr"&gt;xmlns&lt;/span&gt;&lt;span class="kwrd"&gt;="http://www.google.com/earth/kml/2"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Document&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;kml_sample2.kml&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Style&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="red"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;IconStyle&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Icon&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;http://www.google.com/intl/en_us/mapfiles/ms/icons/red-dot.png&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Icon&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;IconStyle&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Style&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Style&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="green"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;IconStyle&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Icon&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;http://www.google.com/intl/en_us/mapfiles/ms/icons/green-dot.png&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Icon&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;IconStyle&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Style&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Style&lt;/span&gt; &lt;span class="attr"&gt;id&lt;/span&gt;&lt;span class="kwrd"&gt;="blue"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;IconStyle&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Icon&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;          &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;http://www.google.com/intl/en_us/mapfiles/ms/icons/blue-dot.png&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Icon&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;IconStyle&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Style&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Placemark&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Google Inc.&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;description&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[&lt;br/&gt;      Google Inc.&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;      1600 Amphitheatre Parkway&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;      Mountain View, CA 94043&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;      Phone: +1 650-253-0000&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;      Fax: +1 650-253-0001&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Home page: &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;a&lt;/span&gt; &lt;span class="attr"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;="http://www.google.com"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;www.google.com&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;a&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    ]]&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;description&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;styleUrl&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;#red&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;styleUrl&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; &lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Point&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;coordinates&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;-122.0841430, 37.4219720, 0&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;coordinates&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Point&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Placemark&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;  &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Placemark&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Yahoo! Inc.&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;name&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;description&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;!&lt;/span&gt;[CDATA[&lt;br/&gt;      Yahoo! Inc.&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;      701 First Avenue&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;      Sunnyvale, CA 94089&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;      Tel: (408) 349-3300&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;      Fax: (408) 349-3301&lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;br&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;Home page: &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;a&lt;/span&gt; &lt;span class="attr"&gt;href&lt;/span&gt;&lt;span class="kwrd"&gt;="http://yahoo.com"&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;http://yahoo.com&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;a&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;p&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;      ]]&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;description&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;styleUrl&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;#green&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;styleUrl&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt; &lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;Point&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;      &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;coordinates&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;-122.0250403,37.4163228&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;coordinates&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Point&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;  &lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Placemark&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;Document&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="html"&gt;kml&lt;/span&gt;&lt;span class="kwrd"&gt;&amp;gt;&lt;/span&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;&lt;p&gt;这个是一个典型的用于google maps 的 KML 文件，（注意不同应用的KML 格式会有所不同，比如 google earth 的 kml 格式就复杂得多)&lt;/p&gt;&lt;p&gt;从这个kml 文件格式来看，其实它就是一个 xml 文件，我们只要自动生成这个文件中各个元素的信息就可以得到这个xml&amp;nbsp; 文件。这里其实最大的问题是如何自动通过地址获取经纬度坐标。值得庆幸的是 google 提供了这方面的 api 函数。google api 获取地理坐标的官方例子见：&lt;a href="http://code.google.com/p/geocodingapi/" target="_blank"&gt;geocodingapi&lt;/a&gt;&lt;/p&gt;&lt;p&gt;我的实现稍微复杂一些，因为我需要在函数中为不同的位置自动分配颜色&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;summary&amp;gt;&lt;/span&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;        &lt;span class="rem"&gt;/// Generate placemark by address description&lt;/span&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;/summary&amp;gt;&lt;/span&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;param name="addrDescription"&amp;gt;address and description&amp;lt;/param&amp;gt;&lt;/span&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;        &lt;span class="rem"&gt;/// &amp;lt;returns&amp;gt;if no matched, return false&amp;lt;/returns&amp;gt;&lt;/span&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; Generate(AddressDescription addrDescription)&lt;span class="lnum"&gt;   7:  &lt;/span&gt;        {&lt;span class="lnum"&gt;   8:  &lt;/span&gt;            _LastErrorOrWarning = &lt;span class="kwrd"&gt;null&lt;/span&gt;;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;            Thread.Sleep(DelayInMs);&lt;span class="lnum"&gt;  11:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;            List&amp;lt;GeographicCoordinate&amp;gt; coordinates = Geocoding.Geocode(addrDescription.Address);&lt;span class="lnum"&gt;  13:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (coordinates.Count == 0)&lt;span class="lnum"&gt;  15:  &lt;/span&gt;            {&lt;span class="lnum"&gt;  16:  &lt;/span&gt;                _LastErrorOrWarning = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Address:{0}, Description:{1} does not find the coordinates, please make sure the address is correctly."&lt;/span&gt;,&lt;span class="lnum"&gt;  17:  &lt;/span&gt;                    addrDescription.Address, addrDescription.Description);&lt;span class="lnum"&gt;  18:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;false&lt;/span&gt;;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;            }&lt;span class="lnum"&gt;  21:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (coordinates.Count &amp;gt; 1)&lt;span class="lnum"&gt;  23:  &lt;/span&gt;            {&lt;span class="lnum"&gt;  24:  &lt;/span&gt;                _LastErrorOrWarning = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"Address:{0}, Description:{1} has more than one coordinates."&lt;/span&gt;,&lt;span class="lnum"&gt;  25:  &lt;/span&gt;                    addrDescription.Address, addrDescription.Description);&lt;span class="lnum"&gt;  26:  &lt;/span&gt;            }&lt;span class="lnum"&gt;  27:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;            &lt;span class="kwrd"&gt;string&lt;/span&gt; colorId = Colors[_ColorIndex];&lt;span class="lnum"&gt;  29:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;            _ColorIndex++;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (_ColorIndex &amp;gt;= Colors.Count)&lt;span class="lnum"&gt;  33:  &lt;/span&gt;            {&lt;span class="lnum"&gt;  34:  &lt;/span&gt;                _ColorIndex = 0;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;            }&lt;span class="lnum"&gt;  36:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;            _Kml.Document.Add(&lt;span class="kwrd"&gt;new&lt;/span&gt; Placemark(addrDescription.Address, addrDescription.Description, colorId,&lt;span class="lnum"&gt;  38:  &lt;/span&gt;                coordinates[0].Latitude, coordinates[0].Longitude));&lt;span class="lnum"&gt;  39:  &lt;/span&gt;&amp;nbsp;&lt;span class="lnum"&gt;  40:  &lt;/span&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;span class="lnum"&gt;  41:  &lt;/span&gt;        }&lt;/div&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;第32行有个bug，应该是 &amp;gt;=&amp;nbsp; ，我原来写成 &amp;gt; 了，博客中我改过来了，源码我就不改了。 &lt;br /&gt;&lt;/p&gt;&lt;p&gt;如上代码，第12行就是通过GeocodingApi 获取指定地址的物理坐标，由于有时候获取不到坐标，有时候由于地址不确切，有多个坐标，所以我加了一个错误和警告的属性，用于调用者得到相关的信息。&lt;/p&gt;&lt;p&gt;_Kml 这个对象是一个 Kml 类的实例，这个类用于生成 KML 文件结构，并可以保存到KML文件中。这个类在后面介绍。&lt;/p&gt;&lt;p&gt;下面的 _Color 部分是自动的顺序分配标注点的颜色，我为了省事，在代码中写死了4种颜色，你也可以修改代码增加颜色或其他图标。&lt;/p&gt;&lt;p&gt;标注颜色这里其实还有一个问题，就是如果让相邻的节点显示不同颜色，这个算法比较复杂了，我没有实现，各位如果有兴趣可以思考一下这个怎么做。&lt;/p&gt;&lt;p&gt;好了，最大的问题解决了，剩下就是写 xml&amp;nbsp; 文件了，这个很简单，我就不深入讲了，直接把代码贴出来。&lt;/p&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System;&lt;br/&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;br/&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Linq;&lt;br/&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Text;&lt;br/&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Xml;&lt;br/&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.Xml.Serialization;&lt;br/&gt;&lt;span class="kwrd"&gt;using&lt;/span&gt; System.IO;&lt;br/&gt;&lt;br/&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; GenerateKML&lt;br/&gt;{&lt;br/&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; Placemark&lt;br/&gt;    {&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; KMLPoint&lt;br/&gt;        {&lt;br/&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; KMLPoint()&lt;br/&gt;            {&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; KMLPoint(&lt;span class="kwrd"&gt;double&lt;/span&gt; latitude, &lt;span class="kwrd"&gt;double&lt;/span&gt; longitude)&lt;br/&gt;            {&lt;br/&gt;                SetCoordinates(latitude, longitude);&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;            &lt;span class="kwrd"&gt;private&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; _coordinates;&lt;br/&gt;&lt;br/&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SetCoordinates(&lt;span class="kwrd"&gt;double&lt;/span&gt; latitude, &lt;span class="kwrd"&gt;double&lt;/span&gt; longitude)&lt;br/&gt;            {&lt;br/&gt;                _coordinates = longitude.ToString() + &lt;span class="str"&gt;","&lt;/span&gt; + latitude.ToString();&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;            &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; coordinates&lt;br/&gt;            {&lt;br/&gt;                get&lt;br/&gt;                {&lt;br/&gt;                    &lt;span class="kwrd"&gt;return&lt;/span&gt; _coordinates;&lt;br/&gt;                }&lt;br/&gt;&lt;br/&gt;                set&lt;br/&gt;                {&lt;br/&gt;                    _coordinates = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        [XmlElement(&lt;span class="str"&gt;"name"&lt;/span&gt;)]&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Name { get; set; }&lt;br/&gt;&lt;br/&gt;        [XmlElement(&lt;span class="str"&gt;"description"&lt;/span&gt;)]&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; Description { get; set; }&lt;br/&gt;&lt;br/&gt;        [XmlElement(&lt;span class="str"&gt;"styleUrl"&lt;/span&gt;)]&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;string&lt;/span&gt; StyleUrl { get; set; }&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; KMLPoint Point { get; set; }&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Placemark()&lt;br/&gt;        {&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; Placemark(&lt;span class="kwrd"&gt;string&lt;/span&gt; name, &lt;span class="kwrd"&gt;string&lt;/span&gt; description, &lt;span class="kwrd"&gt;string&lt;/span&gt; styleUrl,&lt;br/&gt;            &lt;span class="kwrd"&gt;double&lt;/span&gt; latitude, &lt;span class="kwrd"&gt;double&lt;/span&gt; longitude)&lt;br/&gt;        {&lt;br/&gt;            Name = name;&lt;br/&gt;            Description = description;&lt;br/&gt;            StyleUrl = styleUrl;&lt;br/&gt;&lt;br/&gt;            Point = &lt;span class="kwrd"&gt;new&lt;/span&gt; KMLPoint(latitude, longitude);&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; kml&lt;br/&gt;    {&lt;br/&gt;        [XmlIgnore]&lt;br/&gt;        &lt;span class="kwrd"&gt;string&lt;/span&gt; Name { get; set; }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;        List&amp;lt;Placemark&amp;gt; _Placemarks = &lt;span class="kwrd"&gt;new&lt;/span&gt; List&amp;lt;Placemark&amp;gt;();&lt;br/&gt;&lt;br/&gt;        [XmlArray()]&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; List&amp;lt;Placemark&amp;gt; Document&lt;br/&gt;        {&lt;br/&gt;            get&lt;br/&gt;            {&lt;br/&gt;                &lt;span class="kwrd"&gt;return&lt;/span&gt; _Placemarks;&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;            set&lt;br/&gt;            {&lt;br/&gt;                _Placemarks = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;br/&gt;            }&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; kml()&lt;br/&gt;        {&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; kml(&lt;span class="kwrd"&gt;string&lt;/span&gt; name)&lt;br/&gt;        {&lt;br/&gt;            Name = name;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;private&lt;/span&gt; XmlNode GetColorStyle(XmlDocument xmlDoc,  &lt;span class="kwrd"&gt;string&lt;/span&gt; color)&lt;br/&gt;        {&lt;br/&gt;            XmlNode style = xmlDoc.CreateNode(XmlNodeType.Element, &lt;span class="str"&gt;"Style"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;);&lt;br/&gt;            XmlAttribute attr = style.OwnerDocument.CreateAttribute(&lt;span class="str"&gt;"id"&lt;/span&gt;);&lt;br/&gt;            attr.Value = color;&lt;br/&gt;            style.Attributes.Append(attr);&lt;br/&gt;&lt;br/&gt;            XmlNode iconStyle = xmlDoc.CreateNode(XmlNodeType.Element, &lt;span class="str"&gt;"IconStyle"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;);&lt;br/&gt;            XmlNode icon = xmlDoc.CreateNode(XmlNodeType.Element, &lt;span class="str"&gt;"Icon"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;);&lt;br/&gt;            XmlNode href = xmlDoc.CreateNode(XmlNodeType.Element, &lt;span class="str"&gt;"href"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;);&lt;br/&gt;            href.InnerText = &lt;span class="kwrd"&gt;string&lt;/span&gt;.Format(&lt;span class="str"&gt;"http://www.google.com/intl/en_us/mapfiles/ms/icons/{0}-dot.png"&lt;/span&gt;,&lt;br/&gt;                color);&lt;br/&gt;            &lt;br/&gt;            &lt;br/&gt;            style.AppendChild(iconStyle);&lt;br/&gt;            iconStyle.AppendChild(icon);&lt;br/&gt;            icon.AppendChild(href);&lt;br/&gt;&lt;br/&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; style;&lt;br/&gt;        }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;        &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; SaveToFile(&lt;span class="kwrd"&gt;string&lt;/span&gt; xml)&lt;br/&gt;        {&lt;br/&gt;            &lt;span class="kwrd"&gt;using&lt;/span&gt; (FileStream fs = &lt;span class="kwrd"&gt;new&lt;/span&gt; FileStream(xml, FileMode.Create, FileAccess.ReadWrite))&lt;br/&gt;            {&lt;br/&gt;                &lt;span class="kwrd"&gt;using&lt;/span&gt; (StreamWriter sw = &lt;span class="kwrd"&gt;new&lt;/span&gt; StreamWriter(fs, System.Text.Encoding.UTF8))&lt;br/&gt;                {&lt;br/&gt;                    XmlSerializer serializer = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlSerializer(&lt;span class="kwrd"&gt;this&lt;/span&gt;.GetType());&lt;br/&gt;                    serializer.Serialize(sw, &lt;span class="kwrd"&gt;this&lt;/span&gt;);&lt;br/&gt;                }&lt;br/&gt;            }&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;            XmlDocument xmlDoc = &lt;span class="kwrd"&gt;new&lt;/span&gt; XmlDocument();&lt;br/&gt;            xmlDoc.Load(xml);&lt;br/&gt;            xmlDoc.CreateXmlDeclaration(&lt;span class="str"&gt;"1.0"&lt;/span&gt;, &lt;span class="str"&gt;"utf-8"&lt;/span&gt;, &lt;span class="kwrd"&gt;null&lt;/span&gt;);&lt;br/&gt;&lt;br/&gt;            XmlNode documentNode = xmlDoc.SelectSingleNode(&lt;span class="str"&gt;@"/kml/Document"&lt;/span&gt;);&lt;br/&gt;&lt;br/&gt;            XmlNode nameNode = xmlDoc.CreateNode(XmlNodeType.Element, &lt;span class="str"&gt;"name"&lt;/span&gt;, &lt;span class="str"&gt;""&lt;/span&gt;);&lt;br/&gt;            nameNode.InnerText = &lt;span class="kwrd"&gt;this&lt;/span&gt;.Name;&lt;br/&gt;&lt;br/&gt;            XmlNode placeMarkNode = documentNode.FirstChild;&lt;br/&gt;            documentNode.InsertBefore(nameNode, placeMarkNode);&lt;br/&gt;&lt;br/&gt;            documentNode.InsertBefore(GetColorStyle(xmlDoc, &lt;span class="str"&gt;"red"&lt;/span&gt;), placeMarkNode);&lt;br/&gt;            documentNode.InsertBefore(GetColorStyle(xmlDoc, &lt;span class="str"&gt;"green"&lt;/span&gt;), placeMarkNode);&lt;br/&gt;            documentNode.InsertBefore(GetColorStyle(xmlDoc, &lt;span class="str"&gt;"blue"&lt;/span&gt;), placeMarkNode);&lt;br/&gt;            documentNode.InsertBefore(GetColorStyle(xmlDoc, &lt;span class="str"&gt;"yellow"&lt;/span&gt;), placeMarkNode);&lt;br/&gt;&lt;br/&gt;            XmlNode kmlNode = xmlDoc.SelectSingleNode(&lt;span class="str"&gt;@"/kml"&lt;/span&gt;);&lt;br/&gt;&lt;br/&gt;            XmlAttribute attr = kmlNode.OwnerDocument.CreateAttribute(&lt;span class="str"&gt;"xmlns"&lt;/span&gt;);&lt;br/&gt;            attr.Value = &lt;span class="str"&gt;"http://earth.google.com/kml/2.0"&lt;/span&gt;;&lt;br/&gt;&lt;br/&gt;            kmlNode.Attributes.Append(attr);&lt;br/&gt;&lt;br/&gt;            xmlDoc.Save(xml);&lt;br/&gt;        }&lt;br/&gt;    }&lt;br/&gt;&lt;br/&gt;}&lt;br/&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;&lt;p&gt;下面看一下调用的方法，使用者如果不想仔细研究细节，那就关注这个就可以了，调用方法非常简单&lt;/p&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;        {&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;            Generator kmlGenerator = &lt;span class="kwrd"&gt;new&lt;/span&gt; Generator(&lt;span class="str"&gt;"Test"&lt;/span&gt;);&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;            kmlGenerator.Generate(&lt;span class="kwrd"&gt;new&lt;/span&gt; AddressDescription(&lt;span class="str"&gt;"1600 Amphitheatre Parkway, Mountain View, CA 94043"&lt;/span&gt;,&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;                &lt;span class="str"&gt;"Google"&lt;/span&gt;));&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;            {&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;                Console.WriteLine(kmlGenerator.LastErrorOrWarning);&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;            }&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  13:  &lt;/span&gt;            kmlGenerator.Generate(&lt;span class="kwrd"&gt;new&lt;/span&gt; AddressDescription(&lt;span class="str"&gt;"1 Microsoft Way, Redmond, WA 98052"&lt;/span&gt;,&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  14:  &lt;/span&gt;                &lt;span class="str"&gt;"Microsoft"&lt;/span&gt;));&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  15:  &lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  16:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  17:  &lt;/span&gt;            {&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  18:  &lt;/span&gt;                Console.WriteLine(kmlGenerator.LastErrorOrWarning);&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  19:  &lt;/span&gt;            }&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  20:  &lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  21:  &lt;/span&gt;            kmlGenerator.Generate(&lt;span class="kwrd"&gt;new&lt;/span&gt; AddressDescription(&lt;span class="str"&gt;"1601 S. California Ave., Palo Alto, CA 95304"&lt;/span&gt;,&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  22:  &lt;/span&gt;                &lt;span class="str"&gt;"Facebook"&lt;/span&gt;));&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  23:  &lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  24:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  25:  &lt;/span&gt;            {&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  26:  &lt;/span&gt;                Console.WriteLine(kmlGenerator.LastErrorOrWarning);&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  27:  &lt;/span&gt;            }&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  28:  &lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  29:  &lt;/span&gt;            kmlGenerator.Generate(&lt;span class="kwrd"&gt;new&lt;/span&gt; AddressDescription(&lt;span class="str"&gt;"701 First Ave, Sunnyvale, CA 94089"&lt;/span&gt;,&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  30:  &lt;/span&gt;                &lt;span class="str"&gt;"Yahoo"&lt;/span&gt;));&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  31:  &lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  32:  &lt;/span&gt;            &lt;span class="kwrd"&gt;if&lt;/span&gt; (!&lt;span class="kwrd"&gt;string&lt;/span&gt;.IsNullOrEmpty(kmlGenerator.LastErrorOrWarning))&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  33:  &lt;/span&gt;            {&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  34:  &lt;/span&gt;                Console.WriteLine(kmlGenerator.LastErrorOrWarning);&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  35:  &lt;/span&gt;            }&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  36:  &lt;/span&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  37:  &lt;/span&gt;            kmlGenerator.Save(&lt;span class="str"&gt;"test.kml"&lt;/span&gt;);&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  38:  &lt;/span&gt;        }&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;span class="lnum"&gt;  39:  &lt;/span&gt;    }&lt;/div&gt;&lt;div class="csharpcode"&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;第三行，实例化 KML 生成器，并指定一个名字，这个名字对于 kml 文档中的 name 字段。&lt;/div&gt;&lt;div class="csharpcode"&gt;第五行，在kml 文件中标注 google 总部的地址&lt;/div&gt;&lt;div class="csharpcode"&gt;第八行，判断是否有最新的错误，每次执行第五行的Generate 方法，会将最新错误清空，所以这里永远是得到最近一次调用 Generate 方法的错误或警告。&lt;/div&gt;&lt;div class="csharpcode"&gt;后面以此类推了。&lt;/div&gt;&lt;div class="csharpcode"&gt;最后 Save 到一个kml文件中就OK了。&lt;/div&gt;&lt;div class="csharpcode"&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;最后，我们可以把这个 kml 文件导入到我们自己创建的 google map 中。这个在 google maps 里面有相应的导入功能，这里就不介绍了。&lt;/div&gt;&lt;div class="csharpcode"&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;完整源码下载&lt;/div&gt;&lt;div class="csharpcode"&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;&lt;a href="http://files.cnblogs.com/eaglet/GenerateKML.zip"&gt;完整源码&lt;/a&gt;&lt;/div&gt;&lt;div class="csharpcode"&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;注意源码中 app.config 文件中&lt;/div&gt;&lt;div class="csharpcode"&gt;&amp;nbsp;&lt;/div&gt;&lt;div class="csharpcode"&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;="GeocodingApi.Key"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="google api key"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;br/&gt;    &lt;span class="kwrd"&gt;&amp;lt;&lt;/span&gt;&lt;span class="html"&gt;add&lt;/span&gt; &lt;span class="attr"&gt;key&lt;/span&gt;&lt;span class="kwrd"&gt;="GeocodingApi.Url"&lt;/span&gt; &lt;span class="attr"&gt;value&lt;/span&gt;&lt;span class="kwrd"&gt;="http://maps.google.com/maps/geo?"&lt;/span&gt; &lt;span class="kwrd"&gt;/&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;p&gt;GeocodingApi.key 这里要填写你自己的 google api key，你可以在 google&amp;nbsp; 网站上获取，地址如下：&lt;/p&gt;&lt;p&gt;&lt;a title="http://code.google.com/apis/maps/signup.html" href="http://code.google.com/apis/maps/signup.html"&gt;http://code.google.com/apis/maps/signup.html&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;/p&gt;&lt;p&gt;&lt;font face="Consolas" size="2"&gt;&lt;/font&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="csharpcode"&gt;&amp;nbsp;&lt;/div&gt;&lt;style type="text/css"&gt;.csharpcode, .csharpcode pre{font-size: small;color: black;font-family: consolas, "Courier New", courier, monospace;background-color: #ffffff;/*white-space: pre;*/}.csharpcode pre { margin: 0em; }.csharpcode .rem { color: #008000; }.csharpcode .kwrd { color: #0000ff; }.csharpcode .str { color: #006080; }.csharpcode .op { color: #0000c0; }.csharpcode .preproc { color: #cc6633; }.csharpcode .asp { background-color: #ffff00; }.csharpcode .html { color: #800000; }.csharpcode .attr { color: #ff0000; }.csharpcode .alt {background-color: #f4f4f4;width: 100%;margin: 0em;}.csharpcode .lnum { color: #606060; }&lt;/style&gt;&lt;img src="http://www.cnblogs.com/eaglet/aggbug/2276668.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/eaglet/archive/2011/12/05/2276668.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry><entry><id>http://www.cnblogs.com/eaglet/archive/2011/11/01/2231021.html</id><title type="text">通过 Windows 7 共享上网</title><summary type="text">要实现多台机器共享上网通常有两种方法，一种是通过路由器共享上网，一种是通过软网关共享上网。在某些情况下，比如要通过3G，或4G无线网卡共享上网，我们需要特殊的3G或4G无线路由器才能共享，在没有这种路由器的情况下，我们只能通过软件共享上网。windows 7 提供了这样的共享功能，而且配置非常简单。</summary><published>2011-11-01T01:41:00Z</published><updated>2011-11-01T01:41:00Z</updated><author><name>eaglet</name><uri>http://www.cnblogs.com/eaglet/</uri></author><link rel="alternate" href="http://www.cnblogs.com/eaglet/archive/2011/11/01/2231021.html"/><link rel="alternate" type="text/html" href="http://www.cnblogs.com/eaglet/archive/2011/11/01/2231021.html"/><content type="html">&lt;p&gt;要实现多台机器共享上网通常有两种方法，一种是通过路由器共享上网，一种是通过软网关共享上网。在某些情况下，比如要通过3G，或4G无线网卡共享上网，我们需要特殊的3G或4G无线路由器才能共享，在没有这种路由器的情况下，我们只能通过软件共享上网。windows 7 提供了这样的共享功能，而且配置非常简单。下面我就把我如何配置办公室的共享上网的步骤写下来，供大家参考。&lt;/p&gt;&lt;p&gt;在开始这篇文章之前，我先介绍一下我的网络环境。&lt;/p&gt;&lt;p&gt;办公室里面有一台台式电脑，操作系统是 windows 7 professional 64bit。 通过 4G 无线网卡上网，上网速度为 20Mbps(下行)/16Mbps(上行)。一台无线路由器，若干办公电脑和网络打印机。没有有线的上网线路。其实普通的 ADSL2+ 的下行速度在我们这里最高只能达到10Mbps，还不如 4G 无线网卡的速度快。注：中国大陆地区目前好像还没有开通4G无线网络，不过无所谓，电脑只要能上网就可以进行共享。&lt;/p&gt;&lt;p&gt;我的目标就是让所有的设备都通过4G无线网卡访问 internet.&lt;/p&gt;&lt;p&gt;首先考虑的是通过路由器来共享，但由于 4G 无线网络在澳大利亚刚刚开通才一个月，还没有相应的无线路由器，找到一个3G的无线路由器 NetComm 的 N3G002W。如下图所示：&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/eaglet/201111/201111010940103830.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/eaglet/201111/201111010940145909.png" width="323" height="323" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;测试了一下，不支持4G无线网卡，只支持3G的，不过3G的无线网卡上网速度实在太慢了，放弃这个想法。&lt;/p&gt;&lt;p&gt;既然不能通过路由器共享，接下来就只能通过软网关来共享上网了。一开始我并不知道 windows 7 自带有类似的功能，在网上找了两个软网关，一个是WinRoute,这个软件是收费的，399美元，而且从网站说明上看，不支持 windows 7. 还有一个是 AnyRouter，这个软件有免费版本，但界面是中文的（公司里面只有我能看懂中文) ，而且从网站说明上看好像也不支持 windows 7。看来都不符合我的要求。还是 google 吧。一搜不要紧，发现windows 7 本身就自带 internet share 的功能，叫 ICS (Internet Connection Sharing)。 参见 &lt;a href="http://windows.microsoft.com/en-AU/windows-vista/Using-ICS-Internet-Connection-Sharing" target="_blank"&gt;Using ICS (Internet Connection Sharing)&lt;/a&gt;&lt;/p&gt;&lt;p&gt;下面就把我的设置步骤说明一下，很简单。&lt;/p&gt;&lt;p&gt;首先进入 Control Panel-&amp;gt;Network and Internet-&amp;gt;Network and Sharing Center，如下图&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/eaglet/201111/201111010940177498.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/eaglet/201111/201111010940212990.png" width="610" height="206" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;这里有个 Telstra Mobile 的网络适配器，这个就是我前面说的 4G 无线网卡的网络适配器，那个台式机就是通过这个无线网卡上网的。点圆圈里面那个蓝色链接再点 Properites(中文系统这里应该是 属性)。进入到这个网络适配器的属性配置。&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/eaglet/201111/201111010940233872.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/eaglet/201111/201111010940269082.png" width="350" height="439" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;在属性设置中，选第二个tab-&amp;gt;Sharing （共享），然后将我红圈部分选中就可以了。下面有一个 Home networking connection 要选择一下，这个设置的意思是通过哪个网络适配器进行共享。通常情况下我们都是通过本地的以太网网卡进行共享，在这里我选择的是本地网络的网络适配器。&lt;/p&gt;&lt;p&gt;点OK后，会有个提示，说本地网络适配器的IP地址将被强行改为 192.168.137.1，这是因为要做软网关，需要一个固定IP地址，windows 7 就强行把这个地址固定在了192.168.137.1 上了。点确认，设置结束。&lt;/p&gt;&lt;p&gt;下面的工作就是配置路由器了。&lt;/p&gt;&lt;p&gt;路由器的链接方法是用直连网线连接路由器的LAN 口和上面那个 windows 7 的台式机的本地网卡。可能也可以连WAN 口，然后配置为级联，不过我没有试过。&lt;/p&gt;&lt;p&gt;路由器的配置方法如下：&lt;/p&gt;&lt;p&gt;首先路由器的IP网段要设置为 192.168.137.* 这个网段(当然也可以用级联)，直接改了路由器的本地IP地址为 192.168.137.2 ，这样网段就一致了。&lt;/p&gt;&lt;p&gt;然后就是配置网关和DNS 地址，这两个地址都设置为 192.168.137.1，即指向 windows 7 的软网关，如下图所示：&lt;/p&gt;&lt;p&gt;&lt;a href="http://images.cnblogs.com/cnblogs_com/eaglet/201111/201111010940277521.png"&gt;&lt;img style="border-bottom: 0px; border-left: 0px; display: inline; border-top: 0px; border-right: 0px" title="image" border="0" alt="image" src="http://images.cnblogs.com/cnblogs_com/eaglet/201111/201111010940304225.png" width="473" height="176" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;有的路由器还要手工设置一下 DHCP 的地址范围，比如设置为 192.168.137.100 &amp;#8211; 192.168.137.254&lt;/p&gt;&lt;p&gt;配置好后，重启路由器。&lt;/p&gt;&lt;p&gt;打开我的笔记本电脑，用无线网卡连接无线路由器自动获取IP地址后，测试了一下，可以正常访问internet 了。至此配置结束。&lt;/p&gt;&lt;img src="http://www.cnblogs.com/eaglet/aggbug/2231021.html?type=1" width="1" height="1" alt=""/&gt;&lt;p&gt;&lt;a href="http://www.cnblogs.com/eaglet/archive/2011/11/01/2231021.html" target="_blank"&gt;本文链接&lt;/a&gt;&lt;/p&gt;</content></entry></feed>
