人生是一场不能存盘的RPG,我只能尽量多搞几个Screenshot

May 31, 2006

中国程序员

Filed under: 技术以外

旺角卡门 他们年轻时(转载)

Filed under: 娱乐

《旺角卡门》
编剧:王家卫
导演:王家卫
摄影:刘伟强
美术:张叔平
主演:刘德华 张曼玉 张学友 万梓良
香港1988年出品

  我很喜欢看导演的处女作,也许那时的手法是稚嫩的,也许那时的技巧是生涩的,但那时对电影的激情绝对是无与伦比的,不像后期可能会有一些导演开始沦为技术或艺术的工匠,而慢慢失去当初对电影的那份热情,这是最可怕的。

  1988年,有点遥远的年头了,我11岁,在干什么呢,谁知道呢,不过有一点是肯定的,我应该还没有开始浪迹录相厅的岁月。那时可能知道刘德华,但绝对不可能知道王家卫。

  但是就在这一年,王家卫完成了他的导演处女作–《旺角卡门》。

  那个龙年,那个27岁的刘德华,27岁的张学友,24岁的张曼玉,31岁的万梓良,共同聚集在一个叫做王家卫的大哥手下,开始了一段江湖故事。那时的刘德华像个真正的偶像,青春无敌,那时的张学友还像个冒失的青头,率直可爱,那时的张曼玉像朵淡黄的小花,清香怡人,那时的万梓良也不像如今满脸横肉。

  最重要的是,那时的王家卫还没有戴墨镜,戴的是一副普通黑框眼镜。关于这点,我也是在DVD附录的预告片中瞥见的。

  影片乍一看,不像是一部有着强烈个人风格烙印的王家卫影片,它可能会被认为就是一部普通的江湖黑帮电影,江湖仇杀,大哥小弟,大哥身边的女人,义气与爱情,似乎与八十年代那些一般江湖英雄片没有什么不同。

  再看不然,其实主要人物皆是边缘人,强烈的宿命感,都已经有了王家卫后来影片的调子。这部影片与其说是在宣扬江湖义气,不如说是表达了对于江湖恩仇的厌恶和无奈,这和一般的江湖影片已经有很大不同。

  当然在王导赖以成名的影像处理上,风格不是特别明显,但是还是有几个抽格、慢镜体现了他日后开始追求的一种个人风格。

  影片中人物的画外音独白丝毫没有出现,这恐怕才是影片感觉最不像王家卫风格的地方。

  经典场面:

  之一:一脸青涩的乌蝇张学友向一脸无赖的肥九讨债,罗嗦了半天也没有任何效果,阿华哥刘德华一到,一个酒瓶就轻松搞定。(点评:太酷了,这就是英雄的出场!)

  之二:雨天,刘德华在车站偶遇前女友,女友告诉他她已结婚,刘不经意地看了一下她的肚子,女友说:”不是你的。”(点评:刘德华”哦”了一下默默走开,英雄也有失意时啊)

  之三:刘德华完成了张学友没有完成的杀手令,当场被警察击中头部死亡,躺在地上,圆睁双眼。(点评:印象中好像只有王家卫敢让偶像刘德华这样干脆地死掉,连一点煽情的台词都不留给他讲,看来导演更酷!)

  经典台词:

  之一:小贩:走鬼啦!(点评:这句话包含了香港小贩多少的”心酸”,也是很多港片中群众演员唯一的台词。)

  之二:阿娥:厨房里有煮好的饭,另外我还买了几个杯子,我知道,用不了多久就都会被打破,所以我偷偷藏起了一个,到有一天你需要那个杯子的时候,就打一个电话给我,我会告诉你放在什么地方。
  ……
  阿华:我想告诉你,我找到那只杯子了。
(点评:有点王氏台词的雏形了。)

  如今的王家卫戴上了墨镜,如今的张曼玉穿上了旗袍,如今的张学友年过四十已然成熟,如今的万梓良淡出娱乐圈,难觅踪迹,不知会否想着像约翰·特拉沃尔塔那样咸鱼翻身,只有同样年过四十的刘德华还在扮着偶像,一年又一年。

  不过,事隔多年之后,我们一定还会想起那些年轻的容颜,曾经在一个叫做旺角的地方,在林忆莲翻唱的《TOP GUN》的旋律中,静静绽放他们的美丽。

————————————————————————————

剧中刘伟强医生的扮演者就是张叔平

————————————————————————————

歌手:林忆莲
曲:G Moroder/T Whitlock 词:林振强

思海中的波涛滔滔不息飞跃起
心窝中的激情终于不可关闭起
当初喜欢孤独要爱却害怕交出爱
你那野性眼神偏偏将恋火惹起
Take my breath away
Take my breath away

火一般的激情滔滔不息因你起
当中一双恋人甘心给恋火灼死
漆黑之中等待你再次与我一起
火一般的嘴唇浪漫地令我不羁
My love Take my breath away

肌肤都紧张地拉紧 只因你就荡来
不可转弯的一颗心 不管有没未来
仍留在禁地 赌赌我运气
Take my breath away
Take my breath away

火一般的激情滔滔不息因你起
今天只得单程即使终于给灼死
漆黑之中等待你再亲身交低你
火一般的嘴唇浪漫地令我不羁
My love Take my breath away
My love Take my breath away

webcast_How do I Video Series_Master Pages and Site Navigation

Filed under: ASP.NET

How do I? Video Series : Master Pages and Site Navigation (hilo_masterpages-nav_FINAL.wmv)
http://asp.net/default.aspx?tabindex=4&tabid=3000
http://asp.net/learn/howdoi/default.aspx?tabid=63

1.Table的使用

2.使用TreeView, data source 设为Site Map, Site Maps会引用当前目录下的web.sitemap文件.

3.SiteMapPath,同TreeView.

4.Cool! 使用 File->Export Template 可以把当前project中的设置导出一个模板.下次再create web site时可以使用之.

5.对无权用户隐藏菜单

<system.web>
<siteMap defaultProvider=”defatult”>
<provider>
<clear/>
<add name=”default” type=”System.Web.XmlSiteMapProvider” SitMapFile=”web.sitemap” securityTrimmingEnable=”true” >
</provider>
</siteMap>
</system.web>

Synchronize Docuent Outline

Filed under: Visual Studio

在使用vs2005编辑网页时,选中一个tag,再使用右键菜单上的”Synchronize Docuent Outline”可以在Document OutLine中构造一个html tag树.

ctrl+shift+v

Filed under: Visual Studio

如果clipboard上存在多份数据,ctrl+shift+v可以循环paste这些内容.

May 30, 2006

webcast_How do I Video Series_Localization

Filed under: ASP.NET

How do I? Video Series : Localization (hilo_localization_final.wmv)
http://asp.net/default.aspx?tabindex=4&tabid=3000
http://asp.net/learn/howdoi/default.aspx?tabid=63

0. Resource 语法
显式: <%$ Resources:[filename prefix,]resource-key %>

隐式: <asp:Label ID=”Label1″ runat=”server” meta:resourcekey=”resource-key-prefix” />

1. 使用Local resource

可以使用菜单Tools->Generate Local Resource来生成local resource.
foo.aspx will refer to the /App_LocalResources/foo.aspx.resx

Create a special folder named “App_LocalResources”.
Create a resource file named “Default.aspx.resx” in it.
Create a resource file named “Default.aspx.fr.resx” in it.

3. Using the resource in the control
<asp:Button ID=”Button1″ runat=”server” Text=”Button” meta:resourceKey=”Button1″/>

4. Set culture for the page
<%@Page … UICulture=”auto”>

在IE中可以设置 default language,从而进行测试

5. 使用Global resource
所有的page, user-control都可以访问
Create a special folder named “App_GlobalResources”.
Create a resource file named “Resource.resx” in it.
Create a resource file named “Resource.fr.resx” in it.

6. 设置Control.Expressions 属性
Sample1:
Bindable properties 设为 Text
Expression Type 设为 Resource
Expression properties 的ClassKey 设为 Resource
Expression properties 的ResourceKey 设为 “资源名称”
Sample2:
Bindable properties 设为 BackColor
Expression Type 设为 Resource
Expression properties 的ClassKey 设为 Resource
Expression properties 的ResourceKey 设为 “资源名称”

7. 通过代码设置Culture

using System.Threading;
using System.Globalization;

protected override InitializeCulture()
{
string lang = Resuest(” “);

Thread.CurrentThread.CurrentUICulture = new CultureInfo(lang);
Thread.CurrentThread.CurrentCulture = new CultureInfo.CreateSpecificCulture(lang);
}

参考

ASP.NET 2.0 Localization Features: A Fresh Approach to Localizing Web Applications

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnvs05/html/asp2local.asp

ZBlogWriter

Filed under: Blog使用

发现了一个很好用的blog writer.

http://www.zoundry.cn/download.html

它可以把blog备份到本地C:\Program Files\Zoundry Blog Writer\users\**\docrepo

可以编辑已发布的blog的分类及内容(注意 check “update existing post”)

按分类发表blog

写很多再一次性post

第一次使用时,出现了异常,但重新打开,已写的内容还存在.

XP自动安装

Filed under: 使用技巧

1.在安装盘 SUPPORT 目录的 Tools 子目录中,找到一个名为 Deploy 的 CAB 压缩文件,将该文件解压即可看到 setupmgr.exe 程序
  运行之,可生成自动安装应答文件unattend.txt.
   
2.以从光盘安装为例:

   (1)在纯 DOS 下用 format A:/s 命令格式化一张软盘。

  (2)把unattend.txt 拷进软盘里

  (3)在软盘里创建文件 Autoexec.bat,并编辑命令行:
        set AnswerFile=unattend.txt
        set SetupFiles=CDDriver:\I386
        %SetupFiles%\winnt32 /s:%SetupFiles% /u:%AnswerFile% /t:C:
     (4)把软盘和光盘一同放进机器里, 启动顺序设置软盘,光盘引导。

注: 核心就是传给winnt32的两个参数: /s /u

SQL2005中xp_cmdshell安全性增强

Filed under: SQL&DB Accessing

在程序中用到以下的机制来新建一个account 库
1 datach account 标准库,
2 copy account 标准库的mdf文件,生成新的account库mdf文件.
3 attach 新的account库.

但是这个过程的步骤2会在sql2005上出错.
可用以下的sql语句来重现这个错误

1 create database AA
2 exec sp_detach_db AA,’True’
3 exec xp_cmdshell ‘copy /Y "c:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\AA.mdf" "D:\AA.mdf"’

语句1执行后会生成一个AA.mdf文件,在查看其属性中的Sercurity页,会看到以下帐号
Administrator
Network service
Service

sql2000中当语句2执行后查看AA.mdf文件属性中的Sercurity页,会看到以下帐号
Administrator
SQLServer2005MSSQLUser$机器名$实例名
Service

而在sql2005中当语句2执行后查看AA.mdf文件属性中的Sercurity页,只会看到当前操作者的帐号

语句3中的xp_cmdshell是以Service权限执行的,所以在Sql2005下会失败.
提示Access is denined.

同时,如果sqlserver中已经禁止掉xp_cmdshell的使用,会看到以下的错误提示:
SQL Server blocked access to procedure ’sys.xp_cmdshell’ of component ‘xp_cmdshell’ because this
component is turned off as part of the security configuration for this server.
A system administrator can enable the use of ‘xp_cmdshell’ by using sp_configure.
For more information about enabling ‘xp_cmdshell’, see "Surface Area Configuration" in SQL Server Books Online.

 

附:
http://msdn2.microsoft.com/zh-cn/library/ms190693(SQL.90).aspx

sql2005默认情况下,xp_cmdshell 安装时处于禁用状态,但是可以通过使用
外围应用配置器工具(Configuration Tools->SQL Server Surface Area Configuration)
或运行 sp_configure 系统存储过程来启用它,代码如下:

– To allow advanced options to be changed.
EXEC sp_configure ’show advanced options’, 1
GO
– To update the currently configured value for advanced options.
RECONFIGURE
GO
– To enable the feature.
EXEC sp_configure ‘xp_cmdshell’, 1
GO
– To update the currently configured value for this feature.
RECONFIGURE
GO

ASP.NET Event Validation

Filed under: ASP.NET

引用
ASP.NET Event Validation and "Invalid Callback Or Postback Argument"
http://odetocode.com/Blogs/scott/archive/2006/03/20/3145.aspx
http://odetocode.com/Blogs/scott/archive/2006/03/21/3153.aspx

参照
Please, please, please, learn about injection attacks!
http://weblogs.asp.net/bleroy/archive/2004/08/18/216861.aspx

ASP.net 添加了"event validation"的功能, ASP.NET会检查 POST方法中的所带的参数,如果
认为不合法,就会抛出异常,信息如下

    Invalid postback or callback argument.
        Event validation is enabled using <pages enableEventValidation="true"/> in
    configuration or <%@ Page EnableEventValidation="true" %> in a page. 
        For security purposes, this feature verifies that arguments to postback or
    callback events originate from the server control that originally rendered them. 
        If the data is valid and expected, use the ClientScriptManager.RegisterForEventValidation
    method in order to register the postback or callback data for validation.
   
这个设计的目的是为了防止恶意用户利用post 方法发送一些恶意数据.但是有时一些常见的
case也会出错,比如使用客户端脚本,根据页面上的其他控件的内容来改变一个dropdown list的内容,最常见的case
就是省市县3级联动菜单.又比如在页面上添加一个dropdown list,然后给它添加3个item,再使用客户端脚本在
dropdown list中添加一个item,如果dropdown list的AutoPostBack="True",每次选择list item都会引起postback,
如果所选的item为dropdown list本来就有的,一切正常.如果所选的item是通过客户端脚本添加的,就会出现异常.

在asp.net render DropDownList 时,会遍历DropDownList的item,并记录所有可能的postback的值,其算法为
hash(DropDownList’s UniqueID XOR hash(ListItem’s Value property)),计算的结果会被保存在page中,

<input type="hidden"
       name="__EVENTVALIDATION"
       id="__EVENTVALIDATION"
       value="/wEWBQKGg9abDQKd9sHMBgKc9s…….."
/>
这个过程发生在control的Render()方法中
当页面postback时,ASP.NET会根据这个隐藏值检查postback values,如果找不到对应信息,就会报错

结局方案
1. 禁止这个功能, 但同时会失去一些安全保障:
//—-通过web.config
<system.web>
   <pages enableEventValidation="false"/>
</system.web>
//—-针对某个page
<%@ Page EnableEventValidation="false" … %>

2.Register For Event Validation
其原理就是让asp.net记录这个postback value.
RegisterForEventValidation必须在render时调用.

protected override void Render(HtmlTextWriter writer)
{
   ClientScript.RegisterForEventValidation(_recipeList.UniqueID,"4");
   base.Render(writer);
}

如果我们自己写了一个control,需要使用validate events功能,就需要使用SupportsEventValidation attribute,

[SupportsEventValidation]
public class DynamicDropDownList : DropDownList
{
  protected override void Render(System.Web.UI.HtmlTextWriter writer)
  {
     Page.ClientScript.RegisterForEventValidation(this.UniqueID, "4");
     base.Render(writer);
  }
}

目前,asp.net还不能单独禁止某个control的validate events功能.

May 29, 2006

webcast_How do I Video Series_Tips and Tricks

Filed under: ASP.NET

How do I? Video Series : Tips and Tricks (hilo_tips_final.wmv)
http://asp.net/default.aspx?tabindex=4&tabid=3000
http://asp.net/learn/howdoi/default.aspx?tabid=63

通过代码加解密的connection string

public void EncryptConfig(bool bEncrypt)
{
    string path = "/tricks";
   
    Configuration config = WebConfigurationManager.OpWebConfiguration(path);
    ConfigurationSection appSettings = config.GetSection("connectionString");
   
    if(bEncrypt)
    {
        appSettings.SetionInformation.ProtectSection("DataProtectionConfigurationProvider");
    }
    else
    {
        appSettings.SetionInformation.UnprotectSection();  
    }
    config.Save();
}

保持滚动条的当前位置
    <%@ Page MaintainScrollPostionOnPostback = "true">
   
跨页面提交
    设置page1的PostBackUrl ="page2.aspx"
    设置page1的form1的
        DefaultButton和DefaultFocus
       
    在page2.aspx的page_load中写下:
    if(!Page.IsPostBack)
    {
        TextBox t = (TextBox)PreviousPage.FindControl("textbox1");
        this.lable1.Text = t.Text;
    }
   
使用BulletedList data binding到xml.
   
   
File Upload Control
   
    if(fileUpload1.HasFile)
    {
        fileUpload1.SaveAs("C:\upload\"+ fileUpload1.FileName);
    }

URL mapping 把一个很复杂的url map成一个简单的url.
    <System.web>
        <add url="…" mappedUrl="…">
    <System.web>
   
使用MultiView控件

webcast_How do I Video Series_Data Access

Filed under: ASP.NET

How do I? Video Series : Data Access(hilo_data_final.wmv)
http://asp.net/default.aspx?tabindex=4&tabid=3000
http://asp.net/learn/howdoi/default.aspx?tabid=63

共14分钟,演示了
1. 使用mdf文件, 从pubs数据库authots表导入数据

2. 生成了数据访问层: 生成connection string , 生成和配置 dataset,

3. 针对dataset的data binding
共两个页面: default.aspx 和 details.aspx

defautl 页面上有一个combo box, 一个gridview,演示了级联数据显示.
        gridview 还添加了detail url,指向 details页面,显示详细信息.

details页面,使用了DetailsView, 根据url中传来的参数,显示详细信息.

详细步骤:
//—-使用mdf文件
1. 在vs 2005 中可以直接生成mdf文件, 生成table,但不能执行 create table 等sql语句.
使用 SQL Server Management Studio Attach上mdf文件,可进行高级操作

//—-操作dataset
dataset会被存放在app_code目录中

可把table或table中的field从db explorer上drag到date set的design view上来生成table adapter

按照Table Adapter Configuration的提示可生成connection string 和用于select, update, delete
的sql 语句.
select 语句的where 子句通过设置filter 来实现,比如把filter设为 Filter = @state,会生成语句
where(state = @state)

完成后可使用preview data 菜单来进行测试, Cool!

//—- data binding
使用dataset,要在为control设置数据源时,选择object.
combo box 用来显示state,并用于引发dataview的变化, 所以combo box 的"Enable AutoPostback" 要设为true.
注意data source 的参数可以来自其他control, 也可以来自url.
把一个page drag到另一个page上可以直接生成一个link.

//如何实现details page
1.给data view添加一个column
2.设置column类型为HyperLinkField
3.设置HyperLink URL
  get url from data field : authorId
  url fromat string : Detauls.aspx?AuthorId={0}
4.在DataSet中添加一个query: GetDataByAuthorID
5.生成details page,添加DetailsView,设置datasource 为object,
  设置Parameter source为QueryString, QueryStringField为AuthorId
  和dataview的HyperLink column的设置对应.

webcast_How do I Video Series_Create a Full-Featured Customer Login Portal

Filed under: ASP.NET

How do I? Video Series : Create a Full-Featured Customer Login Portal(hilo_intro_final.wmv)
http://asp.net/default.aspx?tabindex=4&tabid=3000
http://asp.net/learn/howdoi/default.aspx?tabid=63

全面介绍asp.net2.0 功能

1.DataView的data binding
使用northwinds.mdf数据库
在配置dataview 的data source时使用 select statement, 并设置 where clause,
指定source为QueryString, QueryString Field为CustomerID.
或指定source为control, ControlID为gridview1

如果要使用主从两个dataview,
需要在主gridview中设置DataKeyName,并添加select column

在从gridview中设置其data source的查询语句的source为control, ControlID为gridview1

2.使用Theme
App_Themes下建立某个theme对应的folder,将Theme相关的文件(包括.css,.skin, 图片) 放到文件夹中.

skin文件的写法:
<asp:TextBox BackColor=”Green” Runat=”Server” />
<asp:TextBox SkinID=”BlueTextBox” BackColor=”Blue” Runat=”Server” />
<asp:BulletedList BulletStyle=”CustomImage” BulletImageUrl=”BulletImages/OrangeBullet.gif” Runat=”Server” />
第一个skin不包含 SkinID,被当成默认skin,适用于所有的TextBox.

<system.web>
<pages theme=”ThemeName” styleSheetTheme=”ThemeName”/>
</system.web>

在某个Page中使用theme
<%@ Page Theme=”ThemeName” %>
<%@ Page StyleSheetTheme=”ThemeName” %>

将主题应用于页面时,主题中所设置的任何控件属性都优先于页面中所设置的任何属性。
例如,如果主题指定所有 TextBox 控件的背景都应当显示为橙色,那么即使个别 TextBox
控件的 BackColor 属性具有不同的值,页面中所有 TextBox 控件的背景也仍然都将显示为
橙色。

在 ASP.NET 中,优先级的顺序是:
Theme,包括 Web.config 文件中设置的主题。
Page
StyleSheetTheme
比如skin文件中定义:
<asp:Label runat=”server” ForeColor=”red” Font-Size=”14pt” Font-Names=”Verdana” />
Page中将Lable1.ForeColor 设置为 blue。
如果使用<pages theme=”ThemeName”>Lable1为 red,
如果使用<pages StyleSheetTheme=”ThemeName”>Lable1为 blue,

动态加载Theme

Protected void Page_PreInit(object sender, EventArgs e)
{
switch (Request.QueryString[”theme”])
{
case “Blue”:
Page.Theme = “BlueTheme”;
break;
case “Pink”:
Page.Theme = “PinkTheme”;
break;
}
}

3. 使用master page
快速修改一个page:
1. 删光所有代码,只剩<%@page
2. 在<%@page 中写 MasterPageFile=”"
3. 切换到design view, 选择”Create Custom Content”

4. 用户登录,权限
使用web site admin tool生成config, user account, user role
使用loginview
使用LinginStatus
使用CreateUserWizard

5. Site map
Web.sitemap
使用TreaView ,将datasource设为SitemapDatasource
使用SiteMapPath
在web.config中使用 securityTrimmingEnable=”true”,可过滤掉用户无权访问的链接.

6. 使用 profile
类似app setting,但是保存在sqlserver 中
在web.config中添加
<profile>
<properties>
<add name =”FullName” defaultValue= “”>
</properties>
</profile>
使用:
//读
if(!page.IsPostBack)
{
TextBox1.Text = Profile.FullName;
}
//写
Profile.FullName = TextBox1.text

参考
演练:在 Visual Studio 中使用主题自定义网站
http://msdn2.microsoft.com/zh-cn/library/zcsbskx7.aspx

May 28, 2006

WinDbg+SOS实例

Filed under: WinDbg&SOS

出自
 SOS: It’s Not Just an ABBA Song Anymore(John Robbins)
 http://msdn.microsoft.com/msdnmag/issues/03/06/Bugslayer/
 
源码:
//——————————————————–
using System ;
using System.Diagnostics ;

namespace ExceptApp
{
    enum Days { Sat = 1 , Sun , Mon , Tue , Wed , Thu , Fri } ;
   
    class DoSomething
    {
        public void Doh ( String StrParam , Days ValueParam )
        {
            Console.WriteLine ( StrParam ) ;
            Console.WriteLine ( ValueParam.ToString ( ) ) ;
            throw new ArgumentException ( "Throwing an exception" , "x" ) ;
        }
       
        public void Reh ( int i , String StrParam )
        {
            Console.WriteLine ( "Reh = " + i ) ;
            String s = "Tommy can you see me? " + StrParam ;
            Days e = Days.Fri ;
            Doh ( s , e ) ;
        }
       
        public void Mi ( Object o )
        {
            Console.WriteLine ( "Mi = " + o.ToString ( ) ) ;
            String LocalStr = "Can you see me?" ;
            Reh ( 0x42 , LocalStr ) ;
        }
       
        public void Fa ( )
        {
            Mi ( this ) ;
        }
    }
 class Class1
 {
  static void Main(string[] args)
  {
      try
      {
          DoSomething x = new DoSomething ( ) ;
          x.Fa ( ) ;
      }
      catch
      {
      }
  }
 }
}
 
1. 何让WinDbg 拦截CLR Exception
使用菜单Debug->Event Filter打开Dialog
Click "Add"
enter "0xE0434F4D"
Select "Enabled" in the Execution group box
select "Not Handled" in the Continue group box

2. 使用 !thread 显示进程或一个dump文件中所有的managed线程

ThreadCount: 2
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 0
Hosted Runtime: no
                                      PreEmptive   GC Alloc           Lock
       ID OSID ThreadOBJ    State     GC       Context       Domain   Count APT Exception
   0    1  188 00181148      a020 Enabled  013c4b6c:013c5fe8 0014f238     0 MTA System.ArgumentException (013c4ad0)
   2    2  94c 0018ae58      b220 Enabled  00000000:00000000 0014f238     0 MTA (Finalizer)

OSID为 win32 thread id
Domain 线程所在的app domain
Exception 可能包含多种含义, 以上的信息表明1号线程引发了ArgumentException, 2号线程是Finalizer
          这个字段的值还可能是 (Threadpool Worker), (Threadpool Completion Port), or (GC),这些
          都是.net的执行线程.

3. 使用Windbg的 ~ 系列命令
   ~     :  显示所有的线程
   ~*    :  显示所有的线程
   ~.    :    显示当前线程
   ~#    :  引发异常的线程
   ~2    :  2号线程

使用~会显示
.  0  Id: b64.188 Suspend: 1 Teb: 7ffde000 Unfrozen
   1  Id: b64.a14 Suspend: 1 Teb: 7ffdd000 Unfrozen
   2  Id: b64.94c Suspend: 1 Teb: 7ffdc000 Unfrozen
  
   可见, 进程中除了2个.net线程,还存在一个win32线程.
     
4. 使用 !clrstack (或!dumpstack)
   !clrstack -a       查看所有信息,包括参数和局部变量
   !clrstack -l       查看局部变量
   !clrstack -p       查看参数
  
   ~*e!clrstack       查看所有线程的调用栈.
  
使用 !clrstack -a 显示

OS Thread Id: 0x188 (0)
ESP       EIP    
0012f350 7c81eb33 [HelperMethodFrame: 0012f350]
0012f3f4 00df02e7 ExceptApp.DoSomething.Doh(System.String, ExceptApp.Days)
    PARAMETERS:
        this = 0x013c1c44
        StrParam = 0x013c3f18
        ValueParam = 0x00000007

0012f418 00df0237 ExceptApp.DoSomething.Reh(Int32, System.String)
    PARAMETERS:
        this = 0x013c1c44
        i = 0x00000042
        StrParam = 0x013c1c6c
    LOCALS:
        <CLR reg> = 0x013c3f18
        0x0012f41c = 0x00000007

0012f438 00df01a0 ExceptApp.DoSomething.Mi(System.Object)
    PARAMETERS:
        this = 0x013c1c44
        o = 0x013c1c44
    LOCALS:
        0x0012f438 = 0x013c1c6c

0012f450 00df0134 ExceptApp.DoSomething.Fa()
    PARAMETERS:
        this = 0x013c1c44

0012f458 00df00b8 ExceptApp.Class1.Main(System.String[])
    PARAMETERS:
        args = 0x013c1c34
    LOCALS:
        0x0012f458 = 0x013c1c44

0012f69c 79e88f63 [GCFrame: 0012f69c]

以上内容对应于.net2.0 和原文中有所不同.

5. 使用dd 0x**** 可以查看内存中的值

6. !DumpMT [-MD] <MethodTable address>
    显示位于某个地址的 method table的信息, 每个managed object都会有个method table
   
7. !DumpClass 显示class所有信息

8. !Dumpmodule

9. !Dumpobject
    对于一个static 变量,会显示domain 和 静态变量在domain中位置, 这些信息被>>和<<扩起.
   
    790fa3e0  4000099       10        System.String  0   shared   static Empty
    >> Domain:Value  0014f238:790d6584 <<

10.!DumpStackObjects 显示当前线程的堆栈上的所有对象.

设计模式纵横谈(15)Command 命令模式

Filed under: Design Pattern

隔离 行为请求者 和 行为实现者 之间的耦合.
将行为抽象成object.
行为的请求者传递一个对象,该对象表达了一个方法(行为)

//== Version 1.
class Application
{
    public void Show()
    {
        Document doc = new Document();
        doc.ShowText();
       
        Graphics graph = new Graphics();
        graph.ShowGraphics();
    }
       
}

class Document
{
    public void ShowText()
    {
        …
    }
}

class Graphics
{
    public ShowGraphics()
    {
        …
    }
}

此时,Application 直接依赖于 document 和 graphics的showXX()这样的
具体行为实现.
考虑如何实现undo,redo,需要添加大量的代码.

//== Version 2.
public interface Command
{
    public void Show();
    public void Undo();
    public void Redo();
}

//==这个设计违背了单一职责原理,
class Document : Command
{
    public virtual void Show()
    {
   
    }
}

class Graphics : Command
{
    public virtual void Show()
    {
   
    }
}

class Application
{
    Stack<Command> commands;
    Stack<Command> undoList;
   
    public void Show()
    {
        foreach(Command c in list)
        {
            c.Show();
        }
    }
   
    public void Undo()
    {
        if(canUndo)
        {
            Command command = commands.Pop();
            command.Undo();
            undoList.Push(command);
        }
    }
   
    public void Redo()
    {
        if(canUndo)
        {
            Command command = undoList.Pop();
            command.Redo();
        }
    }       
}

//== Version 3.  扩展已有的类
//已存在,实现细节
class Document : Command
{
    public virtual void Show()
    {
   
    }
}

class Graphics : Command
{
    public virtual void Show()
    {
   
    }
}

//==实现command 模式
public interface Command
{
    public void Show();
    public void Undo();
    public void Redo();
}

//==具体化的行为对象,
class DocumentCommand : Command
{
    Document doc;
   
    public DocumentCommand(Document doc)
    {
        this.doc = doc;
    }
   
    public void Show()
    {
        doc.ShowText()
    }
   
    public void Undo()
    {
        …
    }
   
    public void Redo()
    {
        …
    }
}

此时,Application不再依赖于document和graphics这样的细节, 而是依赖于Command这样的
抽象,体现了依赖导致原则.

Command和Delegate之间的选择:

Command更趋向于oo的特征,更符合抽象的原则. Delegate 更灵活

May 27, 2006

星际争霸 vs 魔兽争霸3 vs 红警(转载)

Filed under: 娱乐

           魔兽娱乐性强 比较搞笑 你常常越玩越轻松
    星际竞技性强 比较严肃 你常常越玩越紧张
    红警政治性强 比较偏激 你常常越玩越气愤
      
    玩魔兽 就像唱卡拉ok 普通人练一首歌半个月 已经能赢得同伴的掌声
    玩星际 就像唱京戏 曲不离口的练上一年 可能还唱不上调子
    玩红警 就像说话 不用练就差不多水平 练了很多年说话的水平不见得高多少。
    
    学习魔兽 你能打赢两家疯狂电脑的时候 你和真人打就能取胜了
    学习星际 你能打赢七家电脑 你还纳闷怎么还打不过真人
    学习红警 你能打赢七家电脑1000000次 不见得和真人玩过。
  
    学习魔兽 两个小时你能死在相同的战术上八次 毫无还手之力
    学习星际 两个小时你能死在迥异的战术上八次 毫无还手之力
    学习红警 两年你都死在相同的得战术上无数次 毫无还手之力
    
    魔兽里面 你专心练一个族往往就能够应付对同族异族4种情况打法
    星际里面 人打虫的高手往往曾经就是虫打人的高手
    红警里面 你学会一个国家就等于学会了所有国家
      
    魔兽里面 熟练了几种套路就可以取胜
    星际里面 熟练了几种套路还是被随机应变的对手牵着鼻子走
    红警里面 熟练了几种套路,你会发现根本没用,只要熟练一种就可以了。
      
    魔兽里面 你利用计谋伏击或者包围了对方主力 对方却掏出回程扬长而走
    星际里面 你会发现不仅有游击战还有阵地战、伏击战、空投战……
    红警里面 你会发现什么战都是多余的。人多才是硬道理。
      
    魔兽里面 敌人无论离家多远都可以十秒内回救被你偷袭的基地
    星际里面 你稍不留神就中了声东击西的诡计
    红警里面 你必须时刻留神你得矿车
      
    魔兽里面 你5分钟侦察一次还能对敌人兵种搭配了如指掌
    星际里面 你5分钟侦察五次说不定得到的还是假情报
    红警里面 你5分钟侦查一次,然后就再也用不着侦查了。
     
    魔兽里面 5分钟不侦察你还能猜出来敌人部队构成
    星际里面 3分钟不侦察出门就可能全是克制你的兵种
    红警里面 不用你去侦查地图上就能看见敌人的情况
      
    魔兽里面 赢了一场大战就可以松口气 因为几乎稳操胜券
    星际里面 赢了一场大战 正得意一下却发现刚刚大战中被一支奇兵偷袭的经济全毁
    红警里面 赢了一场大战 你会觉得很幸运 你好多天都没有打过大战了。
      
    魔兽里面 大战对决常常形势一边倒
    星际里面 大战对决常常双方两败俱伤
    红警里面 大战对决常常就像已经知道了结局颁奖典礼
      
    魔兽里面 一次全军覆没99%可以打GG
    星际里面 十次全军覆说不定都不知鹿死谁手
    红警里面 经常全军覆没是一种战斗方式
    
    魔兽里面 你郁闷于虽然有顽强精神却在难以劣势中翻盘
    星际里面 你郁闷于有优势却被有顽强精神的对手翻盘
    红警里面 你郁闷于必须有对方不知道的战术才能翻盘
      
    魔兽里面 录像看到一半往往能知道结局
    星际里面 录像看到结局你才发现开始的判断错了
    红警里面 录像是什么都不知道
      
    魔兽里面 初始的基地被拆毁就失去了希望
    星际里面 两个人鏖战到调换基地位置甚至四海为家也不稀奇
    红警里面 初始基地不仅可以被拆 还可以被占 被偷 被炸 自己还可以逃跑
      
    魔兽里面 初始矿采完基本胜负就见分晓
    星际里面 全地图的资源耗尽说不定才换来一个平局
    红警里面 大家一直在抢资源很少出现平局
      
    魔兽里面 你可以龟缩防守、偏安一隅
    星际里面 你如果不及时扩张 除了初始矿点 其他矿点都有对方采矿的农民
    红警里面 你必须去抢矿 这也是一种必须走的形势。
      
    魔兽里面 你把基地门口造满防御 敌人骂你猥琐赖皮
    星际里面 你把基地门口造满防御 敌人不是直接空投到你家里就是直接一颗核弹敲开大门
    红警里面 你必须在基地里面造满防御 敌人的飞机 飞行兵才不会占到便宜
    
    魔兽里面 你可以用高级兵种轻松欺负低级兵种
    星际里面 你发现原来小机枪也能“以小反上”地打航母
    红警里面 你发现只有高级兵种才是王者
      
    魔兽里面 没有对空部队看到空军常常就要选择逃跑
    星际里面 你刚出来4个飞龙却被3队不对空的小狗强拆了基地
    红警里面 飞行兵就是制胜的关键,别的都是摆设
      
    魔兽里面 你会质疑“量变引起质变”的法则
    星际里面 你会验证“量变引起质变”的法则
    红警里面 你会质疑“有名气的公司比较负责”
      
    魔兽里面 死掉一个兵会心痛半天
    星际里面 你知道什么叫做前仆后继
    红警里面 兵就是为了死掉的。
      
    魔兽里面 作战部队不敢过于分散
    星际里面 作战常常要地图各点全面开花
    红警里面 作战就是在几个特说的地方进行

          魔兽里面 即使知道敌人什么兵种配置有时候也赢不了
    星际里面 知己知彼才真的百战不殆
    红警里面 看到对方的兵种配置就知道对方的水平了
      
    魔兽里面 规矩多 玩家发挥余地小 按部就班往往比突发奇想更奏效
    星际里面 规矩少 玩家发挥余地大 按部就班往往陷于被动
    红警里面 没规矩 玩家战术就一种 突发奇想只有在对菜鸟的时候才能用
      
    魔兽里面 以不变应万变
    星际里面 以万变应不变
    红警里面 永远不变
      
    魔兽里面 1个英雄、道具可以四两拨千斤
    星际里面 1个隐形的单位可以四两拨千斤
    红警里面 1个高手对菜鸟可以四两拨千斤
      
    魔兽里面 你为那个用光环照耀部队、高人一等的英雄而感到骄傲
    星际里面 你才发现引爆地雷和对方坦克同归于尽的那个小狂徒才是真正的英雄
    红警里面 你为飞行兵拿下矿区而骄傲
      
    魔兽里面 你会发现操作被人性化设计之后 如同一部傻瓜相机
    星际里面 你会发现最简单的细节你也要亲手去处理
    红警里面 你会发现可以自己处理的事情不是很多。可以边吃零食,边和高手对战。
      
    魔兽里面 你会发现apm150的时候已经会无聊到插旗
    星际里面 你会发现apm150的时候才能勉强用用神族
    红警里面 你会发现apm150是什么你都不知道,只是到手快很有用。
  
    魔兽里面 你觉得12个女巫按了12次O之后同时变了对方12个羊很有成就感
    星际里面 你发现原来12运输机的地毯式空降也仅仅是操作的基本功而已
    红警里面 你认为可以让12个坦克移动中躲掉攻击,就是操作了
      
    魔兽里面 你觉得操作2队多部队围杀、齐射、魔法、道具是多么华丽
    星际里面 你才知道就连让4队雷车、2队坦克整齐行进都不容易
    红警里面 你订着炮弹看,快落地的时候让自己的坦克躲,炮弹多的时候还真不容易
      
    魔兽里面 连流星陨石都认识自己人和友军
    星际里面 一个闪电放不好 可能自己被电死的比敌人的还多
    红警里面 除了少数几个枪法好的兵种,其他都经常误伤自己人
      
    魔兽里面 常常讲这是理所当然
    星际里面 常常讲这也不是不可能
    红警里面 常常讲这是不可能的
      
    魔兽里面 常有某个玩家用某某流战术把所用的种族用成所在版本的王者之族
    星际里面 你突然发现昨天似乎无敌的偶像今天就输在某个黑马手
    红警里面 你知道自己只剩下一种战术的时候,你就是高手了。
      
    魔兽玩久了 才知道 效率是第一
    星际玩久了 才知道 数量是第一
    红警玩久了 才知道 经验是第一
      
    魔兽玩久了 才知道 等级是第一
    星际玩久了 才知道 经济是第一
    红警玩久了 才知道 兵力是第一
       
    魔兽玩久了 才知道 稳定娴熟是第一
    星际玩久了 才知道 侦察应变是第一
    红警玩久了 才知道 对偷袭方法了解是第一
    
    魔兽玩久了 才知道什么叫做战斗
    星际玩久了 才知道什么叫做战略
    红警玩久了 才知道什么叫做按部就班
      
    魔兽玩久了 你发现地图到现在为止还停留在在陆战
    星际玩久了 你发现从WCG2001开始官方地图就有岛战
    红警玩久了 你发现地图是永远不变的
      
    魔兽玩久了 你发现看rep要变换版本和收集地图实在厌烦
    星际玩久了 你发现一个400k的rep记录了一场3小时的比赛
    红警玩久了 你发现rep是什么你都不知道
    
    魔兽玩久了 你会发现总有或多或少冷板凳单位
    星际玩久了 你会发现没有一个单位是多余的
    红警玩久了 你发现高手对战大多数单位都是多余的
      
    魔兽玩久了 你会发现你所了解的魔兽知识越来越多
    星际玩久了 你会发现你所不懂的星际知识越来越多
    红警玩久了 你发现你所知道的红警知识没用的越来越多
    
    魔兽玩久了 仿佛在考验你的耐心和熟练程度一般
    星际玩久了 总有出乎你意料的东西令你眼前一亮
    红警玩久了 想睡觉

          魔兽玩久了 你发现刚练熟的高效打法随着版本更新、单位修改而不再应验
    星际玩久了 你发现不但新战术发明的越来越快,而且被破解的也越来越快
    红警玩久了 你发现战术越来越单一,破解方法越来越无用。
      
    魔兽玩久了 你发现战术大多跟着补丁变
    星际玩久了 你发现战术大多跟着玩家变
    红警玩久了 你发现战术就是偷袭和反偷袭
      
    魔兽玩久了 你发现魔兽的未来掌握在补丁手里
    星际玩久了 你发现星际的未来掌握在玩家手里
    红警玩久了 你发现红警的未来掌握在新游戏手里
      
    魔兽玩久了 觉得人在被魔兽玩
    星际玩久了 觉得是人在玩星际
    红警玩久了 觉得人和红警都在被游戏公司玩
      
    魔兽玩久了 天天盼望下一个版本升级补丁调整单位属性
    星际完久了 天天盼望不要出现bug这样就不用再有新补丁诞生
    红警玩久了 天天盼望不要出新补丁,这样bug就没了。
      
    魔兽玩久了 忽然想起冰封王座1.07诞生到1.20几乎版版不同
    星际玩久了 回忆起母巢之战1.04到1.08只做过两次单位属性变动就稳定至今
    红警玩久了 算了一下10年了就出过一次补丁,还没把bug改掉
      
    魔兽玩久了 才知道魔兽三确实比星际一画面好
    星际玩久了 才知道魔兽在用孙子辈的游戏和星际一代的产品比较画面
    红警玩久了 才知道同样是爷爷辈的游戏,差距怎么就那么大呢?
      
    魔兽玩久了 才知道魔兽玩家说魔兽好却很多都没玩过甚至听说过魔兽III的爷爷和爸爸
    星际玩久了 才知道星际的第一代已经快八岁了
    红警玩久了 才知道红警已经六年没人玩了
      
    魔兽玩久了 避免不了争论种族平衡性、英雄兵种单位bug性的口水战
    星际完久了 你问哪个族最强 大家会告诉你三族一样厉害 根据兴趣爱好选择
    红警玩久了 总是想说,咱们出飞行兵了,换种打法吧。
      
    魔兽玩久了 你不知道为什么魔兽玩家似乎也分了种族
    星际玩久了 你会发现三族来自不同星球但各族玩家却似兄弟
    红警玩久了 你会觉得每个国家几乎没有区别
    
    魔兽玩久了 你发现各族玩家往往在为维护自己所用种族而争辩
    星际玩久了 你发现无论何族玩家都在为维护共同的星际而争辩
    红警玩久了 你会发现这个游戏一直在维护某些国家的政治利益
      
    魔兽玩久了 你会品味什么是流行
    星际玩久了 你会体会什么是经典
    红警玩久了 你会明白什么是猥琐
      
    魔兽玩久了 你才知道为什么魔兽如此热门
    星际玩久了 你才知道为什么星际如此冷门
    红警玩久了 你才知道为什么红警如此热门却没有人玩
      
    魔兽玩久了 你会喜欢上魔兽 别人说魔兽不好 你会火冒三丈 恨不得打骂他
    星际玩久了 你会喜欢上星际 别人说星际不好 你会一笑而过 不屑和他争辩
    红警玩久了 你会喜欢上红警 别人说红警不好 你会火冒三丈 不知道怎么争辩
      
    魔兽玩久了 你慢慢体会到魔兽真的是一款好游戏
    星际玩久了 你慢慢体会到星际越来越不像一款游戏
    红警玩久了 你慢慢体会到一个好的公司比一款好的游戏重要的多
      
    魔兽玩久了 你发现魔兽是如此精彩的游戏 给我们带来快乐
    星际玩久了 你发现生活和思维方式已经有了星际的烙印
    红警玩久了 你发现思维方式越来越简单了
      
    魔兽玩久了 才发现原来有很多初中小朋友加入魔兽玩家行列
    星际玩久了 才发现原来有很多成家立业的“大叔”还没退出星际玩家行列
    红警玩久了 才发现原来有很多初中的小朋友和成家立业的大叔,不断加入和迅速退出这红警玩的行列 
     
    魔兽玩久了 才知道世界上最远的距离不是中国电信和网通 而是魔兽精灵玩家和兽人玩家的心
    星际玩久了 才知道 星品不好人品就不好
    红警玩久了 利用bug在红警里不算人品太不好
    
    魔兽玩久了 才知道 魔兽是暴雪制造出来的最流行的精品大作
    星际玩久了 才知道 星际是上帝借暴雪之手赐予玩家们的杰作
    红警玩久了 才知道 西屋为什么会输给暴雪

May 26, 2006

Create Table

Filed under: SQL&DB Accessing

IF  EXISTS (SELECT * FROM dbo.sysobjects WHERE id = OBJECT_ID(N’[dbo].[_MyTable]’) AND type in (N’U'))

IF not exists (select * from dbo.sysobjects where id = OBJECT_ID(N’[dbo].[_MyTable]’) and OBJECTPROPERTY(id, N’IsUserTable’) = 1)
DROP TABLE [dbo].[_MyTable]
GO

CREATE TABLE [dbo].[_MyTable]
(
 [Test] [varchar](32)
)
GO

 

在Managed代码中慎用API

Filed under: .NET

引自
ExitThread() in managed program?
http://blogs.msdn.com/yunjin/archive/2004/01/30/65386.aspx

以下代码有问题吗?
[DllImport( "Kernel32.dll")]
public static extern void ExitThread(int exitCode);

public static void Run ()
{
    …
    // calling OS’s ExitThread to exit the current thread
    ExitThread (0);
}

public static void Main ()
{
    ThreadStart threadStart = new ThreadStart(Run);
    Thread thread = new Thread(threadStart);
    thread.Start();
    …
}

需要注意的是在CLR的控制下,某些系统调用在unmanaged和managed环境下的行为并不相同,
ExitThread就是其中一个,同时,managed threads 和unmanaged threads 也有所不同.
1.当一个managed thread退出时,比如线程处理函数返回或ThreadAbortException被抛出,
CLR会作一些清理的工作(比如stack unwinding),调用API ExitThread()或TerminateThread()
会绕过析构函数的调用,或finally 代码块.

2.在某些情况下,可能有好几个managed thread 被映射到一个OS thread,调用ExitThread 可能
会终止多个 managed thread.

Managed Heap Object pinned

Filed under: .NET

引自
OutOfMemoryException and Pinning
http://blogs.msdn.com/yunjin/archive/2004/01/27/63642.aspx

如果大量使用锁定的object,managed heap会被不可移动的内存块分割
成很多的小碎片,导致OutOfMemoryException.
比如Socket.BeginReceive的buffer参数就会被锁定, 以便unmanaged code 可以
访问这个buffer.

使用SOS可以发现
0:000>!dumpheap

     Address       MT     Size
     00a71000 0015cde8       12 Free
     00a7100c 0015cde8       12 Free
     00a71018 0015cde8       12 Free
     00a71024 5ba58328       68
     00a71068 5ba58380       68
     00a710ac 5ba58430       68
     00a710f0 5ba5dba4       68
     …
     00a91000 5ba88bd8     2064
     00a91810 0019fe48     2032 Free
     00a92000 5ba88bd8     4096
     00a93000 0019fe48     8192 Free
     00a95000 5ba88bd8     4096
     …
     total 1892 objects

     Statistics:
           MT    Count TotalSize Class Name
     5ba7607c        1        12 System.Security.Permissions.HostProtectionResource
     5ba75d54        1        12 System.Security.Permissions.SecurityPermissionFlag
     5ba61f18        1        12 System.Collections.CaseInsensitiveComparer
     …
     0015cde8        6     10260      Free
     5ba57bf8      318     18136 System.String
     …
    
以上数据表明在heap中有3个free slots
statistics一节显示heap中有10,260 bytes的Free objects和18,136 bytes 的字符串.
之所以可以看到这些free object,就说明这些free ojbect处在无法回收的live object之间.
如果heap中存在大量的Free objects,就表明heap中存在大量的内存碎片.

进一步可以使用
0:000>!dumpobj 00a92000    //00a92000 处的对象是一个byte array
   Name: System.Byte[]
   MethodTable 0x00992c3c
   EEClass 0x00992bc4
   Size 4096(0x1000) bytes
     Array: Rank 1, Type System.Byte
     Element Type: System.Byte
    
0:000>!gcroot 00a92000     //address 00a92000 it’s rooted by local variables in thread 1
   Scan Thread 0 (728)
     Scan Thread 1 (730)
     ESP:88cf548:Root:05066b48(System.IO.MemoryStream)->00a92000 (System.Byte[])
     ESP:88cf568:Root:05066b48(System.IO.MemoryStream)->00a92000 (System.Byte[])
     …
     Scan HandleTable 9b130
     Scan HandleTable 9ff18
     HANDLE(Pinned):d41250:Root: 00a92000 (System.Byte[])  //pinned handle.

0:000>!objsize   //显示所有pinned 对象的handle
    …
     HANDLE(Pinned):d41250: sizeof(00a92000) = 4096 ( 0x1000) bytes (System.Byte[])
     HANDLE(Pinned):d41254: sizeof(00a95000) = 4096 ( 0x1000) bytes (System.Byte[])
     HANDLE(Pinned):d41258: sizeof(00ac8b5b0) = 16 ( 0x10) bytes (System.Byte[])
     …

查看对象的详细信息,

可以采用以下措施来减小锁定 object的负面影响:
1.尽量使两个相邻的锁定 object挨得更紧.
2.尽量使锁定 object处在heap的底部,这是由于free的内存集中在heap的顶部.
3.缩短object被锁定的时间.
4.不要每次create一个对象,然后锁定它,而是重用被锁定的对象.

以下的代码演示如何使用一个1k的被锁定的buffer:

public class BufferPool
{
    private const int INITIAL_POOL_SIZE = 512; // initial size of the pool
    private const int BUFFER_SIZE = 1024; // size of the buffers

    // pool of buffers
    private Queue m_FreeBuffers;

    // singleton instance
    private static BufferPool m_Instance = new BufferPool();
    public static BufferPool Instance
    {
        get
        {
            return m_Instance;
        }
    }

    protected BufferPool()
    {
        m_FreeBuffers = new Queue(INITIAL_POOL_SIZE);
        for (int i = 0; i < INITIAL_POOL_SIZE; i++)
        {
            m_FreeBuffers.Enqueue(new byte[BUFFER_SIZE]);
        }
    }

    // check out a buffer
    public byte[] Checkout(uint size)
    {
        if (m_FreeBuffers.Count > 0)
        {
            lock (m_FreeBuffers)
            {
                if (m_FreeBuffers.Count > 0)
                    return (byte[])m_FreeBuffers.Dequeue();
            }
        }
      // instead of creating new buffer,
        // blocking waiting or refusing request may be better

        return new byte[BUFFER_SIZE];
    }

    // check in a buffer
    public void Checkin(byte[] buffer)
    {
        lock (m_FreeBuffers)
        {
            m_FreeBuffers.Enqueue(buffer);
        }
    }
}

 

使用SOS

Filed under: WinDbg&SOS

//—-SOS.dll 的位置
%windir%\Microsoft.NET\Framework\<version>\

Documnet
C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Tool Developers Guide\Samples\sos
.NET 2.0中这个目录不见了.

//—-让WinDbg加载SOS
当打开一个.net 可执行程序windbg6.5会自动加载SOS,如果需要手动加载,有如下方法

方法1:配置系统环境变量,让搜索路径指向系统.NET Framework的安装目录,既sos.dll所在目录
set PATH=%PATH%;C:\WINDOWS\Microsoft.NET\Framework\<Version>
然后使用.load SOS 加载

方法2. 加载某个特定的sos
.load <full path to sos.dll>

方法3.
.extpath command sets or displays the extension DLL search path.

方法4.
.loadby sos mscorwks
debugger 会加载模块mscorwks所在路径下的sos

方法5.
直接使用形如!DLLName.ExtensionCommand 的命令,如果扩展dll没有被加载,debugger会加载之.

在windbg6.5的安装目录下也有一个sos.dll
C:\Program Files\Debugging Tools for Windows\clr10
加载和使用方法如下:
.load clr10\sos
!clr10\sos.help

//—-相关命令

.load sos
加载SOS

.chain
list extensions dlls,以确认SOS是否正确加载

.setdll sos.dll 把SOS设置为default extension.

lm
查看有哪些模块被载入内存

//—–实验
用Windbg打开一个.net 可执行程序(ctrl+E), WinDbg会自动break到程序入口(如果attach到一个程序上,则
立即break),此时,mscorwks尚未被加载,如果在此时加载了SOS,SOS中的命令还无法使用.F5让程序继续运行,
这次WinDbg会自动break到,此时使用lm命令可以看到被加载的module,其中包含了mscorwks.dll,此时SOS中的命令
才可使用

参考
SOS: It’s Not Just an ABBA Song Anymore(John Robbins)
http://msdn.microsoft.com/msdnmag/issues/03/06/Bugslayer/

Mini Dump Snapshots and the New SOS(John Robbins)
http://msdn.microsoft.com/msdnmag/issues/05/03/Bugslayer/default.aspx

SOS Debugging of the CLR, Part 1
http://blogs.msdn.com/jasonz/archive/2003/10/21/53581.aspx

用WinDbg探索CLR世界
http://flier.cnblogs.com/archive/2004/07/08/22313.html

深入探索.NET框架内部了解CLR如何创建运行时对象
http://www.microsoft.com/china/MSDN/library/netFramework/netframework/JITCompiler.mspx?mfr=true

如何:使用 SOS
http://msdn2.microsoft.com/zh-cn/library/yy6d2sxs.aspx

SOS Debugging Extension (SOS.dll)
http://msdn2.microsoft.com/en-us/library/ms404370.aspx

May 25, 2006

California Dreamin

Filed under: 歌词

 California Dreamin
      —-The Mamas & the Papas
 
All the leaves are brown
And the sky is gray
I’ve been for a walk
On a winter’s day

I’d be safe and warm
If I was in L.A.
California dreamin’
On such a winter’s day

Stopped into a church
I passed along the way
Oh, I got down on my knees
And I pretend to pray

You know the preacher likes the cold
He knows I’m gonna stay
California dreamin’
On such a winter’s day

All the leaves are brown
And the sky is gray
I’ve been for a walk
On a winter’s day

If I didnt tell her
I could leave today
California dreamin’
On such a winter’s day

(California dreamin’)
On such a winter’s day
(California dreamin’)
On such a winter’s day

MS Build 笔记

Filed under: Visual Studio

//—–MSBuild的执行路径
 C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
 或在Visual Studio 2005 command prompt下直接运行
 

//——条件的使用 
<Configuration Condition=" ‘$(Configuration)’ == ‘’ ">
 Debug
</Configuration>

 <MakeDir Directories="$(CopyLocation)" Condition="!Exists(’$(CopyLocation)’)"/>

//——显示信息
<Target Name="Hello">
    <Message Text="Hello MSBuild" Importance="high"/>   
</Target>

//——什么是metadata
一个Item的属性,分为Well-known 和custom
所有的Item都可以使用Well-known的metadata
比如,以下的MyItem 包含了文件file C:\MyProject\Source\Program.cs
<ItemGroup>
    <MyItem Include="Source\Program.cs" />
</ItemGroup>
可以使用Well-known metadata %(FullPath)得到

Custon metadata应用范围在当前的project文件中.

使用metadata和使用well-known的语法相同:
%(RelativeDir)

//——MSBuild 特殊字符
使用 %xx 语法对特殊字符进行转义,xx为该字符的ASC码.

//——在 MSBuild Project中使用环境变量
引用环境变量的方法与引用项目文件中声明的变量的方法相同
 <FinalOutput>$(BIN_PATH)\MyAssembly.dll</FinalOutput>

//——什么是Transformation
Transformation的语法:
 @(ItemName->’TransformationDetails’)

ItemName is the name of the item you are transforming, and the TransformationDetails
can contain raw text, evaluated properties, and metadata references.
比如

 <Copy SourceFiles="@(Compile->’%(FullPath)’)"
        DestinationFiles="@(Compile->’$(MSBuildProjectDirectory)\$(CopyLocation)\%(RelativeDir)\%(FileName)%(Extension)’)"/>
       
 @(Compile->’%(FullPath)’) 会得到Item Compile的FullPath

//——-清除project 的bin目录
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="CleanAllProjects">
    <!– Find all projects in or below the current directory –>
    <ItemGroup>
        <Projects Include="**\*.*proj" />
    </ItemGroup>
    <Target Name="CleanAllProjects">
        <MSBuild Projects="@(Projects)" Targets="Clean" StopOnFirstFailure="false" ContinueOnError="true">
        </MSBuild>
    </Target>
</Project>

//——-MSBuild 的Include 文件
这些文件存在于C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\

修改 Microsoft.Common.targets 中的CoreBuildDependsOn

Microsoft.Common.Tasks

//——-使用custom tasks扩展MS build:
1.从Microsoft.Build.Utilities.Task 派生
 public class TempFile : Task
 {
 
   public override bool Execute()
   {
      this.tempFilePath = System.IO.Path.GetTempFileName();
      return true;
   }
 }
 
2.写一个 project 文件
<UsingTask AssemblyFile="$(SharedTasksDir)\Tasks.dll" TaskName="Move"/>

//——-使用custom logger扩展MS build:

[尚待学习…]
 
 
 
 
参考
Compile Apps Your Way With Custom Tasks For The Microsoft Build Engine
http://msdn.microsoft.com/msdnmag/issues/06/06/InsideMSBuild/default.aspx

May 24, 2006

Are You Lonesome Tonight

Filed under: 歌词

Are You Lonesome Tonight
               
              Singer: Elvis Presley
              Music: Lou Handman
              Lyrics: Roy Turk

Are you lonesome tonight?
Do you miss me tonight?
Are you sorry we drifted apart?
Does your memory stray to a brighter summer day
When I kissed you and called you sweetheart?
Do the chairs in your parlor seem empty and bare?
Do you gaze at your doorstep and picture me there?

Is your heart filled with pain?
Shall I come back again?
Tell me dear,
Are you lonesome tonight?

[Spoken]
I wonder if you’re lonesome tonight

You know someone said that
The world’s a stage
And each must play a part.
Fate had me playing in love with you as my sweet heart.

Act One was when we met.
I loved you at first glance.
You read your line so cleverly and never missed a cue

Then came Act Two.
You seemed to change, you acted strange,
And why I’ve never known.

Honey, you lied when you said you loved me
And I had no cause to doubt you.
But I’d rather go on hearing your lies
Than go on living without you.

Now the stage is bare,
And I’m standing there
With emptiness all around.
And if you won’t come back to me,
Then they can bring the curtain down.

Is your heart filled with pain?
Shall I come back again?
Tell me dear,
Are you lonesome tonight?

 

The world’s a stage
        –莎士比亚

All I Have to Do is Dream

Filed under: 歌词

All I Have to Do is Dream
                         –The Everly Brothers

Dream, dream dream dream, dream, dream dream dream

When I want you in my arms,
When I want you and all your charms
Whenever I want you, all I have to do, is dream, dream dream dream

When I feel blue in the night,
And I need you to hold me tight
Whenever I want you, all I have to do, is dream, dream dream dream

I can make you mine, taste your lips of wine,
Any time, night or day
Only trouble is, gee wiz,
I’m dreamin’ my life away

I need you so that I could die,
I love you so, and that is why
Whenever I want you, all I have to do, is dream, dream dream dream, dream

I can make you mine, taste your lips of wine,
Any time, night or day
Only trouble is, gee wiz, i’m dreamin’my life away

I need you so that I could die,
I love you so, and that is why
Whenever I want you, all I have to do, is dream, dream dream dream (repeats out)

gee wiz :感叹语,表示对某事的惊讶,也可用gee

遭遇yahoo助手

Filed under: 使用技巧

前天安装了一个共享软件"成语词典",一不小心安上了大名鼎鼎的yahoo助手,我的诺顿马上表示抗议,说有病毒Torjan.StartPage,然后重启,同时我还在

C:\WINDOWS\system32\IME看到了堆的垃圾:weather report, 网络猪一堆dll,我马上意识到,真的遇到流氓了,搜索一下,看到有不少人也在问"如何卸载雅虎助手",答案大多是推荐一些卸载工具.但我对如何才能这样流氓和如何比流氓更流氓更感兴趣一点,也有些文章文章给了我这方面的知识,如Windows系统中删除顽固文件的十二招技巧, 全面剖析雅虎助手以及网络实名的流氓行径,最终,我还是选择了Format.教训啊…

May 22, 2006

Symbol File 的使用

Filed under: WinDbg&SOS

//–Symbol的分类
private : 包含最完整的调试信息,如变量,函数信息
retail  : 次之,不包含变量信息
export  : 用处不大

//–设置symbol path的3种方法
1. 设置_NT_SYMBOL_PATH环境变量(要在运行windbg前设置)
2. 使用菜单 File->Symbol File Path或通过快捷键 ctrl+s
3. 使用.sympath 命令

C:\WINDOWS\Symbols\dll;
C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\symbols;
C:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\symbols;
SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbol
其中最重要的是:

SRV*C:\MyLocalSymbols*http://msdl.microsoft.com/download/symbol

这一句会使Windbg在需要Symbol时检查C:\MyLocalSymbols路径,如果没有找到所需的Symbol,
Windbg会从http://msdl.microsoft.com/download/symbol把所需的Symbol下载到C:\MyLocalSymbols

注意:http://msdl.microsoft.com/download/symbols不能通过ie访问,只有MS的debug工具可以访问.

 

 

WinDbg官方资源

Filed under: WinDbg&SOS

http://www.microsoft.com/whdc/DevTools/Debugging/default.mspx

May 21, 2006

多启动xp安装盘制作

Filed under: 使用技巧

需要的工具:easyboot, 在网上找的一个带Ghost的启动系统:ghost.img
1. 把xp的安装盘copy到e:\Disk 下
2. 把sp2 copy到e盘,并解压缩到e:\sp2\,在命令行下运行e:\SP2\UPDATE\UPDATE.EXE /integrate:e:\Disk, 这样就把sp2 merge到了xp的安装文件中。
3. 在e:\Disk 下建一个名为ezboot的目录,把eazyboot要用的文件copy进去:
     w2ksect.bin: 用来装xp
     ghost.img:带ghost的引导系统
4.  用easyboot来制作一个多引导光盘,
     我做的有4个选项:
     1 Install xp vs sp2 ,命令为run w2ksect.bin
     2 Run Ghost  ,命令为run ghost.img
     3 Boot from HD ,命令为boot 80
     4 ReBoot ,命令为reboot
   
    把结果存到e:\Disk \ezboot\
     最终e:\Disk \ezboot\会有4个文件:
     ghost.img(在网上下的一个ghost系统)
     w2ksect.bin(ezboot带的装xp的程序)
     loader.bin(ezboot 生成,用于启动)
     myboot.EZB(ezboot 生成,用于记录菜单的设置)

5. 做ISO,指定文件位置为e:\Disk
   引导信息为e:\Disk \ezboot\loader.bin

VS2005 Team Test 数据驱动的unit test

Filed under: Visual Studio

1.测试数据放在数据库中.
在测试方法的属性窗口中设置 connection string 和data table name
  [TestMethod]
  [Owner("Mark Michaelis")]
  [TestProperty("TestCategory", "Developer"), DataSource("System.Data.SqlClient", "Data Source=.\\SQLEXPRESS;AttachDbFilename="myTestData.mdf";Integrated Security=True", "LogonInfoTest", DataAccessMethod.Sequential)]
  public void ChangePasswordTest()
  {
     //得到测试数据
     string userId = (string)TestContext.DataRow[(int)Column.UserId];
     string password = (string)TestContext.DataRow[(int)Column.Password];
     bool isValid = (bool)TestContext.DataRow[(int)Column.IsValid];

     LogonInfo logonInfo = new LogonInfo(userId, "P@ssw0rd");

     if (!isValid)
     {
        Exception exception = null;
        try
        {
           logonInfo.ChangePassword( "P@ssw0rd", password);
        }
        catch (Exception tempException)
        {
           exception = tempException;
        }
        Assert.IsNotNull(exception, "The expected exception was not thrown.");
        Assert.AreEqual<Type>( typeof(ArgumentException), exception.GetType(),"The exception type was unexpected.");
     }
     else
     {
        logonInfo.ChangePassword("P@ssw0rd", password);
        Assert.AreEqual<string>(password, logonInfo.Password, "The password was not changed.");
     }
  }

2.测试数据方法Excel文件中
    [TestMethod()]
    [DeploymentItem("EmailData\\EmailData.xls")]  //将excel文件部署到测试程序所在的目录,似乎不必要
    [DataSource("System.Data.Odbc","Dsn=Excel Files;dbq=D:\\TestData.xls;defaultdir=.; driverid=790;maxbuffersize=2048;pagetimeout=5", "Sheet1$", DataAccessMethod.Sequential)]
    public void MyFunctionTest()
    {
        //得到测试数据
        string testData = TestContext.DataRow[0].ToString();
        …
    }

3.使用配置文件
测试工程的app.config:

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
        <configSections>
            <section name="microsoft.visualstudio.testtools" type="Microsoft.VisualStudio.TestTools.UnitTesting.TestConfigurationSection, Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
        </configSections>
      
        <connectionStrings>
            <add name="MyJetConn" connectionString="Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\testdatasource.mdb; Persist Security Info=False;" providerName="System.Data.OleDb" />
            <add name="MyExcelConn" connectionString="Dsn=Excel Files;dbq=data.xls;defaultdir=.; driverid=790;maxbuffersize=2048;pagetimeout=5" providerName="System.Data.Odbc" />
        </connectionStrings>
       
        <microsoft.visualstudio.testtools>
            <dataSources>
                <add name="MyJetDataSource" connectionString="MyJetConn" dataTableName="MyDataTable" dataAccessMethod="Sequential"/>
                <add name="MyExcelDataSource" connectionString="MyExcelConn" dataTableName="Sheet1$" dataAccessMethod="Sequential"/>
            </dataSources>
        </microsoft.visualstudio.testtools>
    </configuration>

测试代码:
    [TestMethod()]
    [DeploymentItem("MyTestProject\\testdatasource.mdb")]
    [DataSource("MyJetDataSource")]
    public void MyTestMethod()
    {
    int a = Int32.Parse(context.DataRow["Arg1"].ToString());
    int b = Int32.Parse(context.DataRow["Arg2"].ToString());
    Assert.AreNotEqual(a, b, "A value was equal.");
    }

    [TestMethod()]
    [DeploymentItem("MyTestProject\\data.xls")]
    [DataSource("MyExcelDataSource")]
    public void MyTestMethod2()
    {
        Assert.AreEqual(context.DataRow["Val1"], context.DataRow["Val2"]);
    }

个人认为:DeploymentItem

参考

Strengthening Visual Studio Unit Tests(by John Robbins)
http://msdn.microsoft.com/msdnmag/issues/06/03/Bugslayer/

演练:使用 Visual Studio Team Test 进行单元测试
http://www.microsoft.com/china/msdn/library/langtool/vsts/vstsunittesting.mspx?mfr=true

演练:使用配置文件定义数据源 
http://msdn2.microsoft.com/zh-cn/library/ms243192.aspx

DeploymentItemAttribute
http://msdn2.microsoft.com/zh-cn/library/ms245570.aspx

May 20, 2006

.NET 多线程1_基本操作

Filed under: .NET

和Jave一样, .net从语言级别上支持了线程操作.

//—————–.NET 定义的线程的状态
System.Threading.ThreadState
System.Diagnostics.ThreadState

//——————–Thread 相关的class
System.Threading.Thread
System.Threading.ThreadStart

System.Threading.Timer

System.Threading.ThreadPool

 

//—————- Create Thread
Thread threadObj = new Thread(new ThreadStart(MyWorkerThreadMethod)); //此时state为 Unstarted.
threadObj.Start();  //注意,此时线程一定马上执行,OS会负责把线程从ready态设置到running态.

MyWorkerThreadMethod()要符合ThreadStart Delegate的格式: 无参数,无返回值.可以是静态方法.

//—————- 访问线程信息
Thread currentThreadObject =Thread.CurrentThread;
currentThreadObject.Name = "PrimaryThread";

//—————–操作线程
//—- 挂起
if (threadObject.ThreadState ==ThreadState.Running )
{
  threadObject.Suspend();
}

//—- 恢复
if (threadObject.ThreadState ==ThreadState.Suspended )
{
  threadObject.Resume();
}

//—- Sleep
Thread.Sleep(5000);
Thread.Sleep(TimeSpan.Infinite);

//—- 等待另一个线程结束
if(Thread.CurrentThread.GetHashCode() != threadObject.GetHashCode())
{
    threadObject.Join();   
    //or threadObject.Join(1000);      
}

//—- 结束线程
if (threadObject.IsAlive == true )
{
  threadObject.Abort();
}

会引发一个ThreadAbortException Exception

//——————线程同步
保证在某一时刻,只能有一个线程访问某个数据块

private static readonly object lockObj = newobject();

Test obj = null;
lock(lockObj)
{
     if(obj == null)
        obj = new Test();
}

[*]引用一道网上流传的c#面试题:
调用test方法时i>10时是否会引起死锁?

public void test(int i)
{
    lock(this)
    {
        if (i>10)
        {
            i - - ;
            test(i);
        }
    }
}
我想不会,整个代码中没有哪一行要访问this的实例数据.

 

参考
Working with Threads in C# (2006.05.18)
http://aspalliance.com/846

Multithreading in .NET
http://www.codeproject.com/dotnet/multithread.asp

CLR 的线程池(Jeffrey Richter)
http://www.microsoft.com/china/MSDN/library/netFramework/netframework/NECLRT.mspx?mfr=true
http://msdn.microsoft.com/msdnmag/issues/03/06/NET/

利用.Net 线程池提高应用程序性能
http://edobnet.cnblogs.com/archive/2005/11/29/287094.html

.NET’s ThreadPool Class - Behind The Scenes
http://www.codeproject.com/csharp/threadtests.asp

ASP.NET 2.0 中的异步页
http://www.microsoft.com/china/msdn/library/webservices/asp.net/issuesWickedCodetoc.mspx?mfr=true

如何取字符串的字节数

Filed under: Code snippets

int len = System.Text.Encoding.Default.GetBytes(strTest).Length;

和 strTest.Length 不同,后者返回的是字符数.

MS 著名写手Dino Esposito

Filed under: ASP.NET

http://msdn.microsoft.com/asp.net/community/authors/dinoesposito/default.aspx

Scott Guthrie有关vs2005的一些文章(转载)

Filed under: ASP.NET

转自http://blog.joycode.com/saucer/archive/2005/08/30/62690.aspx

ASP.NET之父Scott Guthrie有关ASP.NET 2.0和VS 2005的文章,

1。VS 2005中的Web项目系统提供的新功能 (VS 2005 Web Project System: What is it and why did we do it?)

2。如何在VS 2005和Web项目系统中使用 IIS (Using IIS with VS 2005 and the new Web Project system)

3。如何设置 ASP.NET 2.0的应用服务使用SQL Server 2000和SQL Server 2005 (Configuring ASP.NET 2.0 Application Services to use SQL Server 2000 or SQL Server 2005)

4。更好地管理VS 2005Web项目中文件的几个技巧 (Some techniques for better managing files in VS 2005 Web Projects)

5。如何使用VS 2005建立可重用的ASP.NET用户控件和页面库 (Building Re-Usable ASP.NET User Control and Page Libraries with VS 2005)

May 19, 2006

VS 的 Build Events

Filed under: Visual Studio

在vs2003 和2005中都支持了Build Events, 但是2003只支持单行的命令,而2005可以支持多行命令.

要想在2003中执行多行命令,只能把命令写在一个批处理文件中,然后通过调用批处理来执行.

1.在Solution explorer中用context meun查看project的property.

2.选择Build Events,可以看到Pre-build 和Post-build event command line,以及运行Post-build event 的条件

//——————————————————

用法收集

1.build完后修改build产物的名字(后缀),并覆盖已有的同名文件.

copy $(TargetFileName) $(TargetName).XXX y

2. 调用外部命令或批处理:

call "C:\Program Files\XXX.exe"

3. 条件判断:

IF NOT $(ConfigurationName) == Release GOTO end

    call "C:\Program Files\XXX.exe" $(ProjectDir)$(TargetName).cvp

:end

4.web project 自动部署

copy     $(TargetDir)*.*     \\MyServer\MyService\bin
copy     $(ProjectDir)*.ascx     \\MyServer\MyService

//——————————————————

Macro收集

$(DevEnvDir)

$(ProjectDir)

$(BuiltOuputPath)

$(ConfigurationName)

$(TargetName)  不含扩展名

$(TargetFileName)  包含扩展名

MSDN中的 Pre-build Event/Post-build Event Command Line Dialog Box 一节有所有的Macro

常用读取数据的方法

Filed under: SQL&DB Accessing

string connectionString = "";
string queryString = ""; 

//–使用dataset         
DataSet ds = new DataSet();
using (SqlConnection connection = new SqlConnection(connectionString))
{
    try
    {
        connection.Open();
        SqlCommand command = new SqlCommand(queryString, connection);
        SqlDataAdapter da = new SqlDataAdapter(command);
        da.Fill(ds);
    }
    catch (Exception exp)
    {
        Console.WriteLine(exp.Message);
    }
}

//–使用Data reader
List<MyType> fields = new List<MyType>();

using (SqlConnection connection = new SqlConnection(connectionString))
{
    try
    {
        connection.Open();
        SqlCommand command = new SqlCommand(queryString, connection);
        SqlDataReader reader = command.ExecuteReader();
        while (reader.Read())
        {
            fields.Add(new MyType(name, type));
        }
    }
    catch (Exception exp)
    {
        Console.WriteLine(exp.Message);
    }
}

写SQL语句容易出错的地方

Filed under: SQL&DB Accessing

1.要注意from, where 附近的空格!

stirng sql = "SELECT COLUMN_NAME AS Name, " +
             "DATA_TYPE AS Type, " +
             "CHARACTER_MAXIMUM_LENGTH as Length " +
             "From INFORMATION_SCHEMA.COLUMNS " +
             "WHERE TABLE_NAME = ‘{0}’";

使用SQL语句得到数据库信息

Filed under: SQL&DB Accessing

先google了一下,找到了两篇文章.

Schema: How do I show all the primary keys in a database? http://www.aspfaq.com/show.asp?id=2244

Querying System Tables http://www.sqlservercentral.com/columnists/rVasant/queryingsystemtables.asp 

下面是用到的一些语句:

–To retrieve all the user created tables:
SELECT name FROM sysobjects WHERE xtype = U

–To get list of all the stored procedures:
SELECT name FROM sysobjects WHERE xtype=P

–To retrieve all the fields of table ‘XYZ’:
SELECT name FROM syscolumns WHERE ID = (SELECT id FROM sysobjects WHERE name=’XYZ’)

 

下面是一些更高级些的,会用到 INFORMATION_SCHEMA views(sql2000以上),查看sql server的online help会看到更多的view

–得到Customers表上的所有的主键的name, type, 长度, default value

SELECT K.COLUMN_NAME,
           C.DATA_TYPE,
           C.CHARACTER_MAXIMUM_LENGTH,
           C.COLUMN_DEFAULT 
  FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS
    OIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE K
     ON T.CONSTRAINT_NAME = K.CONSTRAINT_NAME 
   JOIN INFORMATION_SCHEMA.COLUMNS C
     ON C.Table_Name = T.TABLE_NAME
    AND C.COLUMN_NAME = K.COLUMN_NAME
WHERE T.CONSTRAINT_TYPE = ‘PRIMARY KEY’  AND T.TABLE_NAME = ‘Customers’

此外,How do I show all the primary keys in a database一文中的SQL的缩进格式也很值得学习

SELECT 
    T.TABLE_NAME, 
    T.CONSTRAINT_NAME, 
    K.COLUMN_NAME, 
    K.ORDINAL_POSITION 
FROM 
    INFORMATION_SCHEMA.TABLE_CONSTRAINTS T
    INNER JOIN
    INFORMATION_SCHEMA.KEY_COLUMN_USAGE K
    ON T.CONSTRAINT_NAME = K.CONSTRAINT_NAME 
WHERE
    T.CONSTRAINT_TYPE = ‘PRIMARY KEY’ 
    — AND T.TABLE_NAME = ‘table_name’
ORDER BY
    T.TABLE_NAME,
    K.ORDINAL_POSITION

.NET 2.0中的connection string

Filed under: SQL&DB Accessing

//——————————————-

    config 文件中的connection stirng

//——————————————-

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
    </configSections>
    <connectionStrings>
        <add name="MyDB" connectionString="Data Source=myServer;Initial Catalog=myDB;Integrated Security=True"                                            providerName="System.Data.SqlClient" />
    </connectionStrings>
</configuration>

//——————————————-

    读取

//——————————————-

    string conn = ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString;
         

May 16, 2006

MS的开源项目站 CodePlex

Filed under: 技术资源

MS的开源项目站

http://www.codeplex.com/

Webcast_使用.NET Remoting 建立分布式应用程序

Filed under: Web cast学习

//—————————————————-
    第1讲   
//—————————————————-   
Remoting 使用的技术
    XML
    SOAP
    SerializableAttribute()  或实现ISerializable
 
    //==Bin
    FileStream fs = new FileStream("my.bin" , FileMode.Creat);
    BinaryFormatter bf = new BinaryFormatter();
    bf.Serialize(fs , myObj);
    fs.Close();
   
    //==Soap
    FileStream fs = new FileStream("my.xml" , FileMode.Creat);
    SoapFormatter formatter = new SoapFormatter();
    formatter.Serialize(fs , myObj);
    fs.Close();
      
    //==XML
    FileStream fs = new FileStream("my.xml" , FileMode.Creat);
    System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(MyType));
    xmlSer.Serialize(fs , myObj);
    fs.Close();
   
远程对象:
    对象运行在远程(MarshalByRefObject)
    传递对象副本(Serialize)
   
对象激活
    服务器激活SAO(WellKnown)
        Singleton
        SingleCall
    客户端激活   
        可保存会话状态

Channels
    用于收发消息
    TCP or Http, 也可自定义
   
开发remoting的步骤
    创建远程对象
        public class HelloServer: MarshalByRefObject
        {
            public
        }
   
    创建host程序, 或host在IIS中
        注册通道(内置: TCP , HTTP)
        注册服务器激活的远程对象, URL
        运行宿主对象
   
    建立客户端程序
        注册通道(内置: TCP , HTTP)
        根据URL得到对象代理
        通过代理调用远程对象.
       
    //===Sample : SampleRemoting   
    public class Client
 {
        public static void Main(string[] args)
        {
            //使用TCP通道得到远程对象
            TcpChannel chan1 = new TcpChannel();
            ChannelServices.RegisterChannel(chan1);
            HelloServer obj1 = (HelloServer)Activator.GetObject(typeof(RemotingSamples.HelloServer),"tcp://localhost:8085/SayHello");
            if (obj1 == null)
            {
                System.Console.WriteLine("Could not locate TCP server");
            }
           
            //使用HTTP通道得到远程对象
            HttpChannel chan2 = new HttpChannel();
            ChannelServices.RegisterChannel(chan2);
            HelloServer obj2 = (HelloServer)Activator.GetObject(typeof(RemotingSamples.HelloServer), "http://localhost:8086/SayHello");
            if (obj2 == null)
            {
                System.Console.WriteLine(
                    "Could not locate HTTP server");
            }

            Console.WriteLine( "Client1 TCP HelloMethod {0}", obj1.HelloMethod("Caveman1"));
            Console.WriteLine("Client2 HTTP HelloMethod {0}", obj2.HelloMethod("Caveman2"));
            Console.ReadLine();
        }
/*
            <configuration>
             <system.runtime.remoting>
              <application>
               <client>
                <wellknown type="HelloServer, General" url="http://localhost:8086/SayHello" />
               </client>
               <channels>
                <channel ref="http" port="0"></channel>
               </channels>
              </application>
             </system.runtime.remoting>
            </configuration>
           
           
   RemotingConfiguration.Configure(@"C:\Documents and Settings\RenMin\桌面\Remoting\Demo\02-SimpleRemoting\Client\client.exe.config");
   HelloServer obj2 = new HelloServer();
*/
 }
 
 public class Server
 {
  public static int Main(string [] args)
  {

   TcpChannel chan1 = new TcpChannel(8085);
   HttpChannel chan2 = new HttpChannel(8086);

            //注册通道, server会开始监听该通道
   ChannelServices.RegisterChannel(chan1);
   ChannelServices.RegisterChannel(chan2);

            RemotingConfiguration.RegisterWellKnownServiceType( typeof(HelloServer),
                                                                "SayHello" ,                    //URL
                                                                WellKnownObjectMode.Singleton   //对象类型
                                                              );

   System.Console.WriteLine("Press Enter key to exit");
   System.Console.ReadLine();

   return 0;
  }
    }
   
    //==Remote object
    public class HelloServer : MarshalByRefObject
    {
        public HelloServer()
        {
            Console.WriteLine("HelloServer activated");
        }
        public String HelloMethod(String name)
        {
            Console.WriteLine( "Server Hello.HelloMethod : {0}", name);
            return "Hi there " + name;
        }
    }
   
}

可传递的类型:
    简单类型
    可序列化的类型
    自定义的类型[serializable]
   
    在Client端直接使用User class
   
Singleton VS SingleCall
    都是服务器激活(WellKnown)
    Singleton :
        在服务器端只实例化一次
        每次调用都是同一实例.
        可以维持状态
    SingleCall
        每次调用都实例化新的实例
       
Serialization vs MarshalByRefObject
    Serialization
        副本,不论Singleton还是SingleCall
    MarshalByRefObject
        通过proxy   
         Singleton记录更改, SingleCall无状态
        
   
    判断一个obj是否是一个Proxy
    RemotingServices.IsTransparentProxy()
   
//—————————————————-
    第2讲   
//—————————————————-  
 
SAO 配置文件 wellknown
<configuration>
    <system.runtime.remoting>
        <application>
            <service>
                <wellknown mode="Singleton" objectUri="SayHello" type="RemotingSamples.HelloServer, General" />
            </service>
            <channels>
                <channel port="8086" ref="http"/>
            </channels>
        </application>
    </system.runtime.remoting>
</configuration>

<service>说明是server端
ref实际上是引用machine.config
%WINDIR%\Microsoft.NET\Framework\[version]\CONFIG
<channels>
    <channel id="http" type=" "…/>
</channels>

客户端配置文件
<configuration>
    <system.runtime.remoting>
        <application>
            <client>
                <wellknown url="http://localhost:8086/SayHello" type="RemotingSamples.HelloServer, General" />
            </client >
            <channels>
                <channel port="0" ref="http"/>
            </channels>
        </application>
    </system.runtime.remoting>
</configuration>

<channel port="0" />client
不需要监听

–代码——————————————————-
Server.cs
    public class Server
 {
  public static int Main(string [] args)
  {
            RemotingConfiguration.Configure(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
            //or RemotingConfiguration.Configure("Server.exe.config");

   System.Console.WriteLine("Press Enter key to exit");
   System.Console.ReadLine();
   return 0;
  }
 }
   
Client.cs
    public class Client
    {
        public static void Main(string[] args)
        {
            //使用HTTP通道得到远程对象
            RemotingConfiguration.Configure(@"client.exe.config");
            HelloServer obj2 = new HelloServer();
            if (obj2 == null)
            {
                System.Console.WriteLine("Could not locate HTTP server");
            }

            Console.WriteLine( "Client2 HTTP HelloMethod {0}", obj2.HelloMethod("Caveman2"));
            Console.ReadLine();
        }
    }

基于租约的对象生存期
可参考
使用.NET Remoting开发分布式应用——基于租约的生存期
http://terrylee.cnblogs.com/archive/2005/11/28/285809.html

    微软的DCOM技术使用了Ping机制,在这种机制下,客户程序有规律的对服务程序发出Ping请求,
以通知服务程序自己仍旧活着,并通知服务程序自己需要使用哪个对象。
    .NET Remoting使用的是基于租约的生存期机制,在租约期内,对象一直存活着,直到租借时间
结束,.NET Remoting使用Leasing程序完成了这项工作。

隐式续约
    每次调用远程对象上的方法的时候自动进行。
显示的续约
    ILease.Renew()
发起租约
    ISponsor接口
    ILease.Register()
   
   
租约的配置
    租约配置                默认值(秒)
    LeaseManagerPollTime       300
    SponsorshipTimeout         120
    RenewOnCallTime            120
    InitialLeaseTime (轮讯时间)          10        
   
//–如何得到当前的租约
HelloServer obj = (HelloServer)Activator.GetObject(typeof(RemotingSamples.HelloServer), "http://localhost:8086/SayHello");

ILease lease = (ILease)obj.GetLifetimeService();

if (lease != null)
{
    Console.WriteLine("Lease Configuration:");
    Console.WriteLine("InitialLeaseTime: " +
        lease.InitialLeaseTime);
    Console.WriteLine("RenewOnCallTime: " +
        lease.RenewOnCallTime);
    Console.WriteLine("SponsorshipTimeout: " +
        lease.SponsorshipTimeout);
    Console.WriteLine(lease.CurrentLeaseTime);
}  

//–通过代码改变租约, 见 Helloserver.cs
// Overrides the lease settings for this object.
public override Object InitializeLifetimeService()
{

    ILease lease = (ILease)base.InitializeLifetimeService();
    // Normally, the initial lease time would be much longer.
    // It is shortened here for demonstration purposes.
    if (lease.CurrentState == LeaseState.Initial)
    {
        lease.InitialLeaseTime = TimeSpan.FromSeconds(3);
        lease.SponsorshipTimeout = TimeSpan.FromSeconds(10);
        lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
    }
    return lease;
}

//–通过配置改变租约, 见 server的web.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <system.runtime.remoting>
  <application>
         ….
   <!–leaseManagerPollTime="7S"–>
   <lifetime leaseTime="7M"  sponsorshipTimeout="7M"  renewOnCallTime="7M"/>
  </application>
 </system.runtime.remoting>
</configuration>

CAO客户端激活 activated
   客户端激活的server端config文件
   <application>
   <service>
    <activated type="ClientActivatedType, General"/>
   </service>
   </application>
  
   client 端config文件
  
   <application>
   <client url="http://localhost:8080">
    <activated type="ClientActivatedType, General"/>
   </client>
   </application>

  
   优点客户端可以保存客户状态
        例子为 04-CAOsDemo
       
   客户端发起租约
        例子为 05-SponserDemo
       
   客户端发起租约的代码
        public class MyClientSponsor : MarshalByRefObject, ISponsor
        {
       
            private DateTime lastRenewal;
       
            public MyClientSponsor()
            {
                lastRenewal = DateTime.Now;
            }
       
            public TimeSpan Renewal(ILease lease)
            {
       
                Console.WriteLine("I’ve been asked to renew the lease.");
                Console.WriteLine("Time since last renewal:" + (DateTime.Now - lastRenewal).ToString());
       
                lastRenewal = DateTime.Now;
                return TimeSpan.FromSeconds(20);
            }
        }

        public class Client
        {
       
            public static void Main(string[] Args)
            {
                // Loads the configuration file.
                RemotingConfiguration.Configure("client.exe.config");
       
                ClientActivatedType CAObject = new ClientActivatedType();
       
                ILease serverLease = (ILease)RemotingServices.GetLifetimeService(CAObject);
                MyClientSponsor sponsor = new MyClientSponsor();
       
                // Note: If you do not pass an initial time, the first request will
                // be taken from the LeaseTime settings specified in the
                // server.exe.config file.
                serverLease.Register(sponsor);
                …… 
            }
        }

//—————————————————-
    第3讲   
//—————————————————-  
程序发布的模式: console, winform, winService, IIS

需要看源代码

//—————————————————-
    第4讲   
//—————————————————-  
聊天程序

  
  
  

Wabcast_应用程序性能调节

Filed under: Web cast学习

//——————————–
    原则
//——————————–
1.设置目标
2.测量
3.了解平台特性

//——————————–
    方法论
//——————————–
性能周期: 收集性能数据->分析数据找到问题->solution-> 实现 ->测试->收集性能数据
高质量的代码: 可移植性,可读性,可维护性,可靠性
收集数据:计时器 , 工具: Intel Vtune(收集数据)
负载: 可测量,可再生,静态,有代表性
识别问题: 瓶颈,热点
途径:算法,数据结构, 代码调节, 系统软件, 硬件

//——————————–
    .Net 程序优化
//——————————–
StringBuilder
GC的特点:使用弱引用
Ngen
值类型
using 对应的IL代码

//——————————–
    工具
//——————————–
Intel Vtune
应用平台: .net(可测到方法一级),c++(可测到代码级)

Performance:

CLR profiler

Dev partner (Compuware)

期望能看到一个性能分析的实例,但结果很失望,咬牙挺到了最后.

4种字符串判空的方法

Filed under: C#

1.  myStr.Length == 0

2.  myString == String.Empty

3.  myString==""

4.  String.IsNullOrEmpty (2.0)

在1.0时,FxCop推荐使用方法1,但为了防止null refrence,我们得先判一下null.

2.0有了新的静态方法IsNullOrEmpty(),那个最好呢?

使用Reflector打开.net 2,050727 下的mscorlib.dll

1 的代码为

[MethodImpl(MethodImplOptions.InternalCall)]
public extern int get_Length();

2和3  要使用了运算符==,而string的==的代码为

public static bool operator ==(string a, string b)
{
      return string.Equals(a, b);
}

string.Equals的代码为:

public static bool Equals(string a, string b)
{
      if (a == b)
      {
            return true;
      }
      if ((a != null) && (b != null))
      {
            return string.EqualsHelper(a, b);
      }
      return false;
}
看到这,你恐怕不会使用这种方法了吧.更有甚者myString==""还会先new一个空串出来.更浪费资源.

4 的代码为:

public static bool IsNullOrEmpty(string value)
{
      if (value != null)
      {
            return (value.Length == 0);
      }
      return true;
}

正是我们期待已久的答案.

string.Equals的静态方法和实例方法哪个更快

Filed under: C#

比较string是否相等可以使用静态方法String.Equals(), 也可以调用字符串的实例方法, 用reflector察看mscorlib.dll

–Instance Equals method implementation:
<.net  2.0.50727>
public bool Equals(string value)
{
    if ((value == null) && (this != null))
    {
        return false;
    }

    return string.EqualsHelper(this, value);
}

<.net 1.1>
[MethodImpl(MethodImplOptions.InternalCall)]
public extern bool Equals(string value);

An internal call is a call to a method implemented within the common language runtime itself.
 

–Static Equals method implementation:
<.net  2.0.50727>
public static bool Equals(string a, string b)
{
      if (a == b)
      {
           return true;
      }
      if ((a != null) && (b != null))
      {
           return string.EqualsHelper(a, b);
      }
      return false;
}

<.net 1.1>
public static bool Equals(string a, string b)
{
      if (a == b)
      {
            return true;
      }
      if ((a != null) && (b != null))
      {
            return a.Equals(b);
      }
      return false;
}

[*]读EqualsHelper的代码,可以看看MS是怎么比字符串的.

可以看到,静态方法会先比较refrence,如果事先知道字符串相等的可能性较大,使用静态方法会快那么一点点.

 

给我的Categories加icon

Filed under: Blog使用

进入 Manage->file->修改css,

添加以下部分

#categories ul li
{
        margin-left: 6px;
 list-style-type: none;
 list-style-image: url(http://recordsome.blogsome.com/images/bullet.gif); 
}

后来觉得这样不是很好,正解应该是修改css中的Content & menu一节,

#menu ul ul {
 margin-left: 0;
 list-style: disc;
 list-style-position: inside;
 padding-left: 0.5em;
 text-indent: 0;
 
 color: black;
}

改为

#menu ul ul {
 margin-left: 0;
 list-style-position: inside;
 padding-left: 1em;
 text-indent: 0;
 list-style-type: none;
 list-style-image: url(http://recordsome.blogsome.com/images/bullet.gif); 

 color: black;
}

Cool!目标实现了,但是由于加了icon和padding,右边菜单区域的空间有点太窄了,于是又修改了

#menu {
 width: 16em;      

增加width的值.

 

咏蛙 类诗文收集

Filed under: 其他

咏蛙
独坐池塘如虎踞,绿荫树下养精神。春来我不先开口,哪个虫儿敢作声。

—1909年,16岁的毛泽东(1893-1976)来到离家50里外的湘乡县(湘军曾国藩属下有2000多个被封为二品以上的军官住在当地) 东山书院读书,做此诗。

题菊花

飒飒西风满院栽,蕊寒香冷蝶难来。他年我若为青帝,报与桃花一处开。

—- (唐)黄巢

不第后赋菊

待到秋来九月八,我花开后百花杀。冲天香阵透长安,满城尽带黄金甲。

—- (唐)黄巢

西江月

自幼曾攻经史,长成亦有权谋。 恰如猛虎卧荒丘,潜伏爪牙忍受。 不幸刺文双颊,那 堪配在江州。 他年若得报冤仇,血染浔阳江口!

心在山东身在吴,飘蓬江海谩嗟吁。 他时若遂凌云志,敢笑黄巢不丈夫!

—- 水浒传 宋江
 

.net 开发service必须要写一个从Installer类继承的类

Filed under: 经验积累

出自

http://www.cnblogs.com/jjstar/archive/2004/07/02/20354.aspx

我一直有一个误区:只要从System.ServiceProcess.ServiceBase继承一个类并编译好就可以用.net提供的命令行程序InstallUtil.exe安装了。但实际上如果仅仅做了这样的一个类是无法用InstallUtil.exe安装的,在安装时会报错:

这是因为installUtil.exe会用反射的方法去查找所有把RunInstallerAttribute设置为true的System.Configuration.Install.Installer类型,并执行上面的Install方法,当找不到的时候,安装就失败了。
所以我们必须要写一个从Installer类继承的类来满足installUtil.exe的要求。

May 15, 2006

什么样的连接对于IIS来说是一个Inactive的连接?

Filed under: My Questions

IIS会回收一个Inactive的连接所占用的资源.如果一个用户请求提交了一个非常耗时的请求,然后等待响应,这个请求对应的连接是否是Inactive的?

调试时不要过分相信自己眼睛.以下代码有什么问题?

Filed under: 经验积累
If _cnt.ConnectionString.ToLower().IndexOf("Integrated") >= 0 Then
     Return True
Else

Web Method不能overloading

Filed under: 经验积累

WSDL不能区分两个名字一样,参数不同的web method

解决方案
1.不要这样搞
2.
[WebMethod (MessageName="HelloWorld")]
public string HelloWorld()
{
 return "HelloWorld";
}
[WebMethod (MessageName="HelloWorldWithName")]
public string HelloWorld(string name)
{
 return "HelloWorld " + name;
}

在proxy中添加了一个新方法,请进行下列检查

Filed under: 经验积累
1.Class上的System.Web.Services.WebServiceBindingAttribute 属性中的[Namespace]是否和proxy method上的SoapDocumentMethodAttribute属性中的RequestNamespace和ResponseNamespace保持一致,特别是 namespace最后的"/", 否则参数无法传递
2.proxy method中SoapDocumentMethodAttribute属性中URL ,web method的名字, Invoke中的字符串是否一致. 否则,web method访问失败.
3.proxy method 的参数名必须和web method一致,否则参数无法传递

操作Windows Service

Filed under: Code snippets

Namespace: System.ServiceProcess
Assembly: system.serviceprocess.dll

//—-判断本机是否运行了某项服务

ServiceController service = new ServiceController("MSSQLSERVER");

if(service.Stauts == ServiceProcess.ServiceControllerStatus.Running){…}

//—改变Service运行状态

private const string myService = "XXX";

ServiceController service = new ServiceController(myService );

if(service.Status != ServiceControllerStatus.Stopped)

{

    service.Stop();

    serviceControl.WaitForStatus(ServiceControllerStatus.Stopped);

}

service.Start();

//—-安装.net service

%SystemRoot%\Microsoft.NET\Framework\<Version>\InstallUtil /u /name=S1 myService.exe
%SystemRoot%\Microsoft.NET\Framework\<Version>\InstallUtil /name=S1 myService.exe
%SystemRoot%\system32\services.msc /s

//—-命令行操作

net start "myService"

net stop "myService"

Check UNC path

Filed under: Code snippets

Uri uri = new Uri("……….");

–Indicating whether the Uri is a universal naming convention (UNC) path.

Uri.IsUnc

–Indicating whether the specified Uri references the local host.

Uri.IsLoopback

正则表达式使用

Filed under: Regular Expression

—-代码—-

using System.Text.RegularExpressions;

string regexStr = "href\\s*=\\s*\"([^\"]*)\"";
Regex regex = new Regex (regexStr, RegexOptions.IgnoreCase);
MatchCollection matches = regex.Matches(text);

foreach (Match match in matches)
{
    //do sth…
}

—-正则表达式收集—-

//———————————————————–
//形如 href="http://msdn.microsoft.com/netframework/"的连接
//—-注意Group的使用\"([^\"]*)\"
//—-如果使用Groups[1],会返回  http://msdn.microsoft.com/netframework/
//—-如果使用Groups[0],会返回  href="http://msdn.microsoft.com/netframework/"

string regexStr = "href\\s*=\\s*\"([^\"]*)\""
foreach (Match match in matches)
{
    string myURL = match.Groups[1];
}       

Webcast_ ASP.NET 2.0中的异步页面

Filed under: Web cast学习

–参考–

Asynchronous Pages in ASP.NET 2.0
http://msdn.microsoft.com/msdnmag/issues/05/10/WickedCode/default.aspx
讲座中的内容来源于此

//—————————————————–
Asp.net运行原理:
//—————————————————–

    IIS() -> aspnet_isapi.dll ->aspnet_wp.exe
    
    Asp.net实际是一个IIS ISAPI Extension, 处理到.aspx, .asmx的请求
        C:\WINDOWS\Microsoft.NET\Framework\<version>\aspnet_isapi.dll
    Asp.net的工作进程(host):
        在IIS6中,当IIS运行在 worker process isolation mode 时(default),
        为IIS6的工作进程w3wp.exe
        如果使用ASP.NET Process Model,Asp.net的工作进程为
        C:\WINDOWS\Microsoft.NET\Framework\<version>\aspnet_wp.exe()
   
    win2003上IIS进程池中的进程host.exe,host了.net CLR   
   
    进程隔离级别在IIS5.0和IIS6.0上的区别
      
    运行帐号的不同 ASPNET(IIS5.0),Network service(IIS6.0)
   
    [*]如何测试web 站点的吞吐量:
        IIS Stress , Application center test.

//—————————————————–
Asp.net 1.1中的异步页面实现
//—————————————————–
–参考–
Use Threads and Build Asynchronous Handlers in Your Server-Side Web Code
http://msdn.microsoft.com/msdnmag/issues/03/06/Threading/

讲座中的例子也来源于此

通常情况下,ASP.NET 会调用页面的IHttpHandler.ProcessRequest来处理用户请求,
为了实现异步,在页面的code hehid class 中实现IHttpAsyncHandler,
然后使用IHttpAsyncHandler.BeginProcessRequest来处理请求.BeginProcessRequest会
launch另外一个线程,这个线程会调用base.ProcessRequest,来完成request处理,请注意,
在这种情况下,整个request处理不是使用线程池中的线程完成的,而是在BeginProcessRequest
launch出的线程中完成的.而且BeginProcessRequest在launch一个新线程后马上返回,这样一来.
执行BeginProcessReques的线程也会被重新放到线程池中.

* AsyncDelegate.ashx的扩展名表示它是一个Handler

//—————————————————–
Asp.net 2.1中的异步页面实现
//—————————————————–
1.设置
    <%@Page Async="true"…%>

2.在Page_Load中添加
    AddOnPreRenderCompleteAsync(new BeginEventHander(MyBeginMethod), new EndEventHandler(MyEndMethod));

//—————————————————–
异步调用Web 服务
//—————————————————–
使用proxy上的Completed Event
proxy.FooCompleted += new FooCompletedEventHandler(OnFooCompleted);

proxy.FooAsync (…);

void OnFooCompleted (Object source, FooCompletedEventArgs e)
{
    // Called when Foo completes
}

 

//———————————————
    完整的代码
//———————————————

public partial class AsyncPage : System.Web.UI.Page
{
    private WebRequest _request;

    void Page_Load (object sender, EventArgs e)
    {
        AddOnPreRenderCompleteAsync (new BeginEventHandler(BeginAsyncOperation), new EndEventHandler (EndAsyncOperation));
    }

    IAsyncResult BeginAsyncOperation (object sender, EventArgs e, AsyncCallback cb, object state)
    {
        _request = WebRequest.Create("http://msdn.microsoft.com");
        //—我的工作环境在一个局域网中,要运行例子,需要添加:
        _request.Proxy.Credentials = System.Net.CredentialCache.DefaultCredentials;
        return _request.BeginGetResponse (cb, state);
    }
   
    void EndAsyncOperation (IAsyncResult ar)
    {
        string text;
        using (WebResponse response = _request.EndGetResponse(ar))
        {
            using (StreamReader reader = new StreamReader(response.GetResponseStream()))
            {
                text = reader.ReadToEnd();
            }
        }

        Regex regex = new Regex ("href\\s*=\\s*\"([^\"]*)\"",  RegexOptions.IgnoreCase);
        MatchCollection matches = regex.Matches(text);

        StringBuilder builder = new StringBuilder(1024);
        foreach (Match match in matches)
        {
            builder.Append (match.Groups[1]);
            builder.Append("<br/>");
        }

        Output.Text = builder.ToString ();
    }
}

C#的const和readonly

Filed under: C#

–相同

const和readonly的值一旦初始化则都不再可以改写.

–不同

    const只能在声明时初始化;readonly既可以在声明时初始化也可以在构造器中初始化;
    const隐含static,不可以再写static const;readonly则不默认static,如需要可以写static readonly;
    const是编译期静态解析的常量(因此其表达式必须在编译时就可以求值);readonly则是运行期动态解析的常量;
    const既可用来修饰类中的成员,也可修饰函数体内的局部变量;readonly只可以用于修饰类中的成员

得到windows安装路径

Filed under: Code snippets

方法1 使用API

Private Declare Function GetWindowsDirectory Lib "kernel32.dll" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
 
‘ Return values as C:\Windows or <Driver>:\Windows
Public Function GetTheWindowsDirectory() As String
    Dim strWindowsDir As String        ‘ Variable to return the path of Windows Directory
    strWindowsDir = Space(250)         ‘ Initilize the buffer to receive the string
    GetWindowsDirectory(strWindowsDir, 250) ‘ Read the path of the windows directory
    Return strWindowsDir
End Function
   
方法2
Environment.GetEnvironmentVariable("windir")

Is string null or empty?

Filed under: Code snippets

Cheap and interesting trick:

    Convert.ToString((object)stringVar) == ""
 
This works because Convert.ToString(object) returns an empty string if object is null. 

注意!!!
Convert.ToString(string) returns null if string is null.

(Or, if you’re using .NET 2.0 you could always use String.IsNullOrEmpty.)

其实以上的代码还可以再优化一点点:

根据FxCop的建议,我们应该使用

 Convert.ToString((object)stringVar).Length==0

数字,日期的格式化

Filed under: Code snippets

–Custom Numeric Format Strings

    int a =100;
    Console.WriteLine(a.ToString("000000"));
   

    输出"000100"
  
– Standard Numeric Format Strings
    比如输出16进制数 X or x    Hexadecimal

    Console.WriteLine(a.ToString("X"));

    输出"64"

    Console.WriteLine(a.ToString("X6"));

    输出"000064"

– Composite Formatting

    Each format item takes the following form.
             {index[,alignment][:formatString]}

    String.Format("hours = {0:hh}", DateTime.Now); 得到 hours = 07

    String.Format("Date = {0:yy/MM/dd}", DateTime.Now);  得到 Date = 06-05-15

 

序列化

Filed under: Code snippets

参考
http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconBasicSerialization.asp

一个Class实现序列化需要使用SerializableAttribute() Attribute或实现ISerializable

缺省情况下,一个被SerializableAttribute标记的类型中的所有public和
private field(除过NonSerialized标记的field)都会被
序列化,如果想改变序列化的处理过程,需要实现ISerializable.
如果类型中包含pointer,将有可能无法从另一个环境中被反序列化,此时应该
用NonSerialized标记point字段

!!需要特别注意的是,Serializable 属性不能被继承。如果我们从 MyObject 派生一个新类,
此新类必须也用该属性标记,否则它不能被序列化。例如,当您试图序列化下面的类的实例时,
您将获得 SerializationException。

//========= A test object that needs to be serialized.
[Serializable()]       
public class TestSimpleObject 
{

    public int member1;
    public string member2;
    public string member3;
    public double member4;
   
    // A field that is not serialized.
    [NonSerialized()] public string member5;
   
    }
}

//=========使用
//==Bin
FileStream fs = new FileStream("my.bin" , FileMode.Creat);
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(fs , myObj);
fs.Close();

//==Soap
FileStream fs = new FileStream("my_Soap.xml" , FileMode.Creat);
SoapFormatter formatter = new SoapFormatter();
formatter.Serialize(fs , myObj);
fs.Close();

//==XML
FileStream fs = new FileStream("my.xml" , FileMode.Creat);
System.Xml.Serialization.XmlSerializer xmlSer = new System.Xml.Serialization.XmlSerializer(typeof(MyType));
xmlSer.Serialize(fs , myObj);
fs.Close();

//==Deserialize
IFormatter formatter = new BinaryFormatter();
Stream stream = new FileStream("MyFile.bin", FileMode.Open, FileAccess.Read, FileShare.Read);
MyObject obj = (MyObject) formatter.Deserialize(stream);
stream.Close();

如何得到当前Application的cofig文件的路径

Filed under: Code snippets

string cfgFullPath = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;

如何在程序运行时得到当前的call stack

Filed under: Code snippets

需要引入以下的namespace
using System.Diagnostics; //For StackTrace
using System.Reflection;  //MethodInfo

Step1. Create a StackTrace
    StackTrace stackTrace = new StackTrace();
    大多时情况下,我们希望在exception 发生时找到引发exceptioin的代码,
    此时需要使用
    try
    {
        …
    }
    catch(Exception exp)
    {
        StackTrace stackTrace = new StackTrace(exp);
    }
    此时通过stackTrace.ToString() 已经可以得到大致的callstack信息.

step2. 通过StatckFrame得到代码信息

    int frameCount = stackTrace.FrameCount;   
    for (int i = 0; i < frameCount; i++)
    {
        StackFrame stackFrame = stackTrace.GetFrame(i);

        // Display the stack frame properties.
        Console.WriteLine(" File: {0}", stackFrame.GetFileName());
        Console.WriteLine(" Line Number: {0}", stackFrame.GetFileLineNumber());
        Console.WriteLine(" Column Number: {0}", sf.GetFileColumnNumber());
        //还有很多其他的功能GetILOffset(),GetNativeOffset()…
    }

step3. 通过MethodInfo得到每一个函数的信息,用到的主要是Reflection的技巧
    int frameCount = stackTrace.FrameCount;   
    for (int i = 0; i < frameCount; i++)
    {
        StackFrame stackFrame = stackTrace.GetFrame(i);
        MethodInfo methodInfo = (MethodInfo)stackFrame.GetMethod();
       
        //1 get Access
        string access = string.Empty;
        if (methodInfo.IsPrivate)
            access = "private ";
        else if (methodInfo.IsPublic)
            access = "public ";
        else if (methodInfo.IsFamily)
            access = "protected ";
        else if (methodInfo.IsAssembly)
            access = "Internal ";
       
        if (methodInfo.IsStatic)
            access += "static ";
       
        //2 method nanme
        string methodName = methodInfo.Name;
       
        //3 parameter info
        ParameterInfo[] pInfos = methodInfo.GetParameters();
        string paramterList = string.Empty;
        for (int j = 0; j < pInfos.Length; j++)
        {
            paramterList += string.Format(", {0} {1}", pInfos[j].ParameterType.Name, pInfos[j].Name);
        }
       
        // Get rid of the first ", " if it exists.
        if (paramterList.Length > 2)
            paramterList = paramterList.Substring(2);
       
        string output = access + methodInfo.ReturnType.Name + " "+ methodName + "(" + paramterList + ")";
        Console.WriteLine(output);
       
    }   

如何得到.net framework的安装路径

Filed under: Code snippets

LOCAL_MACHINE\software\Microsoft\.NetFramework
下可以看到 InstallRoot为"C:\WINDOWS\Microsoft.NET\Framework\"

LOCAL_MACHINE\software\Microsoft\.NetFramework\policy
下会有key
v1.1
v2.0

每个key下会有当前的次版本号:
如:
v1.1->4322
v2.0->50727
根据InstallRoot, primer version, sub version就可以得到.net frame work的安装路径.

C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727

一个有创意的网站43things

Filed under: 网络资源

http://www.43things.com/

给Blog估价的网站

Filed under: 网络资源

博客价值评估工具由博易独家提供,根据Alexa排名、各大搜索引擎搜索记录数、RSS订阅数进行综合评估.

使用NAnt操作VSS

Filed under: NAnt

1.首先需要下载NAntContrib,把所有的文件和NAnt的执行文件放在一起.

2.NAntContrib会调用VSS的客户端来get源代码,如果不想安装VSS,可以
只copyVSS安装路径下的SSAPI.dll  和SSUS.dll,并注册ssapi.dll,命令如下:
regsvr32 ssapi.dll

3.script
——–get:
<vssget
     user="myusername"
      password="mypassword"
      localpath="myLocalpath"
      recursive="true"
      writable="true"
      dbpath="myVSS\srcsafe.ini"
      path="$/MyProduct"
    />
——-checkout:
  <vsscheckout
      user="myusername"
      password="mypassword"
      localpath="myLocalpath"
      recursive="true"
      writable="true"
      dbpath="myVSS\srcsafe.ini"
      path="$/MyProduct"
    />
注意localpath只能指定为本地路径
path,可以制定为vss中的路径或某个文件

——–checkin:
<vsscheckin
    user="myusername"
      password="mypassword"
      localpath="myLocalpath"
      recursive="true"
      writable="false"
      dbpath="myVSS\srcsafe.ini"
      path="$/MyProduct"
  comment="NAnt checkin"
/>

也可以直接使用vss来进行操作:
比如get:
<exec program="${vss_path}\ss.exe" commandline="GET ${path_vss} -R -I-Y -O- -GTM -GL${path_local}"
               output="my.log">
</exec>
只是那一堆的参数让人有点头大.

PetShop中的Facade

Filed under: 代码学习

在petshop中用到了HttpRuntime.Cache.Add()
其中第3个参数为dependencies,可以是null,说明此时无dependencie

petshop中的CacheDependency会根据web.confog来传递null,或dependencies
给HttpRuntime.Cache.Add()
这个变化被封装在DependencyFacade中
public static class DependencyFacade
{
private static readonly string path = ConfigurationManager.AppSettings[”CacheDependencyAssembly”];

//封装点
public static AggregateCacheDependency GetCategoryDependency()
{
if (!string.IsNullOrEmpty(path))
//这里又会用到Abstract Factory
return DependencyAccess.CreateCategoryDependency().GetDependency();
else
return null;
}
}

在使用时只会调用
// Create a AggregateCacheDependency object from the factory
AggregateCacheDependency cd = DependencyFacade.GetCategoryDependency();
// Store the output in the data cache, and Add the necessary AggregateCacheDependency object
HttpRuntime.Cache.Add(cacheKey, data, cd, DateTime.Now.AddHours(cacheDuration), Cache.NoSlidingExpiration, CacheItemPriority.High, null);
不用再判断何时需要传入null.

PetShop中的Abstract Factory

Filed under: 代码学习

在PetShop中,用户可以通过修改Web.Config来指定当前使用的数据访问层,
而不用修改任何代码,用到的核心技术为:Abstract Factory + config file

1.配置文件
<appSettings>
<add key=”WebDAL” value=”PetShop.SQLServerDAL”/>
<add key=”OrdersDAL” value=”PetShop.SQLServerDAL”/>

</appSettings>

2.在程序中有一个名为DALFactory的assemble,它只提供一个class充当Abstract Factory:
namespace PetShop.DALFactory
{

/// <summary>
/// This class is implemented following the Abstract Factory pattern to
/// create the DAL implementation
/// specified from the configuration file
/// </summary>
public sealed class DataAccess
{
//读取web.config
// Look up the DAL implementation we should be using
private static readonly string path = ConfigurationManager.AppSettings[”WebDAL”];
private static readonly string orderPath = ConfigurationManager.AppSettings[”OrdersDAL”];

private DataAccess() { }

public static PetShop.IDAL.ICategory CreateCategory()
{
string className = path + “.Category”;
return (PetShop.IDAL.ICategory)Assembly.Load(path).CreateInstance(className);
}

public static PetShop.IDAL.IInventory CreateInventory()
{
string className = path + “.Inventory”;
return (PetShop.IDAL.IInventory)Assembly.Load(path).CreateInstance(className);
}

public static PetShop.IDAL.IItem CreateItem()
{
string className = path + “.Item”;
return (PetShop.IDAL.IItem)Assembly.Load(path).CreateInstance(className);
}

public static PetShop.IDAL.IOrder CreateOrder()
{
string className = orderPath + “.Order”;
return (PetShop.IDAL.IOrder)Assembly.Load(orderPath).CreateInstance(className);
}

public static PetShop.IDAL.IProduct CreateProduct()
{
string className = path + “.Product”;
return (PetShop.IDAL.IProduct)Assembly.Load(path).CreateInstance(className);
}
}
}

以上代码逻辑基本相同:
CreateXXX先根据web.config中的信息拼接出一个classname(= config string + XXX),
然后使用CreateInstance生成实例并返回.

3. 在SQLServerDAL和OracleDAL中实现具体的class,实现对某个数据库的访问逻辑
public class Category : ICategory
{

}

这样的例子在PatShop中还有好几个.比如:
在web.config中可以个看到
<appSettings>
<add key=”ProfileDAL” value=”PetShop.SQLProfileDAL”/>

</appSettings>
代码中相应地可以找到

ProfileDALFactory
IProfileDAL
SQLProfileDAL
OracleProfileDAL

MessagingFactory
CacheDependencyFactory

May 14, 2006

如何判断一个dll是否是.net assembly

Filed under: Code snippets

方法1.

引用自http://lozanotek.com/archive/2004/11/15/159.aspx

private const int COR_E_ASSEMBLYEXPECTED = -2147024885;
private bool IsAssembly(string asmFile)
{
    bool isAsmbly = true;
    try
    {
         AssemblyName.GetAssemblyName(asmFile);
    }
    catch(BadImageFormatException imageEx)
    {
         int hrResult = Marshal.GetHRForException(imageEx);
         isAsmbly = (hrResult != COR_E_ASSEMBLYEXPECTED);
    }

    return isAsmbly;
}
方法2.运用PE格式的知识,佩服.

出自http://geekswithblogs.net/rupreet/archive/2005/11/02/58873.aspx

  public static bool GetCLRHeaders(string fileFullName)
        {
            uint peHeader;
            uint peHeaderSignature;
            ushort machine;
            ushort sections;
            uint timestamp;
            uint pSymbolTable;
            uint noOfSymbol;
            ushort optionalHeaderSize;
            ushort characteristics;
            ushort dataDictionaryStart;
            uint[] dataDictionaryRVA = new uint[16];
            uint[] dataDictionarySize = new uint[16];

            Stream fs = new FileStream(fileFullName, FileMode.Open, FileAccess.Read);
            try
            {
                BinaryReader reader = new BinaryReader(fs);

                //PE Header starts @ 0x3C (60). Its a 4 byte header.
                fs.Position = 0x3C;
                peHeader = reader.ReadUInt32();

                //Moving to PE Header start location…
                fs.Position = peHeader;
                peHeaderSignature = reader.ReadUInt32();

                //We can also show all these value, but we will be      
                //limiting to the CLI header test.
                machine = reader.ReadUInt16();
                sections = reader.ReadUInt16();
                timestamp = reader.ReadUInt32();
                pSymbolTable = reader.ReadUInt32();
                noOfSymbol = reader.ReadUInt32();
                optionalHeaderSize = reader.ReadUInt16();
                characteristics = reader.ReadUInt16();
                /*
                    Now we are at the end of the PE Header and from here, the
                    PE Optional Headers starts…
                    To go directly to the datadictionary, we’ll increase the
                    stream’s current position to with 96 (0x60). 96 because,
                    28 for Standard fields
                    68 for NT-specific fields

                    From here DataDictionary starts…and its of total 128 bytes. DataDictionay has 16 directories in total,
                    doing simple maths 128/16 = 8.
                    So each directory is of 8 bytes.
                    In this 8 bytes, 4 bytes is of RVA and 4 bytes of Size.
                    btw, the 15th directory consist of CLR header! if its 0, its not a CLR file :)
                  */

                dataDictionaryStart = Convert.ToUInt16(Convert.ToUInt16(fs.Position) + 0x60);
                fs.Position = dataDictionaryStart;
                for (int i = 0; i < 15; i++)
                {
                    dataDictionaryRVA[i] = reader.ReadUInt32();
                    dataDictionarySize[i] = reader.ReadUInt32();
                }
                return dataDictionaryRVA[14] != 0;
            }
            finally
            {
                fs.Close();
            }
        }

软件开发的隐喻

Filed under: 技术以外

看<<代码大全>>闹程序革命

Filed under: 技术以外

VS2005的Code Snippets

Filed under: Visual Studio

1.如何使用

可以使用菜单: Edit->ItelliSencse->Insert Smnippet 或使用Context meun :Insert Snippet也可以使用快捷键:Ctrl+K,Ctrl+X

2.使用很简单,关键是可以定制.使用菜单Tools->Code Snippet Manager可以看到Code Snippet所在的路径.

C:\Program Files\Microsoft Visual Studio 8\VC#\Snippets\1033\Visual C#

所有的code snippets文件都是xml格式,并以.snippet结尾

文件中有两个核心的节点用来实现功能

<Header>节点用来描述code snippet的title,快捷键,描述,比如using.snippet

<Header>
   <Title>using</Title>
   <Shortcut>using</Shortcut>
   <Description>Code snippet for using statement</Description>
   <Author>Microsoft Corporation</Author>
   <SnippetTypes>
    <SnippetType>Expansion</SnippetType>
    <SnippetType>SurroundsWith</SnippetType>
   </SnippetTypes>
  </Header>

<Snippet>用来描述要生成的code,以using.snippet为例:

它会生成如下代码

using(resource)
{
 
}

用户可以把resource替换为自己的代码,xml中的描述如下

<Snippet>
   <Declarations>
    <Literal>
     <ID>resource</ID>
     <ToolTip>Resource to use</ToolTip>
     <Default>resource</Default>
    </Literal>
   </Declarations>
   <Code Language="csharp"><![CDATA[using($resource$)
 {
  $selected$ $end$
 }]]>

   </Code>
  </Snippet>

<Literal>部分定义了可替换的部分的id和default

[!CDATA]部分定义了要生成的代码模板,

参考资料

Code Snippets in Visual Studio 2005 讲解Code Snippets的使用和自定义,并提供了一个例子

Advanced Basics: IntelliSense Code Snippets — MSDN Magazine, April 2006

文章中的附件提供了几个例子,值得参考,同时还提供了几个Code Snippet编辑器的地址,用到时再看吧

 MSDN Code Snippet Schema Reference

May 13, 2006

Blogsome的Categories菜单层级显示

Filed under: Blog使用

一直想有这种效果,去论坛上看了一下,刚好有这个问题的回答

Show Topic Categories and Subcategories

到Mange->files把index.html中的

{list_cats optionall=0 all=All sort_column=name}

修改成就可以了
{list_cats hide_empty=0 optioncount=1 sort_column=name hierarchical=1 children=1}

此外,还可以添加optiondates=1, feed=RSS,optional=1  效果试试就知道了.

(为了方便显示,我去掉了所有的value的单引号)

杜琪峰的<<黑社会2>>

Filed under: 娱乐

刚看完黑社会1,2就出来了,有了无间道虎头蛇尾的前车之鉴,我从一开始就很怀疑2的质量,5.1放假的时候终于下载了一个(罪过,罪过).果然,1中性格迥然的几个角色在2里已被糟蹋得不堪入目,实在无法想象阿乐会一脚把邓伯踹下楼梯,做话事人的这两年在忙什么?临了和吹鸡一样,派手下把龙头棍藏起来,第2次,或许是第n次证明,大家拼的是实力,棍子只是棍子.总之,觉得阿乐的智力是黑社会1中的1/2.东莞仔在1中是一个精明,冷脆的角色,1中刚开始东莞仔指挥运"货"的一节给我留下了深刻的印象,后来的夺棍,送棍,也是处处出彩,在2中忽然像是被1中的大b附身,暴力无脑,唯一出彩的就是冲入货柜,并在后门打开时直立而出.2和1中反差最大的其实是警匪关系,1中邓伯在警局中侃侃而谈,说得总警司无言以对,到了2中,吉米仔在副庭长面前哭得象个小姑娘,鲜明地展示了一个公式:香港警察<香港黑社会<大陆警察.警匪片可以这般如此,也算是很有几分新意.

从枪火开始喜欢杜琪峰的电影,全男班的人马,精彩紧凑的情节,完全不屑于加入善男信女的所谓爱情元素,杜琪峰的电影中的女人,要么是象水浒传中的女人,仅仅是一个可有可无的标点符号,要么就是一个大哥背后的大姐,这一次不同了,我们看到了女人的眼泪,男人的柔情,老杜,这还是你吗?

Web Service bin目录下的Dll

Filed under: 经验积累

在debug web service时,想临时往bin目录下拷贝一个文件,但是又不想覆盖原来的文件,于是我就修改了原来的文件名,并copy了一个新的文件,

注意!这个修改并不生效,在web service的执行过程中,仍然会使用旧的文件,正确的做法是把老的文件移到别的目录,再copy新的文件.

其中的原因就是asp.net在某处备份了bin目录下的文件,并监视了对这些文件的修改.

Hello world!

Filed under: 随便说说

一直想找一个地方记录自己工作,学习中的收获,以前也去过几个地方,但好像都不支持多层的分类管理,今天终于得逞,于是最后一个偷懒的理由也不成了.开始写吧.

ASP.NET 的Session State

Filed under: ASP.NET

1.Session的本质
每一个用户和web application交互过程被称为Session.
为了可以给每个Session存取一些信息,出现了Session state机制,SessionState实际上就是一个
在seesion 的生命周期中可以读写的hashtable或dictionary(在ASP时代,这个数据结构存放在内存中),
Session[”Stocks”] =” “; //写
string stockString = Session[”Stocks”];//读

如何区分不同用户的session state呢? 在ASP时代,每一个用户在session开始时会得到一个key,
这个key会被存在cookie中,每一个用户请求都会把这个key也发给server,server就能根据这个key
找到该用户对应的session state.

2.局限
以上是session最初的实现机制,很快,这个实现就被发现有如下的局限性
[1] ASP session state存放在asp的工作进程中,如果进程崩溃,或被回收,session state将丢失
[2] ASP session state存放在asp的工作进程中,所以在使用server farm的情况下,一个server上
的用户的session 信息在另一个server将不可用.
[3] 用户可能禁止cookie,这会导致session state不可用

3.ASP.NET的session state
ASP.NET支持3种session state的存储方式.
[1] in-process 和asp的session state兼容,Session Value被存放在ASP.net 的工作进程的内存中.
ASP.NET的工作进程为: aspnet_wp.exe或w3wp.exe(win 2003)

web.config的写法
<configuration>
<sessionstate mode=”inproc” timeout=”20″ />
</configuration>

[2] state server
session 会被存在state server上一个名为aspnet_state.exe的service的内存中,这个service是一个独立的进程,
可以运行在和IIS不同的机器上, 防止工作进程崩溃后session丢失.
首先要启动 service : net start aspstate
再在web.config中设定mode,server, port
<configuration>
<sessionstate mode=”stateserver”
cookieless=”false”
timeout=”20″
server=”127.0.0.1″
port=”42424″ />
</configuration>

[3] sql server
session会被存在sql server中,用于支持server farm
首先要安装相应的数据库,sql脚本存在于Microsoft.NET\Framework\[version]\
osql -S [server name] -U [user] -P [password] <InstallSqlState.sql

或执行

Microsoft.NET\Framework\[version]\\aspnet_regsql -S .\sql2k5 -E -ssadd -sstype p

再在web.config中设定mode,server, port
<configuration>
<sessionstate mode=”sqlserver”
cookieless=”false”
timeout=”20″
sqlconnectionstring=”data source=MySqlServer; user id=<…>; password=<…>”/>
</configuration>

同时ASP.NET还实现了无cookie的 session state访问.
ASP.NET通过ISAPI filter修改了URL,
http://localhost/(lit3py55t21z5v55vlm25s55)/Application/SessionState.aspx
这样就相当于提供了cookie.
–如何根据一个原始的用户请求来修改URL呢?

参考资料

ASP.NET Session State(2000)***

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspnet/html/asp12282000.asp

Underpinnings of the Session State Implementation in ASP.NET(Dino Esposito 2003.9)*****

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaspp/html/aspnetsessionstate.asp

.NET Framework Developer’s Guide: Session State

PRB: Session State Is Lost in Web Farm If You Use SqlServer or StateServer Session Mode
http://support.microsoft.com/default.aspx?scid=kb;en-us;325056

Working on a Web Farm(1999)
http://www.microsoft.com/mind/0699/basics/basics0699.asp

How to create keys by using Visual Basic .NET for use in Forms authentication
http://support.microsoft.com/kb/313091/






















Get free blog up and running in minutes with Blogsome
Theme designed by Hadley Wickham