Hello World
Spiga

关于排错:专注思考,细心观察,步步为营

2009-10-14 14:27 by 老赵, 17085 visits

时常有朋友发邮件给我,说遇到了一个什么什么奇怪的问题,不知道是怎么回事,希望我帮忙看看。我基本上每天都会抽出或长或短的时间来回复这些邮件,不过也经常发现,其实许许多多的问题都完全是有能力自行解决的。在很多时候,我发现许多朋友还缺乏最基本的解决问题,分析问题的方式。其实我在平时工作中也会遇到各种各样的问题,有时候甚至异常古怪,但是在仔细分析之下,往往都能解决。于是我现在打算谈点解决问题的基本方式,希望可以帮到一些朋友。

如果您也有着方面的体会,也可以分享一下,即使是某个简单案例也是很有帮助的。

要解决问题,首先是要定位问题,配合正确的推理方式,再仔细分析,“动手尝试”很可能只是验证推理是否正确的手段而已,其实大部分的情况都可以用思考来得出(或排除)。要定位问题,很重要的一点便是要把概念理清。很多朋友会轻视概念,认为那种“理论”有什么重要的,最关键的是“动手”——但殊不知概念能让您的“动手”少走很多弯路。

例如,在一个问题出现之后,我往往会心想,这到底是“开发时”还是“运行时”的问题。我们在做开发时会用到许多概念,有些是“开发时”的概念,有些则是“运行时”的概念。我们开发会用到很多工具,Visual Studio是一个大工具,但是它也会把很多功能,如“编译”等操作委托给外部的命令,VS只负责捕获那些输出而已。而在运行的时候,根本不会关VS什么事情。之前我写过一篇文章,指出csproj,sln等等都是开发时的概念,它们离开了Visual Studio,MSBuild等开发工具之后,就没有任何作用了。同样,“项目模板”也是Vistual Studio才知道的东西,而运行的根本不会关心所谓的ASP.NET Web Site还是Web Application。

于是,许多问题的排错就可以有大致的方向了。许多做ASP.NET的朋友都会问:“为什么我创建的ASP.NET AJAX项目可以运行”,但是用“ASP.NET Web Application”创建的项目就没法使用ASP.NET AJAX了呢?很明显,这个问题的关键不在“使用什么模板创建的项目”,而是这个项目中的内容是否可以执行,更确切地说,是某个文件夹下的内容能否使用ASP.NET AJAX——因为对于IIS来说,它不会关心“项目”(也就是csproj文件)在管理哪些资源,它只知道“网站目录”。

好,既然知道是网站内容的问题,那么接下来就应该比较的是“一个可以运行的网站”和“一个不能运行的网站”究竟有什么区别。ASP.NET站点最关键的东西便在于web.config,“能够运行”往往也是web.config来决定的。例如,你有没有正确配置HttpModule或HttpHandler。在许多情况下,解决了ASP.NET站点的web.config,问题也就解决了大半。同样的情况还会有,为什么同样的代码(标记)在有的aspx上就能解析成功,有的就不行?那可能是web.config中没有引入正确的control标记或命名空间造成的。

有朋友可能会说,你知道web.config的那么多节点是做什么的,自然容易排错,我都不知道,怎么知道问题在哪里?其实,我也不知道很多东西,但是我会比较。我一开始用VS写F#程序的时候,都只是用一个文件来练习。后来想要用多个模块了,于是就创建新的源文件。但是我发现,main方法总是说写在新文件里的模块“还没有定义”,这让我很困惑。于是乎,我去网上找一些示例——不是普通代码片断,而是一些用VS编辑的小型项目,它们自然是能够编译通过的。例如,我拿到了项目A,我就开始比较它和我的写法究竟有什么问题——观察下来没有任何收获,我还是觉得我的做法没有任何问题。于是我尝试着在A项目中添加我的模块——奇怪,在A的main方法中还是访问不到新模块——这不是欺负人么!

于是我进行更深入的比较,比较除了源文件之外,它的项目设置和我的项目设置有什么区别——还是没有!我抱着最后一丝希望,将A项目中的代码添加到我的项目中来,编译,还是失败!但是看到这个结果,我反而看到了解决问题的曙光。因为我都已经把源代码统一了,这样可能发生错误的地方可谓少之又少。刚才我提到,VS将编译工作交给外部命令执行,对于F#也一样。于是我就比较项目A和我的项目在编译时的输出,终于发现两者的区别在于调用fsc.exe的时候,参数顺序不同。F#的编译器和C#编译器不同的地方在于,它对源文件指定的顺序是有要求的,只有放在后面文件中的代码才能访问到前面文件中定义的内容,反之则不行。这意味着,main方法必须作为最后一个源文件存在。但是,VS并没有提供一个选项来调整源文件的顺序,既然这样,那就手动编辑fsproj文件吧。至此,问题解决。

我被这个问题困扰很久的原因,就是在于我从来没有去怀疑过F#编译器对源文件的指定顺序是有要求的。我之前也观察过fsc.exe的参数,但是并没有“看出”什么问题出来。但是,我会和一个成功的项目慢慢比较,把我的项目和它慢慢靠拢,我用这种方式排除了各种错误可能性,最终把我的关注点又“逼迫”到编译器的参数上。进行比较,尝试,最终解决问题。再此之前,我也不知道这一点,不是吗?您其实也一样,如果遇到了一个奇怪的问题,没关系,找一个成功的案例,详细比较为什么它能行而我不行,慢慢地向它靠拢。最终解决问题的时候,就是你获得新知识的时候。这样,你的“经验”增加了。

类似的做法还有:不时有朋友会问到,它的WebForm项目出现了这样那样的问题,例如在PostBack之后事件没有执行,状态没有恢复,读不到某个值等等。从我的经验上来说,这是遇到了生命周期的问题。但是,生命周期是个复杂的玩意儿,除非我亲手进行尝试,我也不可能知道某个特定项目特定问题的解决方案。其实对于这种问题,最好的方法之一,便是从最简化的模型开始尝试。例如,您可以准备一个空白页面,添加一些控件和代码,执行,成功。然后,您将这个简单的页面向您的项目进行靠拢,一次增加一小部分,然后执行看看是否成功。直到某段代码添加之后发现失败了,您就知道到底是什么原因引起的。可能是新的代码有问题,也可能是新代码让之前代码的问题暴露出来了。

对于排错来说,最关键的是思考和分析,而不是动手。我有时候见到一些同事在遇到错误之后就开始盲目地修改代码,重试,最后就算把问题碰对了,时间也浪费了——而且还可能把原有正确的地方改坏了。要进行思考和分析,就要细心观察,例如您有没有看清异常的信息是什么?有没有顺着InnerException一级一级往下看,看看最终是哪行代码出的问题?如今的框架,一般都会把错误信息写的非常完整。记得之前做WCF的时候,它甚至会告诉你可以尝试着修改配置中的哪个节点!如果您直接忽视这些,就丧失了第一手信息了。

还有,别怕英文,就个错误信息而已,没几个词的。

但是我可以这么说,许多朋友都缺少思考。因为从他们给我的邮件上来看,根本没有把问题描述清楚。我相信“如果说不清楚,那说明没想清楚”。事实上,如果能把问题描述清楚了,一般也可以找出用什么关键字去搜索引擎上查找信息。我很奇怪,许多朋友还不会用搜索引擎,例如他们会对搜索引擎说很长一句话,而不是提取出中间的“关键字”进行查询。更严重的问题是“造词”。例如“注入”,这个词很流行啊,脚本注入,SQL注入。于是很多人在提问的时候也一直“注入”,但事实上他的问题和任何一种“现存的注入”的含义都不同。当然,您觉得这是“注入”也没有关系,但是至少描述一下在您的场景下“注入”是什么意思,对不对?而且,如果你用“注入”去搜索引擎上查询,就会发现基本上找不到你想要的东西,因为“注入”这个词在互联网上有别的含义,它和你的含义完全不同,又能给你什么信息呢?

此外,查到内容之后,也要进行基本的信息筛选。例如,一些小站,垃圾站的信息就不要关心了吧。直接找一些著名的大站,如官方社区,文档,博客就行了。

最后一点是为我个人而说的。如果您希望让我分析代码,还请把所有可运行的东西打一个包给我,并告诉一个略为详细的步骤,让我可以直接双击打开编译执行并重现问题。如果您只给我一个代码片断,还无法编译通过,或者还需要我自己去补充各类库,那我就只能说声抱歉了。同样,如果涉及到数据库,那么请给一个用于创建脚本和测试数据的SQL文件。此外,如果项目太大,最好也新建一个项目,只放一些核心的东西即可,关键在于重现问题。而且就我个人经验来说,经过“提炼”之后,说不定您自己就已经发现问题所在了。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

51 条回复

  1. chy710
    *.*.*.*
    链接

    chy710 2009-10-14 14:34:00

    老赵产量高高高!

  2. winter-cn
    *.*.*.*
    链接

    winter-cn 2009-10-14 14:35:00

    一句话 社区是讨论技术的 不是免费的资源
    像老赵这种人 只能解决你"不会做"的问题 不能解决你"不愿意做"的问题

  3. pengxiaojun
    *.*.*.*
    链接

    pengxiaojun 2009-10-14 14:41:00

    基础与原理搞清楚了就OK了。

  4. Ivony...
    *.*.*.*
    链接

    Ivony... 2009-10-14 14:47:00

    nod.....


    先想后做,试验的结果可以印证或推翻之前的分析或猜想。在没有任何分析或猜想的前提下就进行试验,其结果不能说明任何问题也不会增长有用的经验。

  5. KKcat
    *.*.*.*
    链接

    KKcat 2009-10-14 15:26:00

    顶顶顶

  6. 菜鸟毛
    *.*.*.*
    链接

    菜鸟毛 2009-10-14 15:30:00

    相当长一段时间我也犯了动手多于动脑的错误.确实,有时候,硬着头皮去看英文提示,比自己盲目乱改要更快找到问题所在!

  7. 生鱼片
    *.*.*.*
    链接

    生鱼片 2009-10-14 15:31:00

    还有一点就是有开发工具的调试支持也是很重要的,因为在lotus的b/s开发中调试可以说没有任何工具的支持,程序出问题都要靠程序中写好的错误函数找到发生错误的行,没有加错误处理函数的要msgbox变量的值来debug,这点我深有体会啊。

  8. 老赵
    admin
    链接

    老赵 2009-10-14 15:41:00

    @生鱼片
    分享一个案例吧,呵呵。

  9. 天涯Sun
    *.*.*.*
    链接

    天涯Sun 2009-10-14 15:52:00

    不错。

    能力比知识更难学

  10. 苗大开
    *.*.*.*
    链接

    苗大开 2009-10-14 16:04:00

    学习加顶。。

  11. 生鱼片
    *.*.*.*
    链接

    生鱼片 2009-10-14 16:04:00

    这个是不同技术的问题,lotus中本身没有很好的异常支持,比如系统出问题了,后台看报错是entry not found,这种错误鬼才知道代码哪里出问题了。只能在程序的逻辑中加msgbox看变量哪里取值出问题了,看程序停在哪里。当然程序逻辑加上一些错误处理的程序可以解决这些问题,但是技术没有很好的支持的。.net在这方面我觉得就很好。

  12. 老赵
    admin
    链接

    老赵 2009-10-14 16:06:00

    天涯Sun:
    能力比知识更难学


    我觉得,基本能力经过多年学习,中学大学,总归应该有。
    但我观察下来,为什么很多朋友还是缺乏呢?
    我看到很多人说自己学历不高,动手能力强。但是,到底咋个算动手能力强啊。

  13. 我来自月球[未注册用户]
    *.*.*.*
    链接

    我来自月球[未注册用户] 2009-10-14 16:08:00

    真实好文章啊。

  14. 生鱼片
    *.*.*.*
    链接

    生鱼片 2009-10-14 16:08:00

    老赵说主要就这两点:
    1.正确和错误的对比
    2.简化模拟错误的环境

  15. 韦恩卑鄙
    *.*.*.*
    链接

    韦恩卑鄙 2009-10-14 16:29:00

    怨念吐槽:
    技术嘛 你教给别人 你只要持续学新的 还可以保持领先
    连方法论你都教给别人了 你让我们这些老东西怎么混阿。。。



  16. 韦恩卑鄙
    *.*.*.*
    链接

    韦恩卑鄙 2009-10-14 16:45:00

    Jeffrey Zhao:

    天涯Sun:
    能力比知识更难学


    我觉得,基本能力经过多年学习,中学大学,总归应该有。
    但我观察下来,为什么很多朋友还是缺乏呢?
    我看到很多人说自己学历不高,动手能力强。但是,到底咋个算动手能力强啊。



    动手能力强 就是勤奋 舍得拼出一夜把所有可能性都试验下

    我初中的时候动手能力很强 在第一次接触486的时候
    在没有任何指导读物的情况下一夜内把dos 6.22所有外部命令的所有参数都试验了一遍 连硬盘都格式化了10多次

    后来动手能力变得很弱 因为有msdn的例子 很少自己试验了 T_T
    但是涅,考虑的就多了

    以前是考虑在哪里还可以多改一下看看结果有什么不同。。
    现在是考虑在什么关键的地方加一个带条件的断点。。

  17. 老赵
    admin
    链接

    老赵 2009-10-14 16:45:00

    @韦恩卑鄙
    我的想法是:我教会你怎么学了,你去学会别的了再来教我,我就省事了。
    否则一天到晚只能我先学,然后教你,多不合算啊。
    所以我总是让公司小弟学一点我不会的,然后让他们写心得体会报告,嗯嗯。

  18. Teddy's Knowledge Bas…
    *.*.*.*
    链接

    Teddy's Knowledge Base 2009-10-14 16:53:00

    @Jeffrey Zhao
    真想问问Jeffrey,你每天至少1-2个post,还要及时回复,要花多少时间?

    我每天哄完孩子睡觉都十点以后了,偶尔花一两个小时画个什么图都觉得奢侈,呵呵~~ 没结婚,没孩子还是好啊~~

  19. 韦恩卑鄙
    *.*.*.*
    链接

    韦恩卑鄙 2009-10-14 16:55:00

    Jeffrey Zhao:
    @韦恩卑鄙
    我的想法是:我教会你怎么学了,你去学会别的了再来教我,我就省事了。
    否则一天到晚只能我先学,然后教你,多不合算啊。
    所以我总是让公司小弟学一点我不会的,然后让他们写心得体会报告,嗯嗯。



    恩 你已经是叫兽模式了 坏人

  20. Funeral
    *.*.*.*
    链接

    Funeral 2009-10-14 17:05:00

    授人以渔不如授人以鱼,学习了
    顶老赵!

  21. 坚强2002
    *.*.*.*
    链接

    坚强2002 2009-10-14 17:19:00

    老赵,我有一个观点:我们往往是把现象当成问题,比如会有人找我说“安装包安装不了”。其实这是现象,“问题”的描述是包含因果的“由于没有权限,安装包安装无法继续”

    往往把问题识别清楚了,解决方案也就呼之欲出了

    而解决方法也无非是通过 比较 排除 猜测验证等等大家在应试教育就学会的那一套

    如果说这里面有什么非技术因素,那就是心态了和态度了

  22. 妖居
    *.*.*.*
    链接

    妖居 2009-10-14 17:53:00

    同感。分析问题和解决问题的能力很重要。有的时候我问问题,把问题描述了一遍突然发现是什么错误了。呵呵……搞得被我问的人很郁闷。

  23. 精密~顽石
    *.*.*.*
    链接

    精密~顽石 2009-10-14 18:04:00

    个人感觉,如果不知道一些专有名词,那么你在 google 的时候都无从下手,或者查出来的东西不正确。

    比如我想找一个特定的递归算法,暂且不说那个特定的是什么,如果一个不知道递归为何物的初学者者( like me ), 那么他应该如何描述递归这二字表示的含义呢?显然,还是比较困难的。所以还是问你们这些前辈来得快。

    附加:本人觉得,错误,若是你调试很久,发现越是离奇,那么你犯的错误级别就越低。

  24. 老赵
    admin
    链接

    老赵 2009-10-14 18:11:00

    韦恩卑鄙:
    以前是考虑在哪里还可以多改一下看看结果有什么不同。。
    现在是考虑在什么关键的地方加一个带条件的断点。。


    这就说明变nb了啊,因为你做再快,动手能力再强,有计算机快么,我们要发挥人的优势嘛。

  25. 老赵
    admin
    链接

    老赵 2009-10-14 18:11:00

    @Teddy's Knowledge Base
    所以这不就趁没结婚么……嘿嘿。

  26. 老赵
    admin
    链接

    老赵 2009-10-14 18:12:00

    坚强2002:
    老赵,我有一个观点:我们往往是把现象当成问题,比如会有人找我说“安装包安装不了”。其实这是现象,“问题”的描述是包含因果的“由于没有权限,安装包安装无法继续”
    往往把问题识别清楚了,解决方案也就呼之欲出了
    而解决方法也无非是通过 比较 排除 猜测验证等等大家在应试教育就学会的那一套
    如果说这里面有什么非技术因素,那就是心态了和态度了


    嗯嗯没错,所以……我也不知道所以啥了,呵呵。

  27. 老赵
    admin
    链接

    老赵 2009-10-14 18:15:00

    @精密~顽石
    总有特定的东西是很难搜出来的,但这样的东西有多少呢?
    我觉得我收到的大部分问题是可以搜索出来的,呵呵。
    对了,话说,我以后可以尝试直接回复一个搜索链接。

  28. 坚强2002
    *.*.*.*
    链接

    坚强2002 2009-10-14 18:26:00

    @Jeffrey Zhao
    突然想到不久前我和我的师傅曾经也就这个问题讨论过,这是之后我
    总结性的短文《解决问题:心态 原则 方法》

    地址:
    http://www.cnblogs.com/me-sa/archive/2009/07/06/everythingwillbeok.html

  29. heros
    *.*.*.*
    链接

    heros 2009-10-14 19:33:00

    Jeffrey Zhao:
    @Teddy's Knowledge Base
    所以这不就趁没结婚么……嘿嘿。


    很快我也就是三口之家了。真羡慕你啊。

  30. 老赵
    admin
    链接

    老赵 2009-10-14 19:58:00

    @heros
    我还羡慕你呢,各有各好处,不是么,呵呵。

  31. heros
    *.*.*.*
    链接

    heros 2009-10-14 20:09:00

    一到十点,强制关机睡觉。准确的说是被关机睡觉。

  32. 麒麟.NET
    *.*.*.*
    链接

    麒麟.NET 2009-10-14 20:12:00

    老赵关于“注入”的描述应该是源自使用Model Binder绑定Action参数字段时的取舍问题中我的评论吧?这里我不得不为自己辩解几句了。

    所谓“注入”,我个人的理解,应该是通过外部环境改变程序的内部状态,它即包含负面的“SQL注入”、“脚本注入”、“URL注入”等,也包含正面的“依赖注入”。在我的那篇回复中,我认为“如果用户通过/Product/Create?ViewCount=1000这样的URL来访问创建页面,这样提交后的数据也会自动填写上ViewCount”,这种情况应该属于URL注入的一种,即通过外部的URL输入,(非法地)改变了数据库的内部状态,而并非我不加思考的随意“造词”。如果用英文来描述我的原意,我想我也会使用inject这个词的,不是吗?

  33. heros
    *.*.*.*
    链接

    heros 2009-10-14 20:14:00

    Jeffrey Zhao:
    @heros
    我还羡慕你呢,各有各好处,不是么,呵呵。


    不过生活也不能全是工作。
    各位适龄未婚同行们,可得抓抓紧呀。忙死忙活的为啥。

  34. 老赵
    admin
    链接

    老赵 2009-10-14 20:39:00

    @麒麟.NET
    咋又对号入座了,上次递归那个谁也是,总觉得我是在针对某个个例……
    “注入”这个词太典型了,如果只是你的话,我就不举这个例子了,呵呵。

    我文章里也说了,造词也没关系,只要把这个词在上下文中说清楚就行了。
    至于是否是inject……我不知道啊,听你这么解释可能是吧,但我应该不会这么说。

    不过你已经解释了很通顺很容易理解,那么叫“注入”肯定也是没有关系的了。
    因为有了上下文,否则吧唧一下丢个“注入”出来,没人可以理解,呵呵。

  35. 麒麟.NET
    *.*.*.*
    链接

    麒麟.NET 2009-10-14 20:51:00

    @Jeffrey Zhao
    我之所以吧唧一下丢出来,是因为我觉得显而易见,似乎不需要什么解释,对方应该可以理解。看来事实并不是如此,如何顺利、高效地沟通,看来真是门学问啊。
    有时看网上朋友的提问,东一句西一句的,自己连问题都描述不清楚,别人怎么回答?而且最近我发现一个趋势,就是提问者的态度比几年前恶劣多了,丝毫没有虚心请教的口吻,遇见这种人,想必高手都会敬而远之了。

  36. 麒麟.NET
    *.*.*.*
    链接

    麒麟.NET 2009-10-14 20:54:00

    heros:一到十点,强制关机睡觉。准确的说是被关机睡觉。


    没错,一结婚,学习的时间明显减少了

  37. 麒麟.NET
    *.*.*.*
    链接

    麒麟.NET 2009-10-14 20:55:00

    Jeffrey Zhao:
    @heros
    我还羡慕你呢,各有各好处,不是么,呵呵。


    我不信老赵有了女朋友或者老婆之后还能这么高产,看看TerryLee,呵呵

  38. 老赵
    admin
    链接

    老赵 2009-10-14 22:31:00

    @麒麟.NET
    TerryLee原来是这个原因?该消息来源可靠否?

  39. 张荣华
    *.*.*.*
    链接

    张荣华 2009-10-15 08:48:00

    有同感,其实一些简单的问题在问别人之前想一想,稍微分析一下,就可以解决了。我昨天还发了一个类似的推来说这件事来。

  40. JiaruiStone
    *.*.*.*
    链接

    JiaruiStone 2009-10-15 09:14:00

    这篇文章一定要收藏^_^

  41. Jerry Qian
    *.*.*.*
    链接

    Jerry Qian 2009-10-15 09:36:00

    赵老师,我朋友开一婚介公司,要不要帮忙啊。哈哈

  42. 老赵
    admin
    链接

    老赵 2009-10-15 10:13:00

    @Jerry Qian
    本公司不提供外包开发业务,哈哈

  43. Rock.Liuxn
    *.*.*.*
    链接

    Rock.Liuxn 2009-10-15 10:30:00

    赵老师 看到你的这篇文章让我很受启发,让我对程序开发过程中处理解决问题的方式有了深一层的认识,受益匪浅。

    授人以鱼,不如授之以渔,授人以鱼只救一时之及,授人以渔则可解一生之需!

    谢谢你的启发!

  44. 老赵
    admin
    链接

    老赵 2009-10-15 11:50:00

    觉得我这篇文章有帮助的朋友,也欢迎推广一下。

  45. songcan
    *.*.*.*
    链接

    songcan 2009-10-15 12:55:00

    zhichi

  46. jolboy
    *.*.*.*
    链接

    jolboy 2009-10-15 13:04:00

    赞同,说的太有道理了~
    解决问题前先得分析出问题的大致方向~~
    帮人家解决问题,前提是得将问题重现~

  47. 晓鑫[未注册用户]
    *.*.*.*
    链接

    晓鑫[未注册用户] 2009-10-15 17:17:00

    顶老赵,学习了,看了网上很多农博客的朋友老师但是像赵老师这样坚持不懈的比较少。。
    谢谢你,辛苦了

  48. _龙猫
    *.*.*.*
    链接

    _龙猫 2009-10-15 17:42:00

    居然能找到编译参数去,真是五体投地啊!! :D

  49. 老赵
    admin
    链接

    老赵 2009-10-15 17:49:00

    @_龙猫
    这就是排错方法啊,我一开始也想当然地忽视了编译器参数顺序。
    但是我慢慢把自己的项目和正确的项目统一,连源代码都完全一样了,这就保证了99%的正确了。
    那剩下的,可能出错的也只有几个小地方了。

  50. airwolf2026
    *.*.*.*
    链接

    airwolf2026 2009-10-15 18:13:00

    真的不敢找gf哈....深有体会....找了就没有自己的时间了.

  51. 卜俊生
    *.*.*.*
    链接

    卜俊生 2009-10-20 16:21:00

    不要脸地说,我的排错方法跟老赵差不多,尤其是

    例如,您可以准备一个空白页面,添加一些控件和代码,执行,成功。然后,您将这个简单的页面向您的项目进行靠拢,一次增加一小部分,然后执行看看是否成功。直到某段代码添加之后发现失败了,您就知道到底是什么原因引起的。可能是新的代码有问题,也可能是新代码让之前代码的问题暴露出来了。

    我就是这么做的,呵呵!

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我