RSS 2.0 Feed

Sunday, March 02, 2008

以前在北京的时候, 虽然没有参加过宝玉同学组织的.Net User Group 的活动,但是从日常工作中,也从宝玉同学的介绍中了解了一二。印象中, 在北京似乎是没有组织过Code Camp 的活动过。

Code Camp 是最初2004年底的时候 在开发者中逐渐成形的一种活动, 这项活动的最大特点有以下几个显著的特点.

  1. 由开发者社区组织,面向开发者的社区
  2. 永远免费
  3. 没有市场宣传的Session,所有Session都是Code
  4. 不在工作时间进行

    本人在多伦多参加了两届的CodeCamp,第一年由于仅仅是以 参加者的身份参加,所以除了惊叹组织水平之高以外,也不知道该如何说些什么。

今年为了能给宝玉同学提供一些详细的信息, 身体力行的参加了今年Code Camp 的组织和筹备。除了感觉到身心疲惫以外,也体会到了开发者社区的热情。

整个的Code Camp 活动组织下来, 宛如一次小规模的TechEd , 从会场安排、讲师筛选,会务工作人员,广告宣传,等等。更难能可贵的是, 整个地区的.Net User Group 之间的互通有无,信息共享,今年的Speaker 有从千里之外赶来的,也有远从美国赶来的,而且所有的人的付出都是没有报酬的,但是他们收获的激情和信任。

 

每当身处其中的时候,我就在想, 我们北京的开发者社区无论是从规模,能力还是激情这些方面,都不会比多伦多的社区差。今年或者明年,我们能否也组织成功一次我们自己的CodeCamp?

 

这里有一个组织code camp 的wiki 资料 http://www.bostondotnet.org/codecamp/

 

可以去http://www.torontocodecamp.com 看看多伦多的组织情况。

posted @ | Feedback (1) |

Saturday, September 29, 2007

很多朋友都知道,豆腐最近在项目中遇到了技术上的难题,或者说这个难题在现实生活中本身就是存在的。

比如当对两个html进行比较时, 如何能够正确地向用户提供 友好的比较结果。举一个很简单的例子。
<span>123</span> 和<div>123</div> 在html source 层面是完全不同的字符串,但是对于用户体验来说,这两个字符串是一致的。 再比如
<ul><li>First</li><li>Second</li></ul> 和 <li>First</li><li>Second</li> 在显示的时候是完全一致,但是html 确差了很多。 我们可以从技术上向用户解释说, 他们本来就是不一样的,但是这样会吓跑我们的用户。

我想了很多办法来解决这个问题,解决方案就是建立一个可配置的配置表, 通过反射建立起一套规则,当出现比较结果和human 体验不一致的时候,就利用这套逻辑进行修正,但是这样的问题就是 头疼医疼 脚疼医脚 ,总是滞后于用户发现问题,就和IE 的补丁一样,虽然可以解决问题,但是永远都是再发现问题以后才去解决。

终于有一点,痛下决心,在根子上解决这个问题。 解决这个问题的关键,就是在相同的用户体验的前提下,尽量的将数据源修正为同等比较, 这样的唯一解决方案就是XHTML 了,下一步的问题是,如何进行修正,这个可不是一个小问题。 直道有一天一个很偶然的机会,发现了W3C组织提供的Open Source  的项目Html Tidy,

这个Html Tidy 可以帮助我们 对html 字符串进行修正,并做标准化的处理。详细的关于Html Tidy 的信息,大家可以去这个站点, 我也会在后续的Post 中做详细的介绍。

如果大家也有兴趣的话,我们可以一起来研究和探讨。 谢谢。

posted @ | Feedback (9) |

最近在我们的项目中,进行了一次如何进行Test 的大讨论。
 大家都知道,Test 分为UnitTest 和 Function Test, 关于Function Test, 我们大家都没有歧义, 认为现阶段使用WatiN 的自动化测试已经能够满足项目的基本需要, 大家的分歧主要就在于如何进行Unit Test.
很显然,Unit Test是在测试我们的项目的最小单元, 但是问题是在一个 Data Driven 的项目中, 很多的最小单元都会使用到数据库访问,于是 Unit Test 是否需要Touch DB 就成为了这次讨论的核心问题。 我们主要有两种观点
1. 数据库测试也是我们必要的测试一部分 ,因此我们有必要在Unit Test中对物理的数据库访问的函数进行测试。
2.我们的测试并不希望去访问数据库,因为我们的Unit Test的测试用例将近 上千, 这样在每次check in 之后, 运行所有的Unit Test 就会不现实

持第一种观点的同学认为,既然我们有Daily Build的策略,我们不需要每次的 check in 都触发Unit Test的case, 在daily build 中一起运行Unit Test, Coverage Test 和Function Test,将测试报表发到大家的信箱就可以了。
持第二种观点的同学认为,Unit Test是保证代码质量的最低要求,因此需要明每次Check In 都触发Unit Test 并且Unit Test 应该是没有执行次序的, 如果涉及到数据库访问,则必须需要复杂的 Build Script 以保证Unit Test的执行次序。

经过差不多一周的lunch discussion 我们基本上同意使用第二种方案。

但是第二种方案会带来一些新的挑战,如果进行Unit Test ,那些碰到数据库访问的方法, 或者要调用数据库访问的方法和类该如何测试?
在这里,我提出的解决方案是使用NMock 这个Open Source  的项目。
下面简单介绍一下这个 项目, 你可以在http://nmock.org/ 这个地址看到关于这个项目的详细介绍, 我举一个非常简单的例子。
我们的项目一般都会分为 数据层, 业务层和 展现层。
一个典型的数据层是这样的

namespace Q4.Core.Datalayer.Interface
{
    public interface IUser
    {
        int UserId { get;set;}
        string UserName { get;set;}
        string FirstName { get;set;}
        string LastName { get;set;}
    }
}
namespace Q4.Core.Datalayer
{
    public class User : IUser
    {
   }
}

典型的业务逻辑层,我们一般会添加用户访问的处理逻辑。
namespace Q4.DataAdapter.Interface
{
    public interface IUserEntity
    {
        bool AddUser(string userName, string firstName, string lastName);
    }
}
namespace Q4.DataAdapter
{
    public class UserEntity :IDisposable,Interface.IUserEntity
    {
        private SqlConnection _conn;
        private string _connectionString;

        private static UserEntity _instance;

        public static UserEntity Instance()
        {
            string connectionString = "";
            _instance = new UserEntity(connectionString);
            return _instance;
        }


        private UserEntity(string connectionString)
        {
            _connectionString = connectionString;
            _conn = new SqlConnection(connectionString);
        }

       
        #region IDisposable Members

        public void Dispose()
        {
            if (_conn != null)
            {
                _conn.Dispose();
            }
        }


        #endregion

       

        #region IUserEntity Members

        public bool AddUser(string userName, string firstName, string lastName)
        {
            string sqlFormat = "INSERT INTO [MockUser]([UserName],[FirstName],[LastName])VALUES('{0}','{1}','{2}')";
            string sql = string.Format(sqlFormat, userName, firstName, lastName);

            using (SqlCommand cmd = new SqlCommand(sql))
            {
                cmd.Connection = _conn;
                cmd.ExecuteNonQuery();
            }

            return true;
        }

        #endregion
    }
}

在这一层的下面,我们会根据MVC  的架构再相应的搭建起来Controller 和 View. 这个我就不再浪费 大家的时间了。

如果我们希望在Controller中测试 AddUser 成功后, 我们希望将这个用户再添加到对应的用户组中,如果我们使用Mockup Object  的话,代码就类似于这样

namespace Q4.UnitTest
{
    [TestFixture]
    public class MockupTest
    {
        [Test]
        public void TestAddUser()
        {
            Mockery mocks = new Mockery();
            Q4.DataAdapter.Interface.IUserEntity userService = mocks.NewMock<Q4.DataAdapter.Interface.IUserEntity>();
            Expect.Once
                .On(userService)
                .Method("AddUser")
                .With("doufu@hotmail.com", "boke","Tang")
                .Will(Return.Value(true));

          Q4.DataAdapter.Interface.IUserEntity groupService = mocks.NewMock<Q4.DataAdapter.Interface.IGroupEntity>();
            Expect.Once
                .On(userService)
                .Method("AddUserToGroup")
                .With("doufu@hotmail.com", "Admin")
                .Will(Return.Value(true));

            bool bRet=userService.AddUser("robertx@q4websystems.com", "Robert", "Xue");
           if(bRet)
          {
                  bRet=groupService.AddUserToGroup("doufu@hotmail.com","Admin");
           }
        }
    }
}

当然实际的项目中, 测试的代码不会这么简单,我们需要利用Hashtable 建立起一套内存中的数据结构 供 Unit Test 来调用。不过 我相信再引入NMock 以后, 对于Data Driven 的项目进行Unit Test可以提供一种有益的思路。


欢迎大家跟贴和我一起继续探讨。谢谢。

posted @ | Feedback (9) |

Sunday, April 01, 2007

Google announces free in-home wireless broadband service




今天早上一上来就被这个给吸引了,赶快去http://www.google.com/tisp 申请了,现在就等结果了

posted @ | Feedback (15) |

Thursday, March 22, 2007

这个月 watiN 终于Release了,在我们的项目中,一直就在争论到底是使用WatiR 还是 WatiN 的争论,在WatiN发布以前,因为WatiR已经有了稳定版本,所以就一直采用WatiR,等待WatiN 出来以后,我当然是要使用WatiN了,今天花了一天的时间,把以前WatiR的测试用例全都重写了一遍,感觉就是一个字"爽",以前想都不敢想的一些测试,现在也可以做了。

发现了WatiN的两个问题,不过都有了解决方案。
1. WatiN没有直接的JavaScript 的调用接口,这点WatiR强一些
2. WatiN和WatiR犯了同样的问题,当在一个Test Case 中启动多个IE的时候,这些IE之间会共享Session,这点超级不爽。

WaitR的好处是:
1.Open Source
2.Ruby 语言

WatiN的好处是
1.Open Source ,新的Release 甚至为了方便大家使用,修改了使用协议
2..Net 平台,如果大家是开发Asp.net 的网站地话,会非常的方便,因为可以使用很多现有的类库


BTW:
  今天也顺便解决了,WaitR在 NAnt 中有时会无法操作IE 的Bug,要解决这个问题,需要下载今天早晨的最新Gem Build


posted @ | Feedback (17) |

Friday, November 03, 2006

I knew that baidu had developed a news protocol(sorry for everyone,It's my first time to baidu except mp3).When I started my new work,I found there is another open news protocol called newsML.This protolc had been released serveral years ago.There are many news press like Reuters and The Associated Press (AP).It's a XML style protocol and very easy to develop a parser.

 

And It's a pitty that you will not find a .Net parser for it but you can only found a JAVA version.So I think maybe someone can work with me to develop a parser and generator for baidu so that baidu will do more works for our country's internet online news.

 

Anyone who has interest on this project should contact with me.

 

BTW:
Baoyu,should you update your spam blocker?I got too many junk on my blog.You know,I didnot manage my blog for a loooooooooong time.

posted @ | Feedback (15) |

Friday, April 08, 2005

在日常的开发程序的过程中,经常会遇到使用IE的问题,使用IE一般有两种情况,一种是像监视GMmail信箱讲到的那样,另外一种是类似与CrazyBrowser这样的使用webbrowser控件的程序。
其实在程序中使用WebBrowser其实是一件很简单的事情,因为有WebBrowser可以直接使用,但是能用和用起来可不是一样的事情。下面就经常会用到的一些功能简单的介绍介绍。

1.最经常使用的自然如何屏蔽默认的IE右键菜单,并且使用自定义的菜单。这方面网上有很多的文章进行说明,我就不献丑了。因为我采用的办法据说是最没有创意的办法。在PreTranslateMessage中判断。

2.其实大多数情况下,我们还需要动态的去设置Webbrowser控件中的HTML属性,类似于自动填表之类的软件,这样的代码与监视GMmail信箱中使用的方法类似。

3.我们知道在类似的程序中,我们一般都要去截取在WebBrowser中的一些javascript事件,比如adblock这样的软件就需要截取window.open这样的代码,如果我们在自己的程序中使用IE控件的话,我们会希望IE页面里的Button Text Link就和我们在form中创建的Button,Text,Link完全一样的被我们轻松自如的控制。
最早打算去创建一个全局的Hook来监视这样的操作,但是这样做一个是太麻烦,接口过于复杂,而且也不是标准的做法。

通过查看MSDN,发现其实MSHTML其实是提供了这样的接口(与其说是MSHTML提供的接口,不如说是COM提供的接口),我用下面的代码来演示 如何来截取一个href超文本链接的操作。

ON_EVENT(CDialog1, IDC_EXPLORER1, 259, DocumentCompleteExplorer1, VTS_DISPATCH VTS_PVARIANT)

以便我们可以在所有的文档加载完成后,来分析整个的文档,然后通过监视GMmail信箱中介绍的办法找到我们要监视的Href
    if(strId.Find(cstrLink,0) != -1){
     IHTMLAnchorElement  * pButtonElem = NULL;
     hr = pDisp->QueryInterface(IID_IHTMLAnchorElement, (void **)&pAnchorElem); 
     HiJackHref(pAnchorElem); 
    }  
在HiJackHref的代码中,我们通过如下的操作
     hr = pAnchorElem ->QueryInterface(IID_IConnectionPointContainer, (void**)&pCPC);

     if (hr == S_OK)

     {
         hr = pCPC->FindConnectionPoint(DIID_HTMLAnchorEvents2, &pCP);
         if (hr == S_OK)
         {
              if (m_pHtmlEvent)
              {
                   delete m_pHtmlEvent;
                   
m_pHtmlEvent =NULL;
              }            
              m_pHtmlEvent = new HtmlEvent
              m_pHtmlEvent ->SetParent(this);
              IUnknown* pUnk = m_pHtmlEvent 2->GetInterface(&IID_IUnknown);
              hr = pCP->Advise(pUnk, &dwCookie);
              pCP->Release();
         }
         pCPC->Release();
     }
至此,我们已经成功地在我们form和html之间建立起来了一座桥梁,我们只要用标准的COMEvent
就可以简单方便的处理所有的html事件了,下面列出一些常用的事件

"HTMLELEMENTEVENTS2_ONCLICK", DISPID_HTMLELEMENTEVENTS2_ONCLICK

"HTMLELEMENTEVENTS2_ONMOUSEOVER", DISPID_HTMLELEMENTEVENTS2_ONMOUSEOVER

"HTMLELEMENTEVENTS2_ONMOUSEMOVE", DISPID_HTMLELEMENTEVENTS2_ONMOUSEMOVE

"HTMLELEMENTEVENTS2_ONDBLCLICK", DISPID_HTMLELEMENTEVENTS2_ONDBLCLICK

"HTMLELEMENTEVENTS2_ONMOUSEUP", DISPID_HTMLELEMENTEVENTS2_ONMOUSEUP

"HTMLELEMENTEVENTS2_ONMOUSEDOWN", DISPID_HTMLELEMENTEVENTS2_ONMOUSEDOWN

好了,这个问题到此就结束一大半了,为什么说是一大半而不是全部呢?大家首先要回忆一下前面的红色文字,我们这样做的最大问题就是,如果我通过DHTML增加了一个Element以后,HiJack的程序就不能截取了,只能通过重新HiJack一次了,这样多不方便呀,显然不是豆腐的作风。

告诉大家一个小诀窍,可以为我们需要操纵的Element设置一个同样名称的自定义属性,比如vid,然后再定义一个vname,这样就在DocumentCompleteExplorer1去Hook vid为特定数值的Element 然后再HtmlEvent根据vname进行不同的操作。
至此,问题全部解决,剩下的就靠你自己了。

 

Note:

好久没有更新自己的Blog了,开心也一再的催,不过实在是没有办法,最近这小半年的时间实在是太忙了,等到有时间了,会和各位朋友一起分享自己的心得。

posted @ | Feedback (28) |

Saturday, September 18, 2004

这两天一直在疲与奔命与各个Session之间,主要听了Lippman的全部两门课.Lippman果然是属于大牛级的人物,由于名气太大,座位一直不好找.不过说实话,我其实不太喜欢一边讲课,一边翻译这样的组织形式.这样听课的时候没有连贯性而且真正的课程时间非常短.

本来应该有一个和Lippman近距离接触的BOF,不过Lippman临时因为要去长城游览就Cancel了这个Session。真的是好可惜。还好在C++/CLI课程结束的时候眼急手快抢了一本Lippman签名的《Essential C++》这本书。要不然的话启不是血本无归?中午曾毅单独主持了BOF Session ,英语真牛呀。

这次TechEd感觉上由于微软今年几乎没有推出什么新产品,因此虽然有SQL 2005和Notnet 2.0 的Beta助阵,感觉上可以值得听的课程不是特别多。因此就来到今年新增加的这个上网区域上会网,给大家汇报一下最新的情况。

posted @ | Feedback (14) |

Wednesday, September 15, 2004

去年的这个时候去北京参加了一次TechEd,感觉上虽然入门级的介绍性内容偏多,但是也不乏优秀的课程,而且可以了解到很多先进的技术以及拓宽自己的思路。
听说今年的TechEd会增加很多技术含量很高的课程而且有非常著名的Stan Lippman 课程,那是不能不听的。同时非常感谢Grace为我提供了免费的门票,因此才得以成行。当然也要感谢老板给我这个出差的机会:)

在整个TechEd中,会参加的课程

  9.17 DEV 410,DEV 322,OFC 200,DEV 342
  9.18 DEV 411,DEV 412,DEV 382,DEV 365
  9.19 DEV 361,DEV 324,DEV 290

期间不一定每天都能完成自己的任务,19号晚上要赶火车,17号要在微软社区和其他的MVP以及微软的黄MM站台,到时候我会穿一件黄色的MVP衬衣,希望大家光顾辨认豆腐的本来面目。

posted @ | Feedback (11) |

Wednesday, September 08, 2004

首先声明我是Asp.Net菜鸟(虽然我从Beta1就开始学习),最近忙里偷闲给老婆做一个知识管理系统。有所感悟,贴到随笔里面,欢迎大家指正。

DataGrid真的是一个好东西,不光是方便的解决的数据列表和分页的问题。对于Editable Grid的支持也不错,虽然比起当初我在Asp时代的全部用JavaScript生成的那个Editable Grid的功能差了一些,不过我那个东东的封装可是没有人家这个这么直接。好在DataGrid提供的功能已经能够足够满足大多数的应用。

Editable Grid 

HeadTemplate中最让人感觉受不了的就是没有onClick的Server-Side事件,据我所知国人非常喜欢用href的onClick来实现很多的功能,最终选择了来实现对选中的记录的删除,删除本身是很好实现的,问题是我们一般在删除的时候习惯于对用户提示是否删除,而我们知道Server-Side是不可能提供这样的功能的。因此我们必须想办法使用Client-Side的脚本代码。
问题是这样的Client-Side的代码如何同我们的代码关联起来呢?
通过查询MSDN,我们知道了四种方法可以实现ClientScript的功能,分别是
1.
GetPostBackEventReference
2 RegisterArrayDeclaration
3 RegisterClientScriptBlock
4 RegisterStartupScript
其中,GetPostBackEventReference一般在user custom control中使用,我们在这里不做讨论Kaneboy's Blog尚有一个例子,我们着重讨论一下剩余的三个Register函数的用法。
RegisterArrayDeclaration向客户端声明一个Client Array以便 Client Script使用
RegisterClientScriptBlockRegisterStartupScript 的区别在于,RegisterStartupScript 一般都只有一行代码,而且RegisterClientScriptBlock将ClientScript放在开始的地方,而RegisterStartupScript 将代码放在结束的位置。

OK,有了这些知识以后,我们开始下面的代码。首先我们需要为我们的ImageButton增加Attributes,可是我们如何去得到这个ImageButton呢?这个Button是Grid的内部控件,我们在ItemDataBound事件中通过下面的代码得到

        Dim InnerControl As Control

        InnerControl = e.Item.FindControl("delLink")

        If Not InnerControl Is Nothing Then

            Dim InnerButton As ImageButton

            InnerButton = CType(InnerControl, ImageButton)

            InnerButton.Attributes.Add("onclick", "return confirm(确认要删除吗?');")

        End If

这段代码执行起来没有任何问题,但是这个时候我们自然会有这样的想法,如果这个ClientScript代码非常复杂的话,我们该如何来处理呢?说起来,这个问题其实也很常见,比如我们如果想将最后的一句话修改成为

         InnerButton.Attributes.Add("onclick", "return confirmDel();")

我们自然会想到 这样的方法,不错这个方法很好,不过别着急。这样的努力是不会成功的,虽然我们把这样的运行的代码另存成HTML以后,我们会发现Js代码按照我们的预期执行了,但是在运行模式下,这样的不会成功的。解释如下:“ASP.Net can only emit code where there is either databinding <%# %>or runat=server. Thus, the "standard processing area" is the area. This is required for ASP.Net to function and therefore only allows dynamic content to be added between the tags.

不过既然这样,我们也不要去强求,我们可以利用下面的代码使得我们的工作顺利进行下去:

        Dim scriptFile As System.IO.File

        Dim readStread As System.IO.StreamReader

        readStread = scriptFile.OpenText(Server.MapPath("MemberManage.js"))

        Dim strScript As String

        strScript = readStread.ReadToEnd()

        readStread.Close()

        strScript = " "

        If (Not Page.IsClientScriptBlockRegistered("clientScript")) Then

            Page.RegisterClientScriptBlock("clientScript", strScript)

        End If

 

Link:http://weblogs.asp.net/asmith/articles/25465.aspx

好奇怪,这个Post的原来的样子在我的机器上显示非常正常,可是大家普遍反映字体太小,现在该了一个特别大的字体,似乎是好多了,真的好奇怪。

posted @ | Feedback (10) |

Tuesday, August 31, 2004

这两天给老婆补作业,也顺便操起了Asp.net的旧业。是一个内容管理系统,由于权限设置的原因,坚决不允许将文档或者程序存放在一个IIS无法访问的目录,以免造成泄密事件。因此要采用利用Asp.Net读出文件内容后回写到浏览器中的方法,看了uestc95 的[.NET Tips 1001]ASP.NET直接下载一个文件,而不是在IE中打开它 后很有启发,不过偷懒的天性是我觉得这个方法有点麻烦。好在发现Response.Writefile 这个方法,可以最大限度的减少同志们的工作量。,代码如下   

        Response.Clear()

        Response.ContentType = "application/octet-stream"

        Response.AddHeader("Content-Disposition", "attachment;FileName=" + HttpUtility.UrlEncode(filename, System.Text.Encoding.UTF8))

        Response.WriteFile(filepath+filname)

        Response.End()

当然大家可以在这里添加一些权限判断的代码。

posted @ | Feedback (20) |

Monday, August 23, 2004

以前写过一个监视GMail的邮箱的程序的思路:控制IE中的IFrame和Frames实现GMail自动登录  不过今天看了Google 的 Gmail Notifier 感觉好多了。不知道是用什么技术实现的?感觉上应该是差不多的技术。 不过现在这个软件不支持多用户,也不支持重新登陆,这样对于像我这样有N个GMail帐户的无聊认识就太不方便了。

奥运会期间,google 的图标天天换,现在每天都要观察一下 最新的奥运奖牌和Google的每日奥运图片。

 

posted @ | Feedback (30) |

Tuesday, August 17, 2004

或许你看到这个标题会感到非常的惊讶,因为截至到现在,恐怕是没有多少人没有使用过XML文档了吧。
不过如果你是一个VC6或者是VC7中native code的使用者的话,我想您或许会产生一些兴趣。

在MFC中没有提供对XML的操作的类,如果是忠实的COM支持者的话,可以选择使用微软的MSXML DOM 来操作一个xml文件。
如果是开源,又或者是对跨平台的支持的话,您可以选择使用WFC,XML4C 当然还有apache 的著名的Xerces C++ 来操作,使用这些类库基本上都可以比较简单方便高效的实现对xml文件的读写。并且都支持XML 的最新标准。

不过,不要忘记一件事情,需要使用VC来读写XML文件的基本上都是一些配置文件,比如Visual Studio .net 的工程文件,这样的文件的大小一般都会限制在一定的容量以内。如果我们采用上面的任何一个方法,都需要下载几M甚至10几M的库文件。真的是有些不合算。

感谢sourceforge,感谢google 给我们提供了足够多的资源来简化我们的开发,在这里我给大家介绍一个短小精悍的XML parse class----TinyXml,tinyXml 不光短小,效率也是很高,而且使用这个class 可以很快地定位 我们需要在Xml中定位的Node。它提供了一个叫做 TiXmlNode* FirstChild ( const std::string& _value ) 的方法,以最简单的方式开始我们对 Xml 文件节点的读写。

经过实践,发现这个class 读写xml 的速度也还是很不错的,要是说缺点,就是对Unicode的支持还有一些bug。比如说下面的xml 标签的解释就有bug

<Filter Name="程序" Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx">
但是如果你改成
<Filter Name="程序file" Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx">
的话,就可以了。

不过话又说回来了,开源就有这个好处,随时发现Bug,随时Fix Bug.

posted @ | Feedback (28) |

Monday, August 09, 2004

今天看了如何判断Assembly是Debug还是Release?这篇文章,收获很大,但是这个方法还是有自己的缺陷,使用这个方法必须保证这个DLL或者EXE程序参照自己的这个方法来实现?有没有办法判断这个程序是Debug版本的还是Release版本的呢?

在Win32环境下,一般来讲,由于大量的编译信息会保存在Exe或DLL文件中,因此这些文件的size都会比较大,我一般来判断这个文件是DLL还是Release版本都是通过对二进制码的分析得到的。

Debug版本的程序中一般都会保存PDB文件的保存路径,因此我就用这个方法来判断是不是Debug:)

在Dotnet环境下,Framework提供了一个DebuggableAttribute 的class,可以通过如下的代码实现对其编译属性的判断。

   try
   {
      Cursor = Cursors.WaitCursor;

      Assembly assm = Assembly.LoadFrom(filename);
      bool found = assm.GetCustomAttributes(typeof(DebuggableAttribute), false).Length > 0;
      buildType = found ? "Debug" : "Release";
   }
   catch
   {
      buildType = "<error>";
   }
   finally
   {
      Cursor = Cursors.Default;
   }

出处:http://www.sliver.com/dotnet/IsDebug/

程序下载(code):http://www.sliver.com/dotnet/IsDebug/IsDebugSource.zip

 

posted @ | Feedback (15) |

Wednesday, August 04, 2004

安全设计的一个准则就是:除了你,没有人可以冒充你。
什么意思呢?就是一个安全的系统中,即使是管理员也无法知道别人的密码,甚至是系统的设计者也不能冒充别人进入,或许你是管理员,你可以任意修改别人的密码,但是由于修改密码的操作是会被记录在案的,因此你仍然无法做到神不知鬼不觉地冒充别人做坏事。

安全的设计是系统的最后一道防线,完善的一个安全系统,不是说我如何如何能够抵御别人的攻击,而是在我已经被攻陷后还如何最大限度的保护我自己。

所以我们有了各种各样的密码算法,RSA,DES,BlowFish,他们的出发点都是一个开放的算法加上一个外接的密钥。但是我发现在很多的系统中,大家都忽略了一个问题,密码以什么形式保存呢?
答案当然是加密保存了,不错,这样作为我这样的一个试图非法进入一个系统的供给者来说,确实是没有办法得到管理员的密码。但是如果简单的将密码单独加密保存的话,如果我将自己的密码的加密后的字符串更新到管理员的密码字段后,我就可以利用我的密码堂而皇之的进入到系统,而不留任何痕迹。

比如:加入我的密码是:123,加密后的字符串是 BF123FGHOO8hL258BgRR 管理员的密码加密后的字符串是HHKK55RR))99uuKK!!33 我不知道这套系统的设计算法,更无从知道所谓的密钥是多少,但是我知道BF123FGHOO8hL258BgRR 代表的是123,我只要将管理员的密码加密串也更新成BF123FGHOO8hL258BgRR 我就可以用 123 登陆了。

要解决这样的问题,则不能简单的将密码加密,最起码也要将用户名揉到密码串中统一加密,这样就没有办法使用这种方法了。

 

现在的社会中,密码是我们的最后一道生命线,真的希望大家在设计系统的时候,如果牵扯到密码,一定要尽可能的为用户多考虑一些。

BTW(增加一些内容):

永远不要还原用户的密码,因为现代社会中大多数人会将自己在不同场合使用的密码设置成一样的,这样就会出现你的系统中的密码其实很有可能就是该用户银行的存折密码,我以前曾经用$@#$@#方法得到过一个免费网站的用户数据库,该数据库的密码是明文保存,我尝试了80%的用户在该站点的用户密码和他们登记的邮箱的用户和密码是匹配的,所以我现在就不敢在一些不值得信任的站点使用我的最高级别的密码。

posted @ | Feedback (48) |