2010年12月26日

C#实现通过程序自动抓取远程Web网页信息,HtmlDocument,循环取出数据

        通过程序自动的读取其它网站网页显示的信息,类似于爬虫程序。比方说我们有一个系统,要提取BaiDu网站上歌曲搜索排名。分析系统在根据得到的数据进行数据分析。为业务提供参考数据。
  为了完成以上的需求,我们就需要模拟浏览器浏览网页,得到页面的数据在进行分析,最后把分析的结构,即整理好的数据写入数据库。那么我们的思路就是:
  1、发送HttpRequest请求。
  2、接收HttpResponse返回的结果。得到特定页面的html源文件。
  3、取出包含数据的那一部分源码。
  4、根据html源码生成HtmlDocument,循环取出数据。
  5、写入数据库。

程序如下:  

        //根据Url地址得到网页的html源码
         private string GetWebContent(string Url)
         {
             string strResult="";
             try
             {

                //创建访问目标
                 HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
    //声明一个HttpWebRequest请求
                 request.Timeout = 30000;
                //设置连接超时时间
                 request.Headers.Set("Pragma", "no-cache");

                 //得到回应
                 HttpWebResponse response = (HttpWebResponse)request.GetResponse();

                 //得到数据流
                 Stream streamReceive = response.GetResponseStream();

                 //对获取到的数据流进行编码解析,让我们可以进行正常读取
                 Encoding encoding = Encoding.GetEncoding("GB2312");
                 StreamReader streamReader = new StreamReader(streamReceive, encoding);

                 //读取出数据流中的信息
                 strResult = streamReader.ReadToEnd();

                 //关闭流

                streamReader.Close();

                //关闭网络响应流

                response.Close();
             }
             catch
             {
                 MessageBox.Show("出错");
             }
             return strResult;
         }
为了使用HttpWebRequest和HttpWebResponse,需填名字空间引用
  using System.Net;

以下是程序具体实现过程:
private void button1_Click(object sender, EventArgs e)
         {
            //要抓取的URL地址
             string Url = "http://list.mp3.baidu.com/topso/mp3topsong.html?id=1#top2";

            //得到指定Url的源码
   string strWebContent = GetWebContent(Url);

             richTextBox1.Text = strWebContent;
    //取出和数据有关的那段源码
             int iBodyStart = strWebContent.IndexOf("<body", 0);
             int iStart = strWebContent.IndexOf("歌曲TOP500", iBodyStart);
             int iTableStart = strWebContent.IndexOf("<table", iStart);
             int iTableEnd = strWebContent.IndexOf("</table>", iTableStart);
             string strWeb = strWebContent.Substring(iTableStart, iTableEnd - iTableStart + 8);

            //生成HtmlDocument
   WebBrowser webb = new WebBrowser();
             webb.Navigate("about:blank");
             HtmlDocument htmldoc = webb.Document.OpenNew(true);
             htmldoc.Write(strWeb);
             HtmlElementCollection htmlTR = htmldoc.GetElementsByTagName("TR");
             foreach (HtmlElement tr in htmlTR)
             {
                 string strID = tr.GetElementsByTagName("TD")[0].InnerText;
                 string strName = SplitName(tr.GetElementsByTagName("TD")[1].InnerText, "MusicName");
                 string strSinger = SplitName(tr.GetElementsByTagName("TD")[1].InnerText, "Singer");
                 strID = strID.Replace(".", "");
                //插入DataTable
                 AddLine(strID, strName, strSinger,"0");

                 string strID1 = tr.GetElementsByTagName("TD")[2].InnerText;
                 string strName1 = SplitName(tr.GetElementsByTagName("TD")[3].InnerText, "MusicName");
                 string strSinger1 = SplitName(tr.GetElementsByTagName("TD")[3].InnerText, "Singer");
                //插入DataTable
                 strID1 = strID1.Replace(".", "");
                 AddLine(strID1, strName1, strSinger1,"0");

                 string strID2 = tr.GetElementsByTagName("TD")[4].InnerText;
                 string strName2 = SplitName(tr.GetElementsByTagName("TD")[5].InnerText, "MusicName");
                 string strSinger2 = SplitName(tr.GetElementsByTagName("TD")[5].InnerText, "Singer");
                //插入DataTable
                 strID2 = strID2.Replace(".", "");
                 AddLine(strID2, strName2, strSinger2,"0");

             }
            //插入数据库
             InsertData(dt);
   
             dataGridView1.DataSource = dt.DefaultView;


2010年12月20日

嵌入的flash遮挡弹出div层解决方法

当网页中嵌入flash时会遮挡出JavaScript代码生成的div层;这个问题的解决方法是要在嵌入的flash代码中加入以下参数设置:
用于解决IE问题,设置wmode参数。

1
<span style="color: rgb(0, 153, 0);"><<span style="color: rgb(0, 0, 0); font-weight: bold;">param</span> <span style="color: rgb(0, 0, 102);">name</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"wmode"</span> <span style="color: rgb(0, 0, 102);">value</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"transparent"</span> <span style="color: rgb(102, 204, 102);">/</span>></span>

在FF下要给embed标签加入下面wmode属性,

1
<span style="color: rgb(0, 153, 0);"><embed <span style="color: rgb(0, 0, 102);"> </embed>src</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"你的flash.swf"</span> wmode<span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"transparent"</span> ... ><<span style="color: rgb(102, 204, 102);">/</span>embed></span>

现在FF下也支持

<span style="color: rgb(0, 153, 0);"><<span style="color: rgb(0, 0, 0); font-weight: bold;">param</span> <span style="color: rgb(0, 0, 102);">name</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"wmode"</span> <span style="color: rgb(0, 0, 102);">value</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"transparent"</span> <span style="color: rgb(102, 204, 102);">/</span>></span>

下面的示例:
完整代码

1<br />2<br />3<br />4<br />5<br />6
<span style="color: rgb(0, 153, 0);"><<span style="color: rgb(0, 0, 0); font-weight: bold;">object</span> <span style="color: rgb(0, 0, 102);">width</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"480"</span> <span style="color: rgb(0, 0, 102);">height</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"400"</span> <span style="color: rgb(0, 0, 102);">data</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"你的flash.swf"</span> <br /><span style="color: rgb(0, 0, 102);">type</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"application/x-shockwave-flash"</span>></span><br /><span style="color: rgb(0, 153, 0);"><<span style="color: rgb(0, 0, 0); font-weight: bold;">param</span> <span style="color: rgb(0, 0, 102);">name</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"wmode"</span> <span style="color: rgb(0, 0, 102);">value</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"transparent"</span> <span style="color: rgb(102, 204, 102);">/</span>></span><br /><span style="color: rgb(0, 153, 0);"><<span style="color: rgb(0, 0, 0); font-weight: bold;">param</span> <span style="color: rgb(0, 0, 102);">name</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"align"</span> <span style="color: rgb(0, 0, 102);">value</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"middle"</span> <span style="color: rgb(102, 204, 102);">/</span>></span><br /><span style="color: rgb(0, 153, 0);"><<span style="color: rgb(0, 0, 0); font-weight: bold;">param</span> <span style="color: rgb(0, 0, 102);">name</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"src"</span> <span style="color: rgb(0, 0, 102);">value</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"你的flash.swf"</span> <span style="color: rgb(102, 204, 102);">/</span>></span><br /><span style="color: rgb(0, 153, 0);"><<span style="color: rgb(0, 0, 0); font-weight: bold;">param</span> <span style="color: rgb(0, 0, 102);">name</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"quality"</span> <span style="color: rgb(0, 0, 102);">value</span><span style="color: rgb(102, 204, 102);">=</span><span style="color: rgb(255, 0, 0);">"high"</span> <span style="color: rgb(102, 204, 102);">/</span>></span><br /><span style="color: rgb(0, 153, 0);"><<span style="color: rgb(102, 204, 102);">/</span><span style="color: rgb(0, 0, 0); font-weight: bold;">object</span>></span>

wmode 属性/参数官方参考网址:http://livedocs.adobe.com/flash/8_cn/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000852.html

以下为官方定义:
wmode 属性/参数

Window | Opaque | Transparent

模板变量:$WM
说明

(可选)允许使用 Internet Explorer 4.0 中的透明 Flash 内容、绝对定位和分层显示功能。此标记/属性仅在带有 Flash Player ActiveX 控件的 Windows 中有效。

“Window”在 Web 页上用影片自己的矩形窗口来播放应用程序。”Window”表明此 Flash 应用程序与 HTML 层没有任何交互,并且始终位于最顶层。

“Opaque” 使应用程序隐藏页面上位于它后面的所有内容。

“Transparent”使 HTML 页的背景可以透过应用程序的所有透明部分显示出来,并且可能会降低动画性能。

“Opaque windowless”和”Transparent windowless”都可与 HTML 层交互,从而允许 SWF 文件上方的层遮蔽应用程序。这两种选项之间的差异在于”Transparent”允许透明,因此,如果 SWF 文件的某一部分是透明的,则 SWF 文件下方的 HTML 层可以透过该部分显示出来,而”opaque”则不会显示。

如果忽略此属性,默认值为 Window。仅适用于 object。



2010年12月19日

Linux之CentOS5下安装AMP环境的心得体会

CentOS5下安装AMP环境的心得体会
本人刚刚学习Linux,看别人搭建一个LAMP环境很简单,所以觉得也很容易,在这个实验中碰到不少的问题,同时也学习到不少的知识,希望对学习Linux的新手有点帮助。
安装准备
1、在http://www.mysql.com/下载mysql5 具体安装包为mysql-5.0.85.tar.gz
2、在http://www.apache.org/下载Apache2 具体安装包为httpd-2.2.13.tar.gz
3、在http://www.php.net/下载php5 具体安装包为php-5.3.0.tar.gz
安装步骤
1、安装mysql
a、首先解压mysql包
tar -zxvf mysql-5.0.85.tar.gz
b、用configure对选项进行配置
configure --prefix=/usr/local/mysql
执行命令后在,在最后出现以下故障
编译Mysql时configure: error: No curses/termcap library found 的错误解决方法
解决方法:此错误表示缺少一个软件,安装ncurses软件后及可以解决,此软件可在以下网站获得:
http://www.gnu.org/software/ncurses/
此软件的具体安装可以看本软件中的INSTALL。
重新执行选项配置命令
configure --prefix=/usr/local/mysql
无错误提示
c、编译
make
d、安装
make install
e、配置mysql的具体的选项
cp support-files/my-medium.cnf /etc/my.cnf   
cd /usr/local/mysql
chown -R mysql .
chgrp -R mysql .
bin/mysql_install_db --user=mysql
chown -R root .
chown -R mysql var
bin/mysqld_safe --user=mysql &
最后一步后mysql启动成功,mysql成功安装
2、Apache的安装
Apache的安装很顺利没有出现什么问题
安装方法如下:
tar -zxvf httpd-2.2.13.tar.gz
./configure --enable-so  --prefix=/usr/local/apache
make
make install
/usr/local/apache/bin/apachectl start
3、php5的安装
a、安装
./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql 时
遇到以下的问题:
configure: error: xml2-config not found. Please check your libxml2 installation
解决方法:执行如下命令在线安装libxml2-devel :yum install libxml2 libxml2-devel
解决编译PHP错误Cannot find MySQL header files under yes
解决方法:缺少了 mysql-devel 安装包,在线安装此包:yum install -y mysql-devel
./configure --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql
make && make install
b、修改相关的配置等
拷贝配置文件指点路径
cp php.ini-development /usr/local/lib/php.ini (在php-5.3.0.tar.gz中没有安装说明中说的php.ini-disk和php.ini-recommended文件,php.ini-dist和php.ini-recommended对应的ini文件是php.ini-development和php.ini-production)
修改Apache的配置文件加入以下两条
LoadModule php5_module modules/libphp5.so
AddType application/x-httpd-php .php .phtml
c、重启Apache
service httpd restart
成功安装!
在组目录下新建个info.php文件,内容为:
<?php
phpinfo();
?>测试通过。出现php的相关信息。
结论
实验成功,之前看别人做这个搭建lamp很简单,但是在自己实际的安装过程中却遇到很多细节上的问题,不能眼高手低,学习Linux必须多动手学习!!!希望54里面想学习Linux的ma友们,多多动手!让我们共同提高!

Centos5.5下编译安装AMP环境

centos最近发布了5.5版本,但AMP软件包并没有升级(Apache2.2.3/php5.1.6/mysql.5.0.40);所以为了能使用最新稳定版,需要自己编译安装。下面是具体的安装步骤,对于优化细节暂不做多的考虑。

1.准备相应的软件包。

下载相应的软件包放在/usr/local/src目录下。

2.安装mysql

在编译安装mysql之前。需先装ncurses

02 
03chmod +x ncurses-5.7.tar.gz
04 
05tar xzvf ncurses-5.7.tar.gz
06 
07./configure --with-shared --with-normal --with-debug --enable-overwrite
08 
09make
10 
11make install

编译安装mysql。注意–with-innodb是安装innodb引擎

01tar xzvf mysql-5.1.48.tar.gz
02 
03cd mysql-5.1.48
04 
05groupadd db
06 
07useradd -g db mysql
08 
09passwd mysql
10 
11./configure --prefix=/usr/local/mysql --enable-assembler  --with-mysqld-ldflags=-all-static  --with-client-ldflags=-all-static --with-charset=utf8 --with-collation=utf8_general_ci --with-extra-charsets=all  --with-unix-socket-path=/usr/local/mysql/tmp/mysql.sock --with-mysqld-user=mysql --with-innodb
12 
13make
14 
15make install
16 
17cd /usr/local/mysql
18 
19cp share/mysql/my-medium.cnf /etc/my.cnf
20 
21cp /usr/local/src/mysql-5.1.43/support-files/mysql.server /etc/init.d/mysqld
22 
23./bin/mysql_install_db
24 
25./bin/mysqld_safe &

可能出现的问题,在启动/etc/init.d/mysqld start出现MySQL manager or server PID file could not be found! [FAILED]

解决办法:打开vi /etc/my.cnf文件,在[mysqld]下面加入如下配置

1basedir = /usr/local/mysql
2 
3datadir = /usr/local/mysql/data
4 
5log-error = /usr/local/mysql/log/alert.log
6 
7log_slow_queries = /usr/local/mysql/log/slow.log

3 安装Apache

1tar xzvf httpd-2.2.15.tar.gz
2 
3cd httpd-2.2.15
4 
5./configure --prefix=/usr/local/apache2/

4安装PHP

在安装PHP之前,需要先安装libxml2软件包,不然在编译过程中会出现configure: error: xml2-config not found. Please check your libxml2 installation。

1yum install libxml2-devel

下面是编译安装php的具体过程

01tar xzvf php-5.2.13.tar.gz
02 
03cd php-5.2.13
04 
05./configure --prefix=/usr/local/php --with-apxs2=/usr/local/apache2/bin/apxs --with-mysql=/usr/local/mysql --with-mysqli=/usr/local/mysql/bin/mysql_config
06 
07make
08 
09make test
10 
11make install
12 
13cp php-dist /usr/local/php/lib/php.ini

5安装完毕后,需要配置 php.ini和httpd.conf

打开vi /etc/local/php/lib/php.ini,查找”include_path” 加入路径”/usr/local/php/lib”;

打开vi /usr/local/apache2/conf/http.conf。加入如下指令

01</pre>
02AddType application/x-httpd-php .php
03 
04AddType application/x-httpd-php-source .phps
05 
06<IfModule dir_module>
07 
08DirectoryIndex index.php index.html
09 
10</IfModule>
11 
12keepAlive Off
13 
14<IfModule prefork.c>
15 
16StartServers 5
17 
18MinSpareServers 5
19 
20MaxSpareServers 10
21 
22MaxClients 255
23 
24MaxRequestsPerchild 10
25 
26</IfModule>
27<pre>

6 使用apxs安装编译过程中没有安装的Apache模块

如果在编译Apache的过程中,没有使用–with-rewrite选项。则需要增加mod_rewrite模块。以下是安装过程

1</pre>
2cd /usr/local/apach2/modules/mappers
3 
4/usr/local/apache2/bin/apxs -i -a -c mod_rewrite.c
5<pre>

在httpd.conf中查看LoadModule rewrite_module modules/mod_rewrite.so是否开启。AllowOverride 改为All

7 使用php-config安装编译过程中没有安装的PHP模块

安装gettext

01</pre>
02cd /usr/local/src/php-5.1.13/etc
03 
04cd ./gettext
05 
06/usr/local/php/bin/phpize
07 
08./configure --with-php-config=/usr/local/php/bin/php-config
09 
10make
11 
12make install
13<pre>

安装gd

01</pre>
02yum install libpng-devel
03 
04yum install libjepg-devel
05 
06yim install freetype-devel
07 
08cd /usr/local/src/php-5.1.13/etc/gd
09 
10/usr/local/php/bin/phpize
11 
12./configure --with-php-config=/usr/local/php/bin/php-config
13 
14make
15 
16make install
17<pre>

安装完毕后gettext.so和gd.so写到php.ini文件中.(extension=/usr/local/php/lib/php/extensions/no-debug-non-zts-20060613/

gettext.so)

同理。安装mcrypt。在安装mcrypt之前注意先安装yum install libmcrypt libmcrypt-devel

出现的问题:
问题一:PHP安装GD库后发现无法处理JPEG,JPG类型的图片;
解决办法:首先查看系统GD库文件存在哪些.输入命令:gdlib-config –all 结果如下:

includedir: /usr/include
cflags: -I/usr/include
ldflags: -L/usr/lib
libs: -lXpm -lX11 -ljpeg -lfontconfig -lfreetype -lpng12 -lz -lm
libdir: /usr/lib
features: GD_XPM GD_JPEG GD_FONTCONFIG GD_FREETYPE GD_PNG GD_GIF

有GD_JPEG说明libjpeg.so动态库在/usr/lib目录下。出现问题的原因应该是编译安装GD库是没有指名JPEG的路径。所以,重新编译下GD库。方法如下
cd /usr/local/src/php-5.2.13/ext/gd
./configure --with-php-config=/usr/local/php/bin/php-config --with-jpeg-dir=/usr/lib
make
make install
/etc/init.d/apache restart

问题解决。



2010年12月18日

Windows编程革命简史

首先,是 Windows API 和 DLL Hell。(译注:DLL Hell——DLL灾难,就是微软的DLL升级时因为不同版本可能造成应用程序无法运行的灾难,首当其冲的是COM编程,相信大家都知道某些木马或是病毒更改了一些系统的DLL可以导致整个Windows不举,这就是DLL Hell) 于是,第一次革命是DDE——我们可以创建一个状态条在上面显示Microsoft的股票价格(译注:Dynamic Data Exchange,工作原理是: 甲方申请一块全局内存,然后把内存指针postmessage到乙方,乙方根据收到的指针访问那块全局内存)。

在那个时候,Microsoft 创建了 VERSIONINFO 资源来管理版本信息,当然,是用来消除DLL Hell。但是,另一个微软内部的小组发现了DDE的致命缺陷:这不是他们做的!

为了解决这个问题,他们创造了OLE(很像DDE,只是名字不一样),而且,我还记得在一次 Microsoft 大会上,某个微软的演讲者正式宣布—— Windows API 马上就会被 OLE API 所重写并取代,我还盲目地相信了这一说法。而且,所有的在图形界面的控件都会是OCX,那是OLE引入的接口,同样,其目的是为了消除DLL Hell。相信大家都记得,那个时候,我们是怎么地梦想着有一天,我们的应用程序(当然是非常大的程序)可以完全地被嵌入到Word文档中。

然而,在Microsoft的某处,Microsoft有些人开始信仰 C++,其确信MFC的出现并可以解决所有的一切问题,但是,因为历史原因,OLE并没有出局,其改了一个名字,叫COM,此时,我们立马意识到OLE(以前的DDE?)真正意味着什么——其用精心的版本管理系统来消除DLL Hell。与此同时,Microsoft的一个变节小组发现了一个MFC的致命缺陷:这不是他们做的!

当然,微软件的动作是很快的,他们立刻修正了问题——创造了ATL,有些像MFC,只是名字不同,他们想使用漂亮的ATL把那些晦涩难懂的COM的知识给隐藏住。这个动作刺激了COM团队(或是OLE团队?)改名为ActiveX,并发布了成千上万的新接口(甚至是很多版本化的接口,当然,主要目的是为了消除DLL Hell),当然,ActiveX可以让我们的程序可以从Web游览器上下载,并可以完美地和病毒一起嵌入浏览器中(哈,还不紧跟时代,感谢ATL吧)。此时,操作系统团队就像一个失宠的孩子一样,大声呼喊着“Cairo操作系统来了”引起大家注意,当然有一些怪异恶心的东西连他们自己也无法解释清楚,所以,别提发布了。为了声誉,操作系统团队的确引入了“系统文件保护”的理念,当然也是为了消除DLL Hell。

这个时候,Microsoft的某个团队发现了Java的致命缺陷:这不是他们做的!于是他们创造了一个叫J,或是Jole,或是ActiveJ的东西(对不起,我真的记不起叫什么了)来挽救Java(译者:应该是Visual J++)。看起来很像Java,只是名字不同罢了。这太让人兴奋了,但是Sun使用了一些相当古老的法律条款向Microsoft提起了法律诉讼,其在一年内限制了任何一个公司可以发布类似Java的产品。这明显是抑制微软复制别人产品的一次尝试,唯一不同的,其结果导致了微软流向国会议员裤兜的现金网络的建立(在这个网络可以得到时事新闻和价值$14.75的T恤衫)。还记得 J/Jole/ActiveJ 的项目经理用他的鞋桌在敲着桌子并信誓旦旦地坚持 Microsoft 将永远不会放弃他的产品。SB!所有的这些也就仅仅意味着一件事——没有人关心ActiveX团队(或者是COM?)。令人难以置信的是,微软把这些东东全部集成起来,成了COM+(难道不应该是ActiveX+?),还有MTS(我不知道为什么没有COM和Active或是X或是+的字眼,而直接叫MTS了——我为这个名词感到实实在在地震惊!)。他们总是那么NB地为那些流行词加上“+”号。在那段时间,还有人曾叫喊着“Windows DNA”以及“Windows Washboard”,但这两个东西最终在我搞清是什么玩意的之前就夭折了。

在这一点上,Microsoft已经很不安地窥视着Internet好几年了,他们终于意识到Internet上有一个致命缺陷:嗯,你应该知道这是什么(译注:Internet不是做他们做的!)。于是他们开始培养我们和.NET约会(.NET的发音很像“doughnut”圆环图,不过,这只是他们的唯一不同),这和Internet很相似,只不过.NET有更多的印刷品。其让我们清楚再清楚地了解一件事:.NET会消除DLL Hell。.NET包含了一个新的编程语言,叫C#(为了解决已经死翘翘的Active++ J++的缺陷)。.NET还包含一个虚拟机,所有的语言都运行在上面(这主要是为了解决依赖于Intel CPU的缺陷)。.NET还包含了一个单一的登录系统(这主要是为了解决“不把口令存放在Microsoft服务器上”的缺陷)。实际上,我们更容易做的是把.NET不包含的事给列出来。.NET绝对是一个划时代地Windows编程革命……当然,仅到明年。



一些非常不错的资料

一、Intel 给开发人员推荐的资料列表(2010年下半年)

Intel Recommended Books for Developers

其中包含了

  • 硬件:硬件,电源,存储,无线
  • 软件:多线程和多核技术,高性能计算,图形游戏,用户关注
  • 嵌入式:设计,软件,操作系统,安全,优化。
  • IT部门:策略和决策,服务器和数据中心,客户端

--

二、jQuery Fundamentals

jQuery Fundamentals

这可能是我见过写得最好的jQuery教程了,大量的示例,只是没有时间和精力,不然一定全部翻译过来。

jQuery Fundamentals - Code Example

还有其它关于jQuery的文章,你还可以查看《25个jQuery的编程小抄

--

三、How to Design Programs

How to Design Programs

想学学如何设计程序吗?英国剑桥大学写的,MIT出版的,希望你能看看,非常不错。

--

四、Microsoft All-In-One Code Framework

Microsoft All-In-One Code Framework

C++/C#/VB.NET的一站式代码和资料,还有coding standard,也是很不错的。

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

查看《免费电子书列表》查看更多的电子书。



Windows下和程序员相关小工具

1 HOUR SOFTWARE – 很多的小工具集

.NET Memory Profiler – 可以找出.NET程序中的内存泄露问题,并找出可优化的内存。

.NET Reflector – 查看,导航,搜索.NET汇编中的类的继承关系。

Active Webcam – Webcam 视频监视软件。

ArsClip – 剪贴版管理程序,可以跟踪每次剪贴版中的内容,并可以通过设置热键,取出粘贴其中的内容。

ASP2ASPX – 转换ASP 程序页到ASP.NET

AutoHotKey – 自动点击键盘和鼠标。

Awave Studio – 几乎是所有的音频格式的转换程序。

Batch files – 想要不同功能的bat文件吗?这个站点集成了很多功能强大的bat文件。

BartPE – 制作一张可以启动的Windows CD/DVD

Beyond Compare – 快速容易地比较和合并本地,远程或FTP服务器上的文件和目录。

BitPim – 可以查看并操作绝大多数的 CDMA 手机

Bullzip PDF Printer – PDF文件打印机程序。

Cain & Abel – 口令恢复工具。(可以用作正常和不正常的情况)

Camtasia Studio – 屏幕录像工具。

C# Programming Tools – C# 开发工具

CCleaner – 系统优化,隐私和清理工具。

Cisco VPN Clients – Cisco VPN客户端。

Clone Detective – 这是一个集成到Visual Studio 中,允许你分析自己的C# projects 中是否有重复的代码,以便你重构你的代码。

CodeSmith – 代码生成器,可惜是收费的。

Commit Monitor – 一个任务栏中的小监视器,当 subversion 的源代码被别人更新过了,他可以通知你。

Consolas Font Pack – 终级的程序字体。(VS2005)

CurrPorts – 把所有打开的 TCP/IP 和UDP 端口都列出来。

DAEMON Tools Lite – 大名鼎鼎的超轻量级的虚拟光驱程序。

DialAFix – 可以修复很多不同的Windows 问题的小工具。

DiskAction – 查看目前的进程是怎么在存取你的硬盘的。

DoubleKiller – 查找相同的文件,并保留其中的一份。

Doxygen – 一个通过程序注释创建程序文档的工具,非常有用。

DriverMax – 导出所有驱动器的数据到一个目录或一个压缩文件中。

Debug Inspector – 在多线程中,可以同时看到各个线程的函数调用栈。并可以检测死锁。

EAC – 从CD或DVD中捕捉音视的程序。

Eraser – 彻底地删文件,删除文件后,在原来分配给文件的硬盘上写上一些随机的字符。

EVEREST – PC 诊断和benchmark的工具。

Fiddler – Web 调试代理。

FILEACL – NTFS 权限管理工具。

FileMenu Tools – Explorer 的右键菜单管理工具。

FileZilla – 鼎鼎大名的FTP/FTPS/SFTP 客户端。

FireBug – 在Firefox中调试JavaScript。

FireFTP – Firefox的FTP 客户端。

Fortres 101 – 桌面安全软件。

FSUM – 一个验证文件完整性的命令行工具。

FxCop – .NET 源码分析工具。

GetRight – 一个非常优秀的下载管理器。

Hamachi – 可以提供一个VPN 服务。设置起来非常简单,只需要10分钟,然后你就可以通过internet连入你的公司或家里了。

hMailServer - 免费的邮件服务器。

HTTP Analyzer – 实时监控,跟踪,调试,并分析 HTTP/HTTPS 的访问。

httpZip – 基于IIS 4, 5, 和6.0 的ISAPI。

IIS 6.0 Resource Kit Tools – 帮助你设置,保护和管理IIS。

IIsAdmin.NET – 创建多个IIS站点的定义。

Internet Explorer 7 Blocker – 阻止IE7 被安装。(奇怪的工具)

ImTOO MPEG Encoder – 视频格式转换。

InstallPad – 让你的程序运行地更快一些。

Instant C# - 把 VB.NET程序 转成C#程序

JavaRa – 删除好的没有用的Java版本。

Jaxe – 一个免费的 XML 编辑器,并支持 XPath 搜索。

JKDefrag – 一个很不错的磁盘碎片整理优化程序。

Junction Link Magic – 创建 junction points(比如我的文档,网上邻居这类的目录)

jZip – 创建,解压,压缩Zip, TAR, GZip 和7-Zip文件,只能解压 RAR 和ISO文件。

Launchy – 在你的开始菜单中创建文件,工程,目录和收藏夹等东西。

Leaf Networks – 创建你自己私有的网络。

LINQPad – 一个小工具可以和 SQL databases,,XML data 和object collections 交互。

MacDrive – 在Windows下挂载OS-X HFS/HFS+ 文件系统。

MagicISO – 一个强大的 CD/DVD 映像文件 创建/编辑/提取工具。

MBSA – 帮你校对并比对你系统目前的系统安全是否是微软推荐的。

Microsoft Log Parser – 可以读取基于文本的log files,XML 文件或CSV 文件,这些文件一般都是Windows操作系统中各种工具的日志文件,比如事件日志,注册表,性能监视器和活动目录。

Microsoft PowerShell 2 – Microsoft下一代的命令行shell

Microsoft RoboCopy – 强大的文件拷贝。

Microsoft SQL Server Database Publishing Wizard 1.1 – 把SQL  Sever数据库变成T-SQL 脚本。

Microsoft SUA for UNIX-based Applications – 和UNIX 互通的组件。

Mono/GTK#/Moonlight – Linux下的.NET, ASP.NET 和 Silverlight

Microsoft Virtual CD-ROM Control Panel – ISO 文件虚拟光驱。

Microsoft XML Notepad 2007 -  XML 文件编辑器。

MyGeneration – 代码生成器。

NAT32 IP Router – 一个外网内网IP转换程序。

NetShare Manager – 组织并控制不同网络的网络共享。

NetStumbler – 网络抓包程序,用于Wi-Fi 网络。

NetTools – 一个全面的主机监控,网络扫描,安全,管理工具。可能还更多。

NirTools – 一个Windows 工具集。

NOD32 – 号称是目前最好的防病毒软件。

NT Toolkit – 一系例小巧而实用为了网络管理而设计的工具。

NTP – Windows的网络时间服务程序。

Object Desktop – 让Windows看起来就是你想要的。

OpenVPN – 全功能的开源 SSL VPN 解决方案。支持远程访问, site-to-site VPNs, Wi-Fi 安全,和企业级的解决方案——比如负载平衡,权限策略等

Osiris Host Integrity Monitoring – 一个主机监控程序。其可以监控一台或多台主机是否发生了改变,其维护了一个非常细的日志来记录了文件系统,用户,内核模块的改变,以及更多的东西。

OSSIM – 全称是Open Source Security Information Management,一个提供了全面的工具,这些小工具在一起工作,可让你看到所有主机的网络/物理资源的使用情况。

Paint.NET – 一个免费的很简单的图片编辑器。

PowerGREP – Windows 下的grep 工具,不但支持文本文件,还支持,二进制文件,压缩文件,WORD文件,EXCEL电子表格,PDF文件等等。(关于grep,这是一个Unix下的扫描文件内容或标准输出,并找到匹配字符串的程序)

PowerLocker – 提供了一个快速简单的方式让你锁住你的PowerShell scripts

PureText – 任务栏小图标可以移除剪贴板里的文本格式。

PuTTY – 这个不用多说了,鼎鼎大名的免费的Telnet 和SSH客户端程序。

RegExBuddy – 一个容易创建正规表达式的工具。即简单,也复杂。

Regulator – 高级的正则表达式测试工具。并有语法高亮显示和web-service 集成以读取Regexlib.com的在线正则表达式。

ReSharper – 完全集成于Visual Studio,实时的错误高亮,代码提示,以及单元测试工具。一供有超过30 个高级的代码重构方案,多个代码导航和收搜工具,自动代码生成,和代码模板生成,以及其它更多的功能以配合C#, VB.NET, ASP.NET, XML, 和XAML使用。

Revo Uninstaller – 反安装,删除程序。以解决反安装中的问题。

RoboForm – 口令管理,网页表单填写。

SDC Tasks Library – 超过300 MSBuild 任务。

SOS – WinDbg 扩展,可以让WPF 和Silverlight 程序员使用。

System Information for Windows – 收集系统属性和配置的细节信息。并用一种极端的完整的方式显示出来。

SpywareBlaster – 阻止你的IE中了基于ActiveX的间谍软件,广告软件,以及流氓软件,或是其它你不想要的软件。

SmartSniff – TCP/IP 抓包程序。

SnagIt – 强大的抓屏程序。

subversion – 鼎鼎大名的代码版本控制软件。

SQL Digger – SQL存过,视图等关键字搜索工具。

SQLTac – 强大的协助你管理你的Domain Knowledge工具。

SQLTools – 免费的Oracle PL/SQL 编辑器。

SQLyog – 免费的MySQL 编辑器。

StyleCop – 分析C# 源代码,以保成代码风格的一致性。

SuperAntiSpyware – 最牛的反间谍软件扫描器。

SyncBackPro – 实时加密,版本备份和同步。

synergy2 – 让一个鼠标键盘共享给多个电脑使用。

SysInternals Suite Live – 一个超强的NETBIOS 版本的SysInternals Suite

Sysinternals Suite – 一级超强的高兴系统工具和技术信息。

SystemRescueCD – 可启动的 Linux CD 

Take Command – 最好的图形Shell。

TaskPower – 查看并分析进程的运行。

TeamCity – 惊艳的持续综合包。

TestDisk – 恢复丢失的分区。

ThreatFire – 实时的行为分析和间谍软件检测软件。

TreeSize Free – 告诉你为什么宝贵的磁盘空间到哪里去了。

Trillian – 多人网络聊天工具。

TrueCrypt – 免费的开源的磁盘加密软件,可用于Windows Vista/XP, Mac OS X, 和Linux

Tunnelier – SSH 和SFTP 客户端。

TweakUI – 可以修正一些惹人烦的关于Windows UI的小软件。

UltraEdit – Text, hex, HTML, PHP, Java, Javascript, Perl, 等等,一个强大的编辑器。

UltraMon – 多显示器工具。

Undelete Plus – 恢复被删除的文件。

Unlocker – 有些时候,一些文件被一些进程占着我们无法删除,这个程序就是把这些被锁住的文件解锁。

Unstoppable Copier – 恢复被物理损坏的硬盘上的文件。允许你从一些坏磁道上把文件备份下来。

uTorrent – BitTorrent 客户端。

Vista 64-bit Codecs – Windows Vista 64-bit下的音频和视频解码器。

VisualSVN – 为了Microsoft Visual Studio开发的专业的Subversion 集成程序

VirtuaWin – 虚拟桌面。

VLC Media Player – 免费的音频和视频播放器。

vLite – 一个可以定制Windows Vista 安装的小工具。

VMware Server – 在一台机器上运行多个操作系统。

Weblog Expert – 快速和强大的网站访问log 分析和报告。

WinDbg – 低层的Windows程序调试工具。

WinHTTrack – 网页拷贝。

Windows NT 4.0 Resource Kit – 老了但可能还是有用的Windows NT 4.0 工具

Windows 2000 Resource Kit – Windows 2000 工具集

Windows 2003 Resource Kit – Windows 2003 工具集

Windows 2003 Support Tools – Windows 2003 管理工具集

WinDirStat – 磁盘使用统计和清楚工具。

WinSSHD – SSH 服务程序。

WireShark – 强大的网络协义抓包分析器。

zFTPServer Suite – FTP 服务程序,以及强大的SSL 加密安全认证。



2010年12月13日

DataGridView的CellFormatting事件和CellPainting事件

1CellFormatting事件,一般重绘单元格属性。
    private Bitmap highPriImage;
    private Bitmap mediumPriImage;
    private Bitmap lowPriImage;
private void dataGridView1_CellFormatting(object sender,
        System.Windows.Forms.DataGridViewCellFormattingEventArgs e)
    {
        // Set the background to red for negative values in the Balance column.
        if (dataGridView1.Columns[e.ColumnIndex].Name.Equals("Balance"))
        {
            Int32 intValue;
            if (Int32.TryParse((String)e.Value, out intValue) &&
                (intValue < 0))
            {
                e.CellStyle.BackColor = Color.Red;
                e.CellStyle.SelectionBackColor = Color.DarkRed;
            }
        }

        // Replace string values in the Priority column with images.
        if (dataGridView1.Columns[e.ColumnIndex].Name.Equals("Priority"))
        {
            // Ensure that the value is a string.
            String stringValue = e.Value as string;
            if (stringValue == null) return;

            // Set the cell ToolTip to the text value.
            DataGridViewCell cell = dataGridView1[e.ColumnIndex, e.RowIndex];
            cell.ToolTipText = stringValue;

            // Replace the string value with the image value.
            switch (stringValue)
            {
                case "high":
                    e.Value = highPriImage;
                    break;
                case "medium":
                    e.Value = mediumPriImage;
                    break;
                case "low":
                    e.Value = lowPriImage;
                    break;
            }
        }
    }


2
CellPainting事件,一般用于合并单元格用
Windows Forms DataGridView
没有提供合并单元格的功能,要实现合并单元格的功能就要在CellPainting事件中使用Graphics.DrawLine Graphics.DrawString 自己来
下面的代码可以对DataGridView1列内容相同的单元格进行合并:
 #region"
合并单元格的测试"
private int? nextrow = null;
private int? nextcol = null;
private void dataGridView1_CellFormatting(object sender, System.Windows.Forms.DataGridViewCellFormattingEventArgs e)
{
    if (this.dataGridView1.Columns["description"].Index == e.ColumnIndex && e.RowIndex >= 0)
    {
        if (this.nextcol != null & e.ColumnIndex == this.nextcol)
        {
            e.CellStyle.BackColor = Color.LightBlue;
            this.nextcol = null;
        }
        if (this.nextrow != null & e.RowIndex == nextrow)
        {
            e.CellStyle.BackColor = Color.LightPink;
            this.nextrow = null;
        }
        if (e.RowIndex != this.dataGridView1.RowCount - 1)
        {
            if (e.Value.ToString() == this.dataGridView1.Rows[e.RowIndex + 1].Cells[e.ColumnIndex].Value.ToString())
            {
                e.CellStyle.BackColor = Color.LightPink;
                nextrow = e.RowIndex + 1;
            }
        }
    }
    if (this.dataGridView1.Columns["name"].Index == e.ColumnIndex && e.RowIndex >= 0)
    {
        if (e.Value.ToString() == this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex + 1].Value.ToString())
        {
            e.CellStyle.BackColor = Color.LightBlue;
            nextcol = e.ColumnIndex + 1;
        }
    }
}
//==========================
      
//
绘制单元格

private void dataGridView1_CellPainting(object sender, System.Windows.Forms.DataGridViewCellPaintingEventArgs e)
{
 
    //纵向合并
    if (this.dataGridView1.Columns["description"].Index == e.ColumnIndex && e.RowIndex >= 0)
    {
        using (
            Brush gridBrush = new SolidBrush(this.dataGridView1.GridColor),
            backColorBrush = new SolidBrush(e.CellStyle.BackColor))
        {
            using (Pen gridLinePen = new Pen(gridBrush))
            {
                //
擦除原单元格背景

                e.Graphics.FillRectangle(backColorBrush, e.CellBounds);
                ////
绘制线条,这些线条是单元格相互间隔的区分线条,
                ////
因为我们只对列name做处理,所以datagridview自己会处理左侧和上边缘的线条

                if (e.RowIndex != this.dataGridView1.RowCount - 1)
                {
                    if (e.Value.ToString() != this.dataGridView1.Rows[e.RowIndex + 1].Cells[e.ColumnIndex].Value.ToString())
                    {
                        e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1,
                        e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);//
下边缘的线

                        //
绘制值
                        if (e.Value != null)
                        {
                            e.Graphics.DrawString((String)e.Value, e.CellStyle.Font,
                                Brushes.Crimson, e.CellBounds.X + 2,
                                e.CellBounds.Y + 2, StringFormat.GenericDefault);
                        }
                    }
                }
                else
                {
                    e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1,
                        e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);//
下边缘的线
                    //
绘制值
                    if (e.Value != null)
                    {
                        e.Graphics.DrawString((String)e.Value, e.CellStyle.Font,
                            Brushes.Crimson, e.CellBounds.X + 2,
                            e.CellBounds.Y + 2, StringFormat.GenericDefault);
                    }
                }
                //
右侧的线
                e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1,
                    e.CellBounds.Top, e.CellBounds.Right - 1,
                    e.CellBounds.Bottom - 1);
                e.Handled = true;
            }
        }
    }
    //横向合并
    if (this.dataGridView1.Columns["name"].Index == e.ColumnIndex && e.RowIndex >= 0)
    {
        using (
            Brush gridBrush = new SolidBrush(this.dataGridView1.GridColor),
            backColorBrush = new SolidBrush(e.CellStyle.BackColor))
        {
            using (Pen gridLinePen = new Pen(gridBrush))
            {
                //
擦除原单元格背景

                e.Graphics.FillRectangle(backColorBrush, e.CellBounds);
                if (e.Value.ToString() != this.dataGridView1.Rows[e.RowIndex].Cells[e.ColumnIndex + 1].Value.ToString())
                {
                    //右侧的线
                    e.Graphics.DrawLine(gridLinePen, e.CellBounds.Right - 1, e.CellBounds.Top,
                        e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);
                    //
绘制值
                    if (e.Value != null)
                    {
                        e.Graphics.DrawString((String)e.Value, e.CellStyle.Font,
                            Brushes.Crimson, e.CellBounds.X + 2,
                            e.CellBounds.Y + 2, StringFormat.GenericDefault);
                    }
                }
                //下边缘的线
                e.Graphics.DrawLine(gridLinePen, e.CellBounds.Left, e.CellBounds.Bottom - 1,
                                            e.CellBounds.Right - 1, e.CellBounds.Bottom - 1);
                e.Handled = true;
            }
        }
    }
}
#endregion

2010年12月4日

页面内的配合与通信(usercontrol)

页面内的配合与通信

.NET的页面看似一个整体,却可能是由很多不同的区域组合而来的,常常用到的母版页、用户控件就是最鲜明的例子。
然而在一个页面内的元素要形成一个整体,就少不了控件之间的通信与传值,本文是个人在不断的使用过程中总结的一些东西,有谬误或有更好的解决方案,还请提出来。
在写这篇文章的过程中我做了一些一示例,以作佐证。这些示例的目的都是 在“A”中 把 “B”中 的一个Label的值改变。
这样的做法有什么意义?
比如说你在masterpage中含有一个GridView,在aspx改变了一些数据,而这些数据正是影响到masterpage中的GridView的呈现内容,那么你就有必要在aspx中通知masterpage更新了。本文的目的就是要说,如何去通知它的更新。
本文包括以下几个部分:
1、aspx与ascx的通信
2、master与aspx的之间的通信
3、master中的ascx 与 master中的aspx通信
4、ascx与ascx之间的通信

1、aspx与ascx的通信

一个简单的示例,在这个例子中,一共有两个文件:UserControl-Page.aspx和WebUserControl3.ascx,两个文件之中均含有一个TextBox、Label和一个Button
在这里,我们使用A和B来简称前者和后者。
要求的效果是:点击A中的Button,能将A中TextBox中的值赋给B中的Label;反之,点击B中的Butoon,要将B中TextBox中的值赋给A中的Label。
也就是说,它们两个能改变对方的控件内容。
首先说A->B
这是很简单的,在Ascx中写一个公共的方法,在aspx中调用就行了。
复制内容到剪贴板
代码:
//这是在ascx中的方法,该方法将参数_value的值赋给Label。
    public void setSelect(string _value)
    {
        lblMessage.Text = _value;
    }
在aspx中直接调用它
复制内容到剪贴板
代码:
    protected void btnSet_Click(object sender, EventArgs e)
    {
        WebUserControl3_1.setSelect(txtValue.Text);// WebUserControl3_1是用户控件的ID
    }
可能大家看得不是很明白,不过总之,在aspx中可以调用ascx中的公共方法,传入想传的参数,就OK了。

如果倒过来,由B->A。

在ascx中改变aspx中的一个Label,也只换种方式
复制内容到剪贴板
代码:
    Label lblMessage= (Label)Page.FindControl("lblMessage");
    lblMessage.Text = txtValue.Text;
也就是说,可以在ascx中查找当前aspx页的控件ID,找到了,直接赋个值就行了。反正,只要找到这个控件,用起来就好像自己的一样。

2、master与aspx的通信

在master中访问aspx中的东西也是查找控件,和ascx中查找aspx中差不多
复制内容到剪贴板
代码:
    Label lblMessage= (Label)ContentPlaceHolder1.FindControl("lblMessage");
    lblMessage.Text = txtValue.Text;
倒过来,aspx可以调用masterpage的公共方法
复制内容到剪贴板
代码:
    MasterPage master = (MasterPage)Page.Master;//转换为masterpage的类型
    master.setValue(txtValue.Text);//调用masterpage的方法
3、master中的ascx 与 master中的aspx通信

从master中的ascx到master中的aspx,需要通过master,查找ContentPlaceHolder,再查找Label
复制内容到剪贴板
代码:
    MasterPage master = (MasterPage)Page.Master;
    Label _lblMessage = (Label)master.FindControl("ContentPlaceHolder1").FindControl("lblMessage");
    _lblMessage.Text = txtValue.Text;
aspx要想与masterpage的ascx联系,要先得到master,再查找ascx,再查找Label。
复制内容到剪贴板
代码:
    MasterPage master = (MasterPage)Page.Master;
    Label lblMessage=(Label)master.FindControl("WebUserControl4_1").FindControl("lblMessage");
    lblMessage.Text = txtValue.Text;
这个双方互通是一样的原理哦。

4、ascx与ascx之间的通信

这应该是最常见的情况,前段时间做的项目,分两个区域,用户在A区域从事活动,B区域记录下他活动的信息,这两个区域都是用户控件。
一种方法是从a.ascx中查找Aspx,再查找B.ascx,再查找Label。
这种方向理论上的行得通的,不过我没试,因为这种方法必须考虑B控件在A中的ID,我却不想与ID发生任何关系。
所以我用接口。
假设现有WebUserControl2.ascx想操纵WebUserControl1.ascx中的控件。
在app_code中新建一个IUserControl1.cs
内容:
复制内容到剪贴板
代码:
public interface IUserControl1
{
    void setSelect(string value);
}
在WebUserControl1.ascx继承该接口,并实现其方法。
复制内容到剪贴板
代码:
public partial class UserControl_WebUserControl1 : System.Web.UI.UserControl, IUserControl1
{
    public void setSelect(string _value)
    {
        lblMessage.Text = _value;
    }
}
然后直接在webUserControl2.ascx调用webUserControl1.ascx中的方法
复制内容到剪贴板
代码:
    IUserControl1 userControl1 = (IUserControl1)Page.FindControl("WebUserControl1_1");//转化到接口去
    userControl1.setSelect(txtValue.Text);//setSelect是webUserControl1.ascx中的方法,调用它。
这实际上是很好的一种方法,这样来做,其它类型的控件间通信应该都能实现,在那几天,我还一直沾沾自喜着呢。通过这一样一个例子,也发现接口确实不简单,真的是一个“接口”。

.net的partial类的引入使用我的可以在各个文件中实现一个,最后合并在一起,而通过这些小技巧,又可以把各部分联系起来,成为一个真正的“整体”。

用委托提取用户控件中的值

用委托提取用户控件中的值

由于用户控件生成,如page_load .总是在调用用户控件的页面之后.在调用该用户控件的页面上要调用用户控件上的新值时,总是慢一拍,(刷新就不会).
用委托可以解决这样的问题.
UserControl.ascx.cs中的处理:
1. 定义public的事件委托,如SelectedChangedEventHandler;
2. 在UserControl类中声明事件,如SelectedChanged;
3. 在UserControl类中定义引发事件的方法,如OnSelectedChanged()方法;
4. 在UserControl类的相关方法中调用引发事件的方法,
如在DropDownList1_SelectedIndexChanged中调用OnSelectedChanged()。
核心代码示意如下:

public class MyUserControl : System.Web.UI.UserControl
{
protected System.Web.UI.WebControls.DropDownList DropDownList1;
public delegate void SelectedChangedEventHandler(object sender, EventArgs e);
public event SelectedChangedEventHandler SelectedChanged;
protected void OnSelectedChanged(EventArgs e)
{
if (SelectedChanged!=null)
SelectedChanged(this, e);
}
private void DropDownList1_SelectedIndexChanged(object sender, System.EventArgs e)
{
this.OnSelectedChanged(e);
}
}
包含UserControl的页面cs文件中的处理:
1. InitializeComponent()中增加事件处理程序,采用FindControl方法找到UserControl;
2. 定义事件处理方法,在该方法中处理UserControl的事件,如UserControl_SelectedChanged()。
核心代码示意如下:
private void InitializeComponent()
{
this.Load += new System.EventHandler(this.Page_Load);
MyUserControl uc = this.FindControl("myUserControlID") as MyUserControl;
uc.SelectedChanged+= new SelectedChangedEventHandler(this.UserControl_SelectedChanged);
}
private void UserControl_SelectedChanged(object sender, System.EventArgs e)
{
// UserControl_SelectedChanged event hanlder
}

也可以直接对用户控件查找:
1.先定义ASPX页面上调用的用户控件的id
2.用FindControl方法找到用户控件中的控件id.
如下:
protected UserControl UserControl1;//UserControl1就是用户控件在ASPX页面上的id

((DropDownList)UserControl1.FindControl(" DropDownList1")).SelectedValue;

2010年12月2日

再谈软件保护中软加密和硬加密的安全强度

在软件保护技术中一般存在两种主要的保护方式:不需要额外的硬件设备,完全由软件实现的方式和使用硬件加密锁的方式。往往前者被称作“软加密”方式;而后者被称作“硬加密”方式。普遍认为,硬加密方式的安全强度要大于软加密方式。

  但真的是这样吗?

  一 软件解密方法

  如同软件加密的方式千差万别,软件解密的办法也多种多样。但从根本上,无外乎三种主要手段:

  1. 逆向工程

  采用软件代码分析和跟踪的方法,找到软件中调用加密验证或判断验证结果的代码,并进行修改或替换,以绕过保护。

  2. 通讯欺骗

  在软件代码调用验证机制的通道上对通讯指令截取和分析,并通过修改或回放的方法欺骗软件,使之产生错误的判断。

  3. 指纹复制

  对软件进行加密认定的硬件信息或硬件本身进行复制。

  其中逆向工程的破解方法与底层采用何种加密机制的关系不大,破解难度主要由软件代码的复杂程度以及核心安全库的防护机制决定。下面主要分析通讯欺骗和指纹复制的破解方法对软加密和硬加密的难易程度。

  通讯欺骗

  通讯欺骗往往通过监视、修改及复制系统功能调用的结果来实现。它需要破解者有能力在不影响软件正常运行的情况下截获及修改与软件保护相关的系统调用。要能正常实现通讯欺骗,必须要满足以下几个条件:

  1. 有能力找到所有与软件保护相关的系统调用。

  这对硬加密非常容易——所有对加密锁硬件的IO操作;但对软加密则不太容易,任何系统调用,包括文件、注册表、系统信息、时间的调用都可能与软件保护操作相关。

  2. 能够分析了解系统调用的输入、输出参数所代表的意义,能够伪造返回结果。

  3. 能够在不影响系统及应用程序正常工作的条件下修改返回结果。

  设计精良的硬加密产品可以在软件代码和硬件加密锁之间构建所谓的“安全通道”,使得破解者虽然能够截获通讯命令,却无法分析得到其中的原始数据,也无法伪造通讯命令,从而基本无法进行通讯欺骗。

  对于软加密来说,破解者总是可以得到系统调用命令的原始数据,但要想在不影响系统以及应用程序功能的情况下修改系统调用结果则并不容易。一方面,破解者必须能够了解哪些系统调用与软件保护机制有关;另一方面,系统调用的结果并不总是容易截获——很多获取硬件指纹的命令基于系统中断调用;最后,修改系统调用结果在很多情况下将会影响系统和软件的运行,使得破解过程无法正常进行。

  从理论上来说,除非破解者能够营造一个有能力任意监视并改写所有系统调用结果的独立环境,否则将无法完全实现通讯欺骗,而这样做的工作要比逆向工程还要复杂,从而导致对软加密采用通讯欺骗的破解方法失去意义。

  从本质上来说,软加密基于系统功能调用,而硬加密基于对硬件本身功能的调用。因此软加密实现与系统本身的结合程度要比硬加密高得多。

  指纹复制

  软加密的安全指纹由所运行的软、硬件环境获取;而硬加密的指纹就是加密锁本身。与普遍的认知相反,对计算机运行环境指纹的复制要比想象中困难得多,而对加密锁硬件的复制则要比想象中的更容易也更危险。

  为什么计算机运行环境不容易复制:

  1. 有一些计算机硬件设备包含了唯一的ID,比如说CPU或者某些型号的硬盘,这些唯一ID是不可复制的。

  2. 包括硬盘分区序列号或网卡MID等都具有很好的唯一性。

  3. IP地址具有很好的唯一性,而伪造会导致系统网络通讯异常。

  4. 在局域网内部,机器名、用户名及内网IP地址都是很好的唯一特征。

  5. 根据操作系统及硬盘文件可以产生非常好的唯一特征。

  6. 最重要的是,要复制所有上述这些硬件和软件特征,其投入的成本不低。因此不具备大规模复制的可行性。

  关于硬件加密锁的复制:

  1. 主要的加密锁芯片都可以通过硬件剖片的方法读出内容,从而进行复制,包括智能卡芯片。这个过程的成本比通常想象的要低,因为破解者往往会租用专业设备而不需要自己购买。

  2. 破解者总是可以买到厂家的加密锁,并进行分析和改造。

  3. 破解者可能会通过加密锁的代理或开发商内部相关人员得到加密锁内部的算法相关数据,从而在无需硬件分析的情况下复制加密锁。

  4. 需要注意的是,加密锁复制的前期成本较高,但一旦形成复制能力,后期的平均复制成本则很低。

  结论

  精心设计的软加密实现方案可以在通讯欺骗和指纹复制的破解环节上提供足够高的安全性,使破解者转向通过逆向工程的方法破解软件。在这种情况下,软件的防分析及跟踪能力以及代码内部的加密技巧成为了安全系统的核心,底层基于硬加密还是软加密将不再影响系统的实际安全性。

  二 软加密的新技术及四大优势

  通过利用网络通讯和服务器认证,软加密方式在实际应用中可以获得比上述分析好得多的安全应用效果。

  所谓服务器认证,是指软件安全系统首次运行的时候在服务器端“备案”,存储客户端硬件特征,并获取开发商授权的过程。除了首次运行的激活过程外,服务器认证还可以在今后再次进行,以核查及升级授权内容。

  由北京比特安索公司开发的比特平台除了支持服务器认证技术,还提供了将授权运行于服务器系统之上的“云授权”保护方案。云授权采用客户端与服务器实时连接的验证方案,安全系统指纹始终依附在服务器上,因此具有更高的安全性。它与传统的软加密具有明显的区别,因此不在这里进行分析。

  集成了服务器认证的软加密方案具有硬加密不具备的四大优势。

  双因素验证

  无论是传统的硬加密还是软加密,安全验证都是单因素的,即基于加密锁或本机硬件指纹。集成了服务器认证之后,加密方案本身是双因素的:既与本机硬件指纹相关,又与服务器相关。

  双因素验证大大加强了系统整体的安全性,破解者无法通过破解其中的一个因素实现完整的盗版。它使新一代的软加密技术的安全性实质上超过传统硬加密成为现实。

  破解追踪

  世上没有绝对可靠的保护技术,而运行于客户环境的软件代码总是可以被跟踪和分析。与硬加密不同的是,实现双因素验证的软加密方案中很容易实现对破解应用的追踪。

  除非通过逆向工程的办法把所有与服务器通讯相关的代码完全替换——这个工作比软件破解本身的难度还要大——否则服务器将有可能对软件的破解拷贝进行追踪。以比特平台为例,通过设置授权模版的“强制认证”或“智能连接”属性,客户端软件将定期或不定期地尝试与服务器进行连接验证,服务器因此可以发现是否有授权盗用的情况,并且可以根据相应的授权码找到盗用源头,解后进行封锁。

  也就是说,新一代的软加密技术本身通过服务器验证的机制,不再是单纯的本地安全技术。它是包含了本地安全与网络安全的综合性系统架构。

  补救措施

  软加密的一个明显优势是可以方便地推出对破解版本的补救措施。

  当基于硬加密的应用程序被破解后,一般来说,为保证升级后的应用程序与旧版本程序使用的加密锁不兼容,软件开发商在应用升级的时候必须同时升级应用程序代码并提供新的加密锁。这样的升级措施需要很大的成本,开发商实际上往往无法实施。

  而软加密的补救措施是零成本的。

  同样以比特平台为例,当开发商发现现有版本被破解后,可以在平台上为现有产品添加新的特征项(即功能模块),或升级已有的功能算法;开发商相应地升级应用程序代码,制作升级补丁,并发送给合法用户。

  合法用户拿到升级补丁并升级应用程序后,应用软件可以自动连接到授权服务器进行算法更新并升级本地授权文件,从而完成升级。而盗版用户因为无法通过服务器验证而不能应用升级内容。破解者也必须再次实施破解才能使用新的功能。

  破解风险

  前面提到了,软加密与系统和使用环境的结合程度要比硬加密高得多。对于硬加密的破解版本使用者,除了软件本身可能会因破解不充分而存在问题外,使用者不存在任何其它使用风险,盗版使用的成本很低。

  对于软加密,盗版使用者往往需要为使用软件而更改系统设置,如网卡MIC地址或系统时间,而这些都会对整个系统及其它应用程序造成影响,从而提高盗版使用难度,增加使用成本。这些系统设置和负面影响使得盗版使用不可能大规模推广。

  三 效果为王

  使用软件保护技术或产品的目标是以最小的成本达成最佳的防盗版效果,其本身是一个系统性的工作,软件的整体安全性受系统中最薄弱部分的制约,并与实施难度、应用风险、危害程度等密切相关。

  新一代软加密技术以服务器验证为基础,其整体安全性已超出包括传统硬加密在内的单纯的本地安全技术,并显著降低了盗版使用的扩散范围,具有更好的实际安全效果。

  此外,软加密特有的无物流、易管理以及授权方案灵活等众多特点,使得它成为互联网时代的最佳软件保护方案。