Archive for 01月, 2005
用过最流行的Opera和Firefox浏览器后,发现在众多扩展中也无法DIY出我理想中的浏览器。一款优秀网络浏览器最重要的特征是什么呢?速度、舒适性、安全、稳定性、网页兼容性,扩展性等。
即使是IE最新的版本,产生网页的速度,比其他的浏览器都来的慢,尤其是碰到有大量蜂巢式表格的网页。Opera则是这场比赛的冠军,Firefox则位
居第二。当然安全、稳定性、扩展性Firefox是最好的,兼容性也在提高中(模拟IE的方式浏览Only
IE网页研究中)。那么如何得到最快的浏览速度呢,只有在本地计算机中打开网页才是最快的方法。
加速原理:
采用预读链接技术,即每次浏览网页时,会在该网页中找出所有的链接。当您阅读网页且调制解调器处于闲置状态时,它会以后台方式将链接加载到浏览器缓冲区中。如果您随后单击任一链接,浏览器将不必到因特网来获取其内容,这样可以提高网页的显示速度。
1、扩展名:只预读或排除自定义的扩展名的文件(如:mp3,rm,GIF,SWF)。
2、智能化:会跟踪您访问的网页,并判断哪些是您经常访问的网站。它会利用闲置时间刷新您最喜爱的网站。
3、同步收藏夹:会检查您的浏览器收藏夹,并使链接的内容总是保持最新状态。
4、词典:对有敏感词语(如:足球、胡卫东、Csharp)的链接预读,用户能发布个人专业词典到网络中和其他用户共享。
目前,发现不少开发者陷入一个怪圈,即过度且不厌其烦的制作的皮肤。可是却忽略了真正能抓住用户使用你的浏览器的东西根本不是浏览器的皮肤,而是给用户提供最佳的页面浏览体验。
提高舒适度:
1、侧栏:标签管理栏(快照)
打开N多标签后往往会找不到想要的标签页,我们不妨给每个页面来个快照,然后集中在左侧显示快照,可以按网页加载完成度、打开时间…等排序。鼠标移动到快照上时会自动放大,单击后就能快速定位到相关标签,这样不就更便于用户管理吗?
2、局部亮度色彩控制
例如打开西祠主页后,感觉页面白色的部分特多,浏览时很不舒服。在网站没有提供多余的样式表的情况下,通常只能通过调节显示器亮度来降低对眼部的刺激。但
这又影响到正常阅读网页了例如网页中视频和图片的显示效果太差。如果浏览器有个颜色拾取器,可以捕获到页面颜色后替换成其它深颜色,那么就不会影响正常的
浏览。
3、真正的满屏浏览
按F11后,标题栏、菜单栏、工具条、状态栏、地址栏、标签栏甚至滚动条全部是多余的,全部Kill掉,即整个浏览器除了网页外什么都不显示。想要地址栏什么的直接用快捷键调出来。用完后立即自动隐藏。
强烈希望梦想能在FireFox中成为现实。感谢各位看本人劣作,初赶,不足处请包含。
zhujunzji1@sjina.com
2005-1-31
昨天,我开网吧的朋友给我打电话,说这几天他天天都有人QQ,和传奇号等被人狂盗,开始我很奇怪,他用的是卡吧,正版木马客星,正版天网还有还原卡.
我说你杀毒了吗,他说:我XXX的,我把电脑都杀了N遍了什么也没有,我当时也很奇怪.因为现在的QQ盗号软件都被卡吧通吃,冰河2005,和灰鸽子2005都会被杀.
后来用cca.exe找到了个克隆账号,才知道他变成肉鸡.在注册表里看到个很熟悉的键值,想了好久才想起来是RANMIN的服务端
Remote Administrator
(Radmin)是最快的远程控制软件。它为低带宽的连接(如通过Modem)进行了专门的优化。通过Modem连接时,屏幕刷新次数可以达到每秒5-
10次。如果通过局域网连接,速度可以达到每秒100次,使你如同在本地一样进行实时操作。而对于经常进行远程维护工作的IT人员来讲,操作的方便性与速
度是最重要的。因此,这一软件是最适合于进行系统维护以及专业的桌面技术支持(HelpDesk)的产品.
因为RADMIN的编码和传统的冰河等不一样所以不会被杀,因为它是一种真正的远程控制软件.
现在学校和很多地方都放假了,也就是说很多莱鸟级别的黑客也开始他们的行动了,他们没有太多的技术含量,但是现在的黑客软件功能都很强大,使用起来也很方便,使得一些莱鸟也有着很强的杀伤力.
他们一般是先用4899弱口令扫描器去扫NT的弱口令,扫一会就会扫到N个,再用RADMIN连上去,因为RADMIN的默认端口是4899.开个克隆账号.怎么开克隆账号我就不说了,这样一个肉鸡就产生了.
还有一种也是他们乐此不疲的就是用WIN/2000自动攻击机去扫SQL,因为大部分的人SQL用户密码、都是默认的用户名是:sa密码为空,直接用SQLTools连上去,这也是很多人再用,但也是成功率最高的一种了.
上面说的这些只是莱鸟级别的黑客才会做的,真正的黑客是不会去入侵个人电脑的,大家请放心这一点.但是上面的几种方法已经可以让很多人变成肉鸡了.
没写完````不好意识,我要出去了,回来再接着吹牛X`````哈哈
Windows启动时通常会有一大堆程序自动启动。不要以为管好了“开始→程序→启动”菜单就万事大吉,实际上,在Windows XP/2K中,让Windows自动启动程序的办法很多,下文告诉你最重要的两个文件夹和八个注册键。
一、当前用户专有的启动文件夹
这是许多应用软件自动启动的常用位置,Windows自动启动放入该文件夹的所有快捷方式。用户启动文件夹一般在:\Documents
and Settings\<用户名字>\“开始”菜单\程序\启动,其中“<用户名字>”是当前登录的用户帐户名称。
二、对所有用户有效的启动文件夹
这是寻找自动启动程序的第二个重要位置,不管用户用什么身份登录系统,放入该文件夹的快捷方式总是自动启动——这是它与用户专有的启动文件夹
的区别所在。该文件夹一般在:\Documents and Settings\All Users\“开始”菜单\程序\启动。
三、Load注册键
介绍该注册键的资料不多,实际上它也能够自动启动程序。位置:HKEY_CURRENT_USER\Software\Microsoft\WindowsNT\CurrentVersion\Windows\load。
四、Userinit注册键
位置:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsNT\CurrentVersion\
Winlogon\Userinit。这里也能够使系统启动时自动初始化程序。通常该注册键下面有一个userinit.exe,如图一,但这个键允许指
定用逗号分隔的多个程序,例如“userinit.exe,OSA.exe”(不含引号)。
五、Explorer\Run注册键
和load、Userinit不同,Explorer\Run键在HKEY_CURRENT_USER和
HKEY_LOCAL_MACHINE下都有,具体位置是:HKEY_CURRENT_USER\Software\Microsoft\Windows
\CurrentVersion\Policies\Explorer\Run,和HKEY_LOCAL_MACHINE\SOFTWARE\
Microsoft\Windows\CurrentVersion\Policies\Explorer\Run。
六、RunServicesOnce注册键
RunServicesOnce注册键用来启动服务程序,启动时间在用户登录之前,而且先于其他通过注册键启动的程序。
RunServicesOnce注册键的位置是:HKEY_CURRENT_USER\Software\Microsoft\Windows\
CurrentVersion\RunServicesOnce,和HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
Windows\CurrentVersion\RunServicesOnce。
七、RunServices注册键
RunServices注册键指定的程序紧接RunServicesOnce指定的程序之后运行,但两者都在用户登录之前。
RunServices的位置是:HKEY_CURRENT_USER\Software\Microsoft\Windows\
CurrentVersion\RunServices,和HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
Windows\CurrentVersion\RunServices。
八、RunOnce\Setup注册键
RunOnce\Setup指定了用户登录之后运行的程序,它的位置是:HKEY_CURRENT_USER\Software\
Microsoft\Windows\CurrentVersion\RunOnce\Setup,和HKEY_LOCAL_MACHINE\
SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce\Setup。
九、RunOnce注册键
安装程序通常用RunOnce键自动运行程序,它的位置在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\
Windows\CurrentVersion\RunOnce和HKEY_CURRENT_USER\Software\Microsoft\
Windows\CurrentVersion\RunOnce。HKEY_LOCAL_MACHINE下面的RunOnce键会在用户登录之后立即运行
程序,运行时机在其他Run键指定的程序之前。HKEY_CURRENT_USER下面的RunOnce键在操作系统处理其他Run键以及“启动”文件夹
的内容之后运行。如果是XP,你还需要检查一下HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\
CurrentVersion\RunOnceEx。
十、Run注册键
Run是自动运行程序最常用的注册键,位置在:HKEY_CURRENT_USER\Software\Microsoft\Windows
\CurrentVersion\Run,和HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\
CurrentVersion\Run。HKEY_CURRENT_USER下面的Run键紧接HKEY_LOCAL_MACHINE下面的Run键运
行,但两者都在处理“启动”文件夹之前。
Microsoft.Net
Framework为应用程序访问Internet提供了分层的、可扩展的以及受管辖的网络服务,其名字空间System.Net和
System.Net.Sockets包含丰富的类可以开发多种网络应用程序。.Net类采用的分层结构允许应用程序在不同的控制级别上访问网络,开发人
员可以根据需要选择针对不同的级别编制程序,这些级别几乎囊括了Internet的所有需要–从socket套接字到普通的请求/响应,更重要的是,这
种分层是可以扩展的,能够适应Internet不断扩展的需要。
抛开ISO/OSI模型的7层构架,单从TCP/IP模型上的逻辑层面上看,.Net类可以视为包含3个层次:请求/响应层、应用协议
层、传输层。WebReqeust和WebResponse
代表了请求/响应层,支持Http、Tcp和Udp的类组成了应用协议层,而Socket类处于传输层。可以如下示意:

可见,传输层位于这个结构的最底层,当其上面的应用协议层和请求/响应层不能满足应用程序的特殊需要时,就需要使用这一层进行Socket套接字编程。
而在.Net中,System.Net.Sockets 命名空间为需要严密控制网络访问的开发人员提供了 Windows
Sockets (Winsock) 接口的托管实现。System.Net
命名空间中的所有其他网络访问类都建立在该套接字Socket实现之上,如TCPClient、TCPListener 和 UDPClient
类封装有关创建到 Internet 的 TCP 和 UDP
连接的详细信息;NetworkStream类则提供用于网络访问的基础数据流等,常见的许多Internet服务都可以见到Socket的踪影,如
Telnet、Http、Email、Echo等,这些服务尽管通讯协议Protocol的定义不同,但是其基础的传输都是采用的Socket。
其实,Socket可以象流Stream一样被视为一个数据通道,这个通道架设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。

可见,在应用程序端或者服务器端创建了Socket对象之后,就可以使用Send/SentTo方法将数据发送到连接的Socket,或者使用Receive/ReceiveFrom方法接收来自连接Socket的数据;
针对Socket编程,.NET 框架的 Socket 类是 Winsock32 API
提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法,大多数情况下,Socket 类方法只是将数据封送到它们的本机 Win32
副本中并处理任何必要的安全检查。如果你熟悉Winsock
API函数,那么用Socket类编写网络程序会非常容易,当然,如果你不曾接触过,也不会太困难,跟随下面的解说,你会发觉使用Socket类开发
windows 网络应用程序原来有规可寻,它们在大多数情况下遵循大致相同的步骤。
在使用之前,你需要首先创建Socket对象的实例,这可以通过Socket类的构造方法来实现:
|
public Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType); |
其中,addressFamily 参数指定 Socket 使用的寻址方案,socketType 参数指定 Socket 的类型,protocolType 参数指定 Socket 使用的协议。
下面的示例语句创建一个 Socket,它可用于在基于 TCP/IP 的网络(如 Internet)上通讯。
|
Socket s = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp); |
若要使用 UDP 而不是 TCP,需要更改协议类型,如下面的示例所示:
|
Socket s = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram, ProtocolType.Udp); |
一旦创建 Socket,在客户端,你将可
以通过Connect方法连接到指定的服务器,并通过Send/SendTo方法向远程服务器发送数据,而后可以通过
Receive/ReceiveFrom从服务端接收数据;而在服务器端,你需要使用Bind方法绑定所指定的接口使Socket与一个本地终结点相联,
并通过Listen方法侦听该接口上的请求,当侦听到用户端的连接时,调用Accept完成连接的操作,创建新的Socket以处理传入的连接请求。使用
完 Socket 后,记住使用 Shutdown 方法禁用 Socket,并使用 Close 方法关闭 Socket。其间用到的方法/函数有:
|
Socket.Connect方法:建立到远程设备的连接
public void Connect(EndPoint remoteEP)(有重载方法)
Socket.Send 方法:从数据中的指示位置开始将数据发送到连接的 Socket。
public int Send(byte[], int, SocketFlags);(有重载方法)
Socket.SendTo 方法 将数据发送到特定终结点。
public int SendTo(byte[], EndPoint);(有重载方法)
Socket.Receive方法:将数据从连接的 Socket 接收到接收缓冲区的特定位置。
public int Receive(byte[],int,SocketFlags);
Socket.ReceiveFrom方法:接收数据缓冲区中特定位置的数据并存储终结点。
public int ReceiveFrom(byte[], int, SocketFlags, ref EndPoint);
Socket.Bind 方法:使 Socket 与一个本地终结点相关联:
public void Bind( EndPoint localEP );
Socket.Listen方法:将 Socket 置于侦听状态。
public void Listen( int backlog );
Socket.Accept方法:创建新的 Socket 以处理传入的连接请求。
public Socket Accept();
Socket.Shutdown方法:禁用某 Socket 上的发送和接收
public void Shutdown( SocketShutdown how );
Socket.Close方法:强制 Socket 连接关闭
public void Close(); |
可以看出,以上许多方法包含EndPoint类型的参数,在Internet中,TCP/IP
使用一个网络地址和一个服务端口号来唯一标识设备。网络地址标识网络上的特定设备;端口号标识要连接到的该设备上的特定服务。网络地址和服务端口的组合称
为终结点,在 .NET 框架中正是由 EndPoint
类表示这个终结点,它提供表示网络资源或服务的抽象,用以标志网络地址等信息。.Net同时也为每个受支持的地址族定义了 EndPoint
的子代;对于 IP 地址族,该类为 IPEndPoint。IPEndPoint
类包含应用程序连接到主机上的服务所需的主机和端口信息,通过组合服务的主机IP地址和端口号,IPEndPoint 类形成到服务的连接点。
用到IPEndPoint类的时候就不可避免地涉及到计算机IP地址,.Net中有两种类可以得到IP地址实例:
IPAddress类:IPAddress 类包含计算机在 IP 网络上的地址。其Parse方法可将 IP 地址字符串转换为 IPAddress 实例。下面的语句创建一个 IPAddress 实例:
|
IPAddress myIP = IPAddress.Parse(“192.168.1.2″); |
Dns 类:向使用 TCP/IP
Internet 服务的应用程序提供域名服务。其Resolve 方法查询 DNS
服务器以将用户友好的域名(如”host.contoso.com”)映射到数字形式的 Internet 地址(如
192.168.1.1)。Resolve方法 返回一个 IPHostEnty
实例,该实例包含所请求名称的地址和别名的列表。大多数情况下,可以使用 AddressList 数组中返回的第一个地址。下面的代码获取一个
IPAddress 实例,该实例包含服务器 host.contoso.com 的 IP 地址。
|
IPHostEntry ipHostInfo = Dns.Resolve(“host.contoso.com”);
IPAddress ipAddress = ipHostInfo.AddressList[0];
|
你也可以使用GetHostName方法得到IPHostEntry实例:
|
IPHosntEntry hostInfo=Dns.GetHostByName(“host.contoso.com”) |
在使用以上方法时,你将可能需要处理以下几种异常:
SocketException异常:访问Socket时操作系统发生错误引发
ArgumentNullException异常:参数为空引用引发
ObjectDisposedException异常:Socket已经关闭引发
在掌握上面得知识后,下面的代码将该服务器主机( host.contoso.com的 IP 地址与端口号组合,以便为连接创建远程终结点:
|
IPEndPoint ipe = new IPEndPoint(ipAddress,11000); |
确定了远程设备的地址并选择了用于连接的端口后,应用程序可以尝试建立与远程设备的连接。下面的示例使用现有的 IPEndPoint 实例与远程设备连接,并捕获可能引发的异常:
|
try {
s.Connect(ipe);//尝试连接
}
//处理参数为空引用异常
catch(ArgumentNullException ae) {
Console.WriteLine(“ArgumentNullException : {0}”, ae.ToString());
}
//处理操作系统异常
catch(SocketException se) {
Console.WriteLine(“SocketException : {0}”, se.ToString());
}
catch(Exception e) {
Console.WriteLine(“Unexpected exception : {0}”, e.ToString());
} |
需要知道的是:Socket 类支持两种基本模式:同步和异步。其区别在于:在同步模式中,对执行网络操作的函数(如 Send 和 Receive)的调用一直等到操作完成后才将控制返回给调用程序。在异步模式中,这些调用立即返回。
另外,很多时候,Socket编程视情况不同需要在客户端和服务器端分别予以实现,在客户端编制应用程序向服务端指定端口发送请求,同时
编制服务端应用程序处理该请求,这个过程在上面的阐述中已经提及;当然,并非所有的Socket编程都需要你严格编写这两端程序;视应用情况不同,你可以
在客户端构造出请求字符串,服务器相应端口捕获这个请求,交由其公用服务程序进行处理。以下事例语句中的字符串就向远程主机提出页面请求:
|
string Get = “GET / HTTP/1.1\r\nHost: ” + server + “\r\nConnection: Close\r\n\r\n”; |
远程主机指定端口接受到这一请求后,就可利用其公用服务程序进行处理而不需要另行编制服务器端应用程序。
综合运用以上阐述的使用Visual
C#进行Socket网络程序开发的知识,下面的程序段完整地实现了Web页面下载功能。用户只需在窗体上输入远程主机名(Dns
主机名或以点分隔的四部分表示法格式的 IP
地址)和预保存的本地文件名,并利用专门提供Http服务的80端口,就可以获取远程主机页面并保存在本地机指定文件中。如果保存格式是.htm格式,你
就可以在Internet浏览器中打开该页面。适当添加代码,你甚至可以实现一个简单的浏览器程序。

实现此功能的主要源代码如下:
|
//”开始”按钮事件
private void button1_Click(object sender, System.EventArgs e) {
//取得预保存的文件名
string fileName=textBox3.Text.Trim();
//远程主机
string hostName=textBox1.Text.Trim();
//端口
int port=Int32.Parse(textBox2.Text.Trim());
//得到主机信息
IPHostEntry ipInfo=Dns.GetHostByName(hostName);
//取得IPAddress[]
IPAddress[] ipAddr=ipInfo.AddressList;
//得到ip
IPAddress ip=ipAddr[0];
//组合出远程终结点
IPEndPoint hostEP=new IPEndPoint(ip,port);
//创建Socket 实例
Socket socket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
try
{
//尝试连接
socket.Connect(hostEP);
}
catch(Exception se)
{
MessageBox.Show(“连接错误”+se.Message,”提示信息
,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
}
//发送给远程主机的请求内容串
string sendStr=”GET / HTTP/1.1\r\nHost: “ + hostName +
“\r\nConnection: Close\r\n\r\n”;
//创建bytes字节数组以转换发送串
byte[] bytesSendStr=new byte[1024];
//将发送内容字符串转换成字节byte数组
bytesSendStr=Encoding.ASCII.GetBytes(sendStr);
try
{
//向主机发送请求
socket.Send(bytesSendStr,bytesSendStr.Length,0);
}
catch(Exception ce)
{
MessageBox.Show(“发送错误:”+ce.Message,”提示信息
,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
}
//声明接收返回内容的字符串
string recvStr=”";
//声明字节数组,一次接收数据的长度为1024字节
byte[] recvBytes=new byte[1024];
//返回实际接收内容的字节数
int bytes=0;
//循环读取,直到接收完所有数据
while(true)
{
bytes=socket.Receive(recvBytes,recvBytes.Length,0);
//读取完成后退出循环
if(bytes<=0)
break;
//将读取的字节数转换为字符串
recvStr+=Encoding.ASCII.GetString(recvBytes,0,bytes);
}
//将所读取的字符串转换为字节数组
byte[] content=Encoding.ASCII.GetBytes(recvStr);
try
{
//创建文件流对象实例
FileStream fs=new FileStream(fileName,FileMode.OpenOrCreate,FileAccess.ReadWrite);
//写入文件
fs.Write(content,0,content.Length);
}
catch(Exception fe)
{
MessageBox.Show(“文件创建/写入错误:”+fe.Message,”提示信息”,MessageBoxButtons.RetryCancel,MessageBoxIcon.Information);
}
//禁用Socket
socket.Shutdown(SocketShutdown.Both);
//关闭Socket
socket.Close();
}
} |
程序在WindowsXP中文版、.Net Frameworkd 中文正式版、Visual Studio.Net中文正式版下调试通过
我们已经知道,由于Visual
C#本身没有类库,他是通过.Net框架中的.Net FrameWork
SDK(软件开发包)定义的一些类来实现对注册表的操作。这就是名称空间Microsoft.Win32中封装的二个类:Registry类、
RegistryKey类。在RegistryKey类中定义了二个方法用来创建注册表中的主键、子键和键值。他们是CreateSubValue (
)方法和SetValue ( )方法。那么如何用Visual
C#来修改注册信息,在本文中,我们只是介绍了修改注册表中的键值的方法。而对于主键和子键,由于.Net FrameWork
SDK中还没有定义这方面的方法,所以还无法完成安全的修改注册表中的信息。下面就先介绍如何用Visual C#来创建注册信息。
一.Visual C#创建和修改注册信息要调用的二个方法:
(1).CreateSubKey ( String key )方法:此方法是创建以后面的字符串为名称的子键。当然这种方法不仅能够创建子键,在下面介绍的程序中,也通过此种方法来创建一个主键。
(2).SetValue ( String name , String keyvalue
)方法:此方法的作用有二点,一种可以用来重命名键值的数值,一种可以用来创建新的键值。具体情况如下:当打开的子键中,如果存在此键值,就把新值赋给
他,实现重命名操作。如果不存在,则创建一个新的键值。
二.程序设计和运行环境以及要准备的工作:
I>视窗系统2000服务器版
II>.Net FrameWork SDK Beta 2版
III>由于在程序中,要修改一个已经存在的键值,所以就要预先设置好键值所在的位置。打开注册表的编辑器,在
“HKEY_LOCAL_MACHINE”主键下面的”HARDWARE”子键下面创建”aaa”子键并在此子键下面创建一个名称为”bbb”的键值。具
体如下图所示:

图01:为程序设置的注册表的结构图示
三.程序的主要功能以及设计的重要步骤:
在下面介绍的程序中,主要的功能是用Visual
C#在注册表中创建一个主键、一个子键和修改一个指定的键值。其中要创建的子键的结构层次是在主键”HKEY_LOCAL_MACHIN”下面的
“HAREWARE”主键下,名称为”ddd”,其中包含一个键值,名称为”www”,键值的值为”1234″。
其中的要创建的主键的结构层次也是在主键”HKEY_LOCAL_MACHIN”下面的”HAREWARE”主键下,名称为
“main”,在此主键下面包含一个名称为”sub”的子键和名称为”value”键值,键值的值为”1234″。下面就来着重介绍Visual
C#是如何创建和修改这些主键、子键和键值的。
(1).如何创建一个子键,在程序中是结合CreateSubKey ( )方法和SetValue ( )方法来实现的,以下是程序中创建子键的源程序:
listBox1.Items.Clear ( ) ; RegistryKey hklm = Registry.LocalMachine ; RegistryKey software = hklm.OpenSubKey ( “HARDWARE” , true ) ; RegistryKey main1 = software.CreateSubKey ( “main” ) ; RegistryKey ddd = main1.CreateSubKey ( “sub” ) ; ddd.SetValue ( “value” , “1234″ ); |
(2).如何创建一个主键,创建一个主键和创建一个子键的过程大致是差不多的。由于主键包含若干子键,所以在创建主键的时候必须注意他们的层次关系。下面这一段程序,在参考的时候,请注意一下main键和sub键之间的关系。
listBox1.Items.Clear ( ) ; RegistryKey hklm = Registry.LocalMachine ; RegistryKey software = hklm.OpenSubKey ( “HARDWARE”, true ) ; RegistryKey main1 = software.CreateSubKey ( “main” ) ; RegistryKey ddd = main1.CreateSubKey ( “sub” ) ; ddd.SetValue ( “value” , “1234″ ) ; |
(3).如何修改注册信息。由于注册表中的信息十分重要,所以一般不要对其进行写的操作。也可能是这个原因,在.Net
FrameWork SDK 中并没有提供修改注册表键的方法。而只是提供了一个危害性相对较小的方法–SetValue (
),通过这个方法,我们可以来修改键值。下面程序代码是修改一个指定键值名称的键值。当然由于SetValue(
)方法的特性,如果它检测到这个键值不存在,就会创建一个新的键值。
listBox1.Items.Clear ( ) ; RegistryKey hklm = Registry.LocalMachine ; RegistryKey software = hklm.OpenSubKey ( “HARDWARE”, true ) ; RegistryKey dddw = software.OpenSubKey ( “aaa” , true ) ; dddw.SetValue ( “bbb” , “abcd” ) ; |
四.本文中源程序代码( reg.cs )以及编译后的程序运行界面:
以下是程序运行的界面:
图02:本文中介绍的程序运行界面
reg.cs程序代码如下:
using System ; using System.Drawing ; using System.Collections ; using System.ComponentModel ; using System.Windows.Forms ; using System.Data ; using Microsoft.Win32 ; //导入使用到的名称空间
public class Form1 : Form { private System.ComponentModel.Container components ; private ListBox listBox1 ; private Button button1 ; private Button button2 ; private Button button3 ; private Button button4 ;
public Form1 ( ) { InitializeComponent ( ) ; } //清除在程序中使用过的资源 public override void Dispose ( ) { base.Dispose ( ) ; components.Dispose ( ) ; } //初始化程序中使用到的组件 private void InitializeComponent ( ) { this.components = new System.ComponentModel.Container ( ) ; this.button1 = new Button ( ) ; this.listBox1 = new ListBox ( ) ; button1.Location = new System.Drawing.Point ( 16 , 320 ) ; button1.Size = new System.Drawing.Size ( 90 , 23 ) ; button1.TabIndex = 0 ; button1.Text = “读取注册表” ; button1.Click += new System.EventHandler ( this.button1_Click ) ;
this.button2 = new Button ( ) ; button2.Location = new System.Drawing.Point ( 116 , 320 ) ; button2.Size = new System.Drawing.Size ( 90 , 23 ) ; button2.TabIndex = 1 ; button2.Text = “创建子键” ; button2.Click += new System.EventHandler ( this.button2_Click ) ;
this.button3 = new Button ( ) ; button3.Location = new System.Drawing.Point ( 216 , 320 ) ; button3.Size = new System.Drawing.Size ( 90 , 23 ) ; button3.TabIndex = 2 ; button3.Text = “创建主键” ; button3.Click += new System.EventHandler ( this.button3_Click ) ;
this.button4 = new Button ( ) ; button4.Location = new System.Drawing.Point ( 316 , 320 ) ; button4.Size = new System.Drawing.Size ( 90 , 23 ) ; button4.TabIndex = 3 ; button4.Text = “重命名键值” ; button4.Click += new System.EventHandler ( this.button4_Click ) ;
listBox1.Location = new System.Drawing.Point ( 16 , 32 ) ; listBox1.Size = new System.Drawing.Size ( 496 , 264 ) ; listBox1.TabIndex = 4 ; this.Text = “用Visual C#来创建和修改注册表中的注册信息!” ; this.AutoScaleBaseSize = new System.Drawing.Size ( 5 , 13 ) ; this.ClientSize = new System.Drawing.Size ( 528 , 357 ) ; //在窗体中加入组件 this.Controls.Add ( this.listBox1 ) ; this.Controls.Add ( this.button1 ) ; this.Controls.Add ( this.button2 ) ; this.Controls.Add ( this.button3 ) ; this.Controls.Add ( this.button4 ) ; } //以列表形式显示”HARDWARE”下面一层的子键和键值 protected void button1_Click ( object sender , System.EventArgs e ) { listBox1.Items.Clear ( ) ; RegistryKey hklm = Registry.LocalMachine ; RegistryKey software = hklm.OpenSubKey ( “HARDWARE” ) ; //打开”SYSTEM”子键 foreach ( string site in software.GetSubKeyNames ( ) ) //开始遍历由子键名称组成的字符串数组 { listBox1.Items.Add ( site ) ; //在列表中加入子键名称 RegistryKey sitekey = software.OpenSubKey ( site ) ; //打开此子键 foreach ( string sValName in sitekey.GetValueNames ( ) ) //开始遍历由指定子键拥有的键值名称组成的字符串数组 { listBox1.Items.Add ( ” ” + sValName + “: ” + sitekey.GetValue ( sValName ) ) ; //在列表中加入键名称和对应的键值 } } } //创建子键和键值 protected void button2_Click ( object sender , System.EventArgs e ) { listBox1.Items.Clear ( ) ; RegistryKey hklm = Registry.LocalMachine ; RegistryKey software = hklm.OpenSubKey ( “HARDWARE”, true ) ; RegistryKey ddd = software.CreateSubKey ( “ddd” ) ; ddd.SetValue ( “www” , “1234″ ); } //创建一个主键并创建一个键值 protected void button3_Click ( object sender , System.EventArgs e ) { listBox1.Items.Clear ( ) ; RegistryKey hklm = Registry.LocalMachine ; RegistryKey software = hklm.OpenSubKey ( “HARDWARE”, true ) ; RegistryKey main1 = software.CreateSubKey ( “main” ) ; RegistryKey ddd = main1.CreateSubKey ( “sub” ) ; ddd.SetValue ( “value” , “1234″ ) ; } //重命名一个存在的键值 protected void button4_Click ( object sender , System.EventArgs e ) { listBox1.Items.Clear ( ) ; RegistryKey hklm = Registry.LocalMachine ; RegistryKey software = hklm.OpenSubKey ( “HARDWARE”, true ) ; RegistryKey dddw = software.OpenSubKey ( “aaa” , true ) ; dddw.SetValue ( “bbb” , “abcd” ) ; } public static void Main ( ) { Application.Run ( new Form1 ( ) ) ; } } |
由于Visual C#本身没有带类库,他对注册表的处理过程是通过调用.Net FrameWork
SDK中的名称空间Microsoft.Win32中封装的二个类来实现的。这二个类就是Registry类、RegistryKey类。在
RegistryKey类中定义了三个方法来删除注册表中的注册信息。他们分别是:DeleteSubKey (
)方法、DeleteSubKeyTree ( )方法、DeleteValue ( )方法。下面就具体介绍一下在Visual
C#中如何正确使用这三个方法。
一.如何用Visual C#中调用这三个方法:
在介绍如何使用这三个方法之前,还需要重新介绍一下RegistryKey类中的一个方法–OpenSubKey ( )方法。在上一文中已经介绍了,此方法是打开指定的子键。其实OpenSubKey( )方法有二种调用的方式:
- OpenSubKey (string , subkey) :这种调用方式是对于此子键只是进行读操作。
- OpenSubKey (string subkey, Boolean writable):当对子键使用写操作的时候要用此种调用方法。如果在对子键使用了写操作,但仍然使用第一种调用方法,在程序运行的时候会产生一个错误信息。
- DeleteSubKey ( )方法:
此方法是删除一个指定的子键,在使用此方法的时候,如果在此子键中还存在另外的子键,则会产生一个错误信息。在程序中调用此方法有二种原型,为:
- DeleteSubKey ( string , subkey ):这种调用方式就是直接删除指定的子键。
- DeleteSubKey ( string subkey , Boolean info
):其中的”string”是要删除的子键的名称,”Boolean”参数的意思是:如果值为”True”,则在程序调用的时候,删除的子键不存在,则产
生一个错误信息;如果值为”False”,则在程序调用的时候,删除的子键不存在,也不产生错误信息,程序依然正确运行。所以在具体的程序设计过程中,我
还是推荐使用第二种调用方法。
DeleteSubKeyTree ( )方法:
此方法是彻底删除指定的子键目录,即:删除该子键以及该子键以下的全部子键。由于此方法的破坏性是非常强的,所有在使用的时候要非常主要。在程序中调用此方法的原型就一种,为:
DeleteSubKeyTree ( string subkey ):其中”subkey”就是要彻底删除的子键名称。
DeleteValue ( )方法:
此方法是删除指定的键值。在程序中调用此方法的原型就一种,为:
DeleteValue ( string value ):其中”value”就是要删除的键值的名称。
在介绍完与删除注册表中注册信息有关方法后,将通过一个程序来说明他们在程序中具体用法。
二. 程序设计和运行环境以及要准备的工作:
- 视窗系统2000服务器版
- .Net FrameWork SDK Beta 2版
- 由于程序的功能是删除指定的主键、子键和键值,这就需要我们在注册表中先为设置好这些值的位置和名称。具体如下:
在HKEY_LOCAL_MACHINE主键下面的”SOFTWARE”子键中建立如下子键和键值:
在”SOFTWARE”子键下建立”aaa”子键。在”aaa”子键下面建立”bbb”子键和”ddd”子键。在”bbb”子键中建立名称为”ccc”的
键值,键值的值为”ccc”。子”ddd”子键中建立子键”eee”,并在此子键中建立一个”fff”键值,键值的值为”fff”。程序中要删除的键值是
“ccc”键值,要删除的子键是”bbb”,要彻底删除的子键是”ddd”。具体设定如下图所示:

图01:为程序设定的注册表结构图
三. 程序设计的重要步骤:
程序设计的主要步骤就是如何删除键值、不包含任何子键的子键、包含子键的子键。下面就通过程序来具体说明:
- 如何删除键值。在程序中要删除键值是”ccc”。以下就是程序中删除此键值的具体语句。
RegistryKey
hklm = Registry.LocalMachine ;RegistryKey software = hklm.OpenSubKey (
“SOFTWARE”, true ) ;//打开”SOFTWARE”子键RegistryKey no1 =
software.OpenSubKey ( “aaa”, true ) ;//打开”aaa”子键RegistryKey no2 =
no1.OpenSubKey ( “bbb” , true ) ;//打开”bbb”子键no2.DeleteValue( “ccc” )
;//删除名称为”ccc”的键值 |
- 如何删除不包含任何子键的子键。在程序要删除的子键是”bbb”。以下就是删除此子键的具体程序代码:
RegistryKey
hklm = Registry.LocalMachine ;RegistryKey software = hklm.OpenSubKey (
“SOFTWARE”, true ) ;//打开”SOFTWARE”子键RegistryKey no1 =
software.OpenSubKey ( “aaa”, true ) ;//打开”aaa”子键no1.DeleteSubKey (
“bbb”, false );//删除名称为”bbb”的子键 |
- 如何删除包含子键的子键。在程序中要删除的此子键是”ddd”。以下就是删除此子键的具体程序代码:
RegistryKey
hklm = Registry.LocalMachine ;hklm.DeleteSubKey ( “aaa”, false
);RegistryKey software = hklm.OpenSubKey ( “SOFTWARE”, true )
;//打开”SOFTWARE”子键RegistryKey no1 = software.OpenSubKey ( “aaa”, true )
;//打开”aaa”子键no1.DeleteSubKeyTree ( “ddd” );//删除名称为”ddd”的子键 |
四.本文中的程序源代码( reg.cs )以及运行界面:
reg.cs程序的主要功能就是删除注册表中的键值、不包含子键的子键和包含子键的子键。并且通过按钮”读取注册表”,以列表的显示方法来及时了解删除的情况。下图就是程序运行后的界面:

图02:本文中程序的运行界面
reg.cs程序源代码如下:
using System ; using System.Drawing ; using System.Collections ; using System.ComponentModel ; using System.Windows.Forms ; using System.Data ; using Microsoft.Win32 ; public class Form1 : Form { private System.ComponentModel.Container components ; private ListBox listBox1 ; private Button button1 ; private Button button2 ; private Button button3 ; private Button button4 ; public Form1 ( ) { InitializeComponent ( ) ; } //清除在程序中使用过的资源 public override void Dispose ( ) { base.Dispose ( ) ; components.Dispose ( ) ; } //初始化程序中使用到的组件 private void InitializeComponent ( ) { components = new System.ComponentModel.Container ( ) ; button1 = new Button ( ) ; button2 = new Button ( ) ; button3 = new Button ( ) ; button4 = new Button ( ) ; listBox1 = new ListBox ( ) ;button1.Location = new System.Drawing.Point ( 16 , 320 ) ; button1.Size = new System.Drawing.Size ( 75 , 23 ) ; button1.TabIndex = 0 ; button1.Text = “读取注册表” ; button1.Click += new System.EventHandler ( button1_Click ) ;
button2.Location = new System.Drawing.Point ( 116 , 320 ) ; button2.Size = new System.Drawing.Size ( 75 , 23 ) ; button2.TabIndex = 0 ; button2.Text = “删除键值ccc” ; button2.Click += new System.EventHandler ( button2_Click ) ;
button3.Location = new System.Drawing.Point ( 216 , 320 ) ; button3.Size = new System.Drawing.Size ( 75 , 23 ) ; button3.TabIndex = 0 ; button3.Text = “删除子键bbb” ; button3.Click += new System.EventHandler ( button3_Click ) ;
button4.Location = new System.Drawing.Point ( 316 , 320 ) ; button4.Size = new System.Drawing.Size ( 75 , 23 ) ; button4.TabIndex = 0 ; button4.Text = “删除主键ddd” ; button4.Click += new System.EventHandler ( button4_Click ) ;
listBox1.Location = new System.Drawing.Point ( 16 , 32 ) ; listBox1.Size = new System.Drawing.Size ( 496 , 264 ) ; listBox1.TabIndex = 1 ;
this.Text = “用Visual C#来删除注册表中的主键、子键和键值!” ; this.AutoScaleBaseSize = new System.Drawing.Size ( 5 , 13 ) ; this.ClientSize = new System.Drawing.Size ( 528 , 357 ) ; this.Controls.Add ( listBox1 ) ; this.Controls.Add ( button1 ) ; this.Controls.Add ( button2 ) ; this.Controls.Add ( button3 ) ; this.Controls.Add ( button4 ) ; } protected void button1_Click ( object sender , System.EventArgs e ) { listBox1.Items.Clear ( ) ; RegistryKey hklm = Registry.LocalMachine ; RegistryKey software = hklm.OpenSubKey ( “SOFTWARE” ) ; //打开”SOFTWARE”子键 RegistryKey no1 = software.OpenSubKey ( “aaa” ) ; //打开”aaa”子键 foreach ( string site in no1.GetSubKeyNames ( ) ) //开始遍历由子键名称组成的字符串数组 { listBox1.Items.Add ( site ) ; //在列表中加入子键名称 RegistryKey sitekey = no1.OpenSubKey ( site ) ; //打开此子键 foreach ( string sValName in sitekey.GetValueNames ( ) ) //开始遍历由指定子键拥有的键值名称组成的字符串数组 { listBox1.Items.Add ( ” ” + sValName + “: ” + sitekey.GetValue ( sValName ) ) ; //在列表中加入键名称和对应的键值 } } } protected void button2_Click ( object sender , System.EventArgs e ) { RegistryKey hklm = Registry.LocalMachine ; RegistryKey software = hklm.OpenSubKey ( “SOFTWARE”, true ) ; //打开”SOFTWARE”子键 RegistryKey no1 = software.OpenSubKey ( “aaa”, true ) ; //打开”aaa”子键 RegistryKey no2 = no1.OpenSubKey ( “bbb” , true ) ; //打开”bbb”子键 no2.DeleteValue( “ccc” ) ; //删除名称为”ccc”的键值 } protected void button3_Click ( object sender , System.EventArgs e ) { RegistryKey hklm = Registry.LocalMachine ; RegistryKey software = hklm.OpenSubKey ( “SOFTWARE”, true ) ; //打开”SOFTWARE”子键 RegistryKey no1 = software.OpenSubKey ( “aaa”, true ) ; //打开”aaa”子键 no1.DeleteSubKey ( “bbb”, false ); //删除名称为”bbb”的子键 } protected void button4_Click ( object sender , System.EventArgs e ) { RegistryKey hklm = Registry.LocalMachine ; hklm.DeleteSubKey ( “aaa”, false ); RegistryKey software = hklm.OpenSubKey ( “SOFTWARE”, true ) ; //打开”SOFTWARE”子键 RegistryKey no1 = software.OpenSubKey ( “aaa”, true ) ; //打开”aaa”子键 no1.DeleteSubKeyTree ( “ddd” ); //删除名称为”ddd”的子键 } public static void Main ( ) { Application.Run ( new Form1 ( ) ) ; } }
|
五.总结:
本文介绍Visual C#注册表编程的一个重要内容,即:如何删除注册信息。由于删除注册信息是一项非常具有破坏性的操作,所以在操作之前一定要注意对注册表的保护工作。
从视窗95开始,微软公司就在视窗系统中引入了注册表这个概念。注册表到底是什么东东呢?它是视窗系统的一个核心的数据库,在这个数据库中存放中与系统相关的各种参数,这些参数直接控制中系统的启动、硬件的驱动程序安装信息以及在视窗系统上运行的各种应用程序的注册信息等。这就意味着,如果注册表因为某些原因受到了破坏,轻者是视窗系统启动过程出现异常,重者就有可能导致整个系统的完全瘫痪。所以正确的认识注册表,及时的备份注册表,对于视窗用户就显得相当重要。
Vsiaul C#就可以十分方便、简洁的开发出操作注册表的程序。本文就是介绍如何利用VisualC#来读取注册表中的信息。
一.初步认识注册表:
单击”开始/运行”,在”打开”的后面填入”regedit”。就可以看到注册表的数据结构了。如下图。注:Regedit文件是微软公司提供给用户编辑注册表的一个工具。

图01:注册表结构图示
如上图左边的部分在注册表中称为”主键”,据图可见,”主键”是有层次结构的。主键的下一级主键称为该主键的”子键”。每一个主键可以对拥有多个子键。如图所示,右边的这些值就是所谓的键值了。每一个主键或者子键都可以拥有多个键值。注册表是一个庞大的数据库,在其中每一个主键,每一个键值都赋予了不同的功能。
二.Visual C#如何读取注册表中的主键和键值:
在.Net
FrameWork SDK Beta
2版中,有一个Microsoft.Win32的名称空间,在此名称空间中提供了二个用于注册表操作的类:Registry类、RegistryKey类。这二个类都是封闭类,不可以继承。在这二个类,定义了许多关于注册表的方法和属性,通过调用这二个类,在Visual
C#中就可以比较轻松的处理关于注册表的各种操作了。
- Registry类:
此类主要封装了七个公有的静态域,而这些静态域分别代表这视窗注册表中的七个基本的主键,具体如下所示:
Registry.ClassesRoot
对应于HKEY_CLASSES_ROOT主键
Registry.CurrentUser
对应于HKEY_CURRENT_USER主键
Registry.LocalMachine 对应于
HKEY_LOCAL_MACHINE主键
Registry.User 对应于 HKEY_USER主键
Registry.CurrentConfig
对应于HEKY_CURRENT_CONFIG主键
Registry.DynDa
对应于HKEY_DYN_DATA主键
Registry.PerformanceData 对应于HKEY_PERFORMANCE_DATA主键
- .RegistryKey类:
此类中主要封装了对视窗系统注册表的基本操作。在程序设计中,首先通过Registry类找到注册表中的基本主键,然后通过RegistryKey类,来找其下面的子键和处理具体的操作的。
三.通过一个读取注册表信息例子来具体说明这二个来的用法:
- (1).程序设计和运行的环境:I视窗系统2000服务器版 II Net FrameWork SDK Beta 2版
- (2)在运行程序前的一些必要的处理工作:
在程序设计时,主要功能是读取已经存在的主键键值,用户可以按照下图所示的结构新建若干个主键和对应的键值

图02:程序设计中要读取的注册表的信息
- 这里有必要说明的是上图只显示了”新项 #3″子键对应的键值。在”新项 #2″子键也有键值,对应的键值是:”新值#1″为”001″,”新值
#2″为”002″。在”新项 #1″子键中对应的键值是:”新值 #1″为”aaa”,”新值 #2″为”bbb”。
- 程序的主要功能:
程序的主要功能是读取指定主键下面的所有子键和子键拥有的键值,并以列表的形式按层次显示出来,下图是本程序运行后界面:

图03:读取注册表信息并以列表形式显示出来
4.
- .程序设计过程中的重要步骤以及应该注意的一些问题:
I
程序中读取主键、子键和键值所使用到的方法:
程序中为了读取指定主键下面的子键和子键中拥有的键值,主要使用了RegistryKey类中的四个方法:OpenSubKey,GetSubKeyNames,GetValueNames,GetValue。具体的用法和意思如下:
- OpenSubKey ( string name )方法主要是打开指定的子键。
- GetSubKeyNames ( )方法是获得主键下面的所有子键的名称,它的返回值是一个字符串数组。
- GetValueNames ( )方法是获得当前子键中的所有的键名称,它的返回值也是一个字符串数组。
- GetValue ( string name )方法是指定键的键值。
程序中具体的使用语句如下:
RegistryKey hklm = Registry.LocalMachine
;//打开”SYSTEM”子键RegistryKey software = hklm.OpenSubKey ( “SYSTEM” )
;//打开”001″子键RegistryKey no1 = software.OpenSubKey ( “001″ )
;//打开”002″子键RegistryKey no2 = no1.OpenSubKey ( “002″ )
; |
其中listBox1是程序中定义了的列表名称。
II
如何用列表形式显示注册信息:
由于GetSubKeyNames ( )方法和GetValueNames (
)方法的返回值是字符串数组,所以在程序中是通过foreach语句实现遍历这些字符串数组的。并且在遍历的时候,就通过列表形式显示出来,程序中具体实现语句如下:
foreach ( string site in no2.GetSubKeyNames ( )
)//开始遍历由子键名称组成的字符串数组{listBox1.Items.Add ( site ) ;//在列表中加入子键名称RegistryKey
sitekey = no2.OpenSubKey ( site ) ;//打开此子键foreach ( string sValName in
sitekey.GetValueNames ( ) )//开始遍历由指定子键拥有的键值名称组成的字符串数组{listBox1.Items.Add ( “” +
sValName + “: ” + sitekey.GetValue ( sValName ) )
;//在列表中加入键名称和对应的键值}} |
- 源程序代码:
通过以上的论述,我们可以得到程序的源程序代码,具体如下:
using System ;using System.Drawing ;using
System.Collections ;using System.ComponentModel ;using System.Windows.Forms
;using System.Data ;using Microsoft.Win32 ; public class Form1 : Form{private
System.ComponentModel.Container components ;private ListBox listBox1 ;private
Button button1 ;public Form1 ( ){InitializeComponent ( ) ;}//清除在程序中使用过的资源public
override void Dispose ( ){base.Dispose ( ) ;components.Dispose ( )
;}//初始化程序中使用到的组件private void InitializeComponent ( ){this.components = new
System.ComponentModel.Container ( ) ;this.button1 = new Button ( )
;this.listBox1 = new ListBox ( ) ;button1.Location = new System.Drawing.Point (
16 , 320 ) ;button1.Size = new System.Drawing.Size ( 75 , 23 ) ;button1.TabIndex
= 0 ;button1.Text = “读取注册表” ;button1.Click += new System.EventHandler(
this.button1_Click ) ;listBox1.Location = new System.Drawing.Point ( 16 , 32 )
;listBox1.Size = new System.Drawing.Size ( 496 , 264 ) ;listBox1.TabIndex = 1
;this.Text = “读取主测表信息” ;this.AutoScaleBaseSize = new System.Drawing.Size ( 5 ,
13 ) ;this.ClientSize = new System.Drawing.Size ( 528 , 357 )
;this.Controls.Add( this.listBox1 ) ;this.Controls.Add ( this.button1 )
;}protected void button1_Click ( object sender , System.EventArgs e
){listBox1.Items.Clear ( ) ;RegistryKey hklm = Registry.LocalMachine
;RegistryKey software = hklm.OpenSubKey ( “SYSTEM” ) ;//打开”SYSTEM”子键RegistryKey
no1 = software.OpenSubKey ( “001″ ) ;//打开”001″子键RegistryKey no2 = no1.OpenSubKey
( “002″ ) ;//打开”002″子键foreach ( string site in no2.GetSubKeyNames ( )
)//开始遍历由子键名称组成的字符串数组{listBox1.Items.Add ( site ) ;//在列表中加入子键名称RegistryKey
sitekey = no2.OpenSubKey ( site ) ;//打开此子键foreach ( string sValName in
sitekey.GetValueNames ( ) )//开始遍历由指定子键拥有的键值名称组成的字符串数组{listBox1.Items.Add ( “” +
sValName + “: ” + sitekey.GetValue ( sValName ) ) ;//在列表中加入键名称和对应的键值}}}public
static void Main ( ){Application.Run ( new Form1 ( ) )
;}} |
四.总结:
用Visual
C#来读取注册表中的注册信息是通过名称空间Micorsoft.Win32中的二个类来实现的。在这二个类中还定义了对注册表信息的删除、修改和重命名的一些方法。这些方法比起本文介绍的读取方法、打开方法来说,更具有破坏性,但也更实用。对应这些方法的介绍将在以后的文章中进行。
通过以上的介绍,我们发现用Visual
C#来处理注册表,其实是一件比较轻松而简单的事情。事情虽然是轻松的,但我也要提醒各位,由于注册表在视窗系统中的重要作用,所以在每一次对注册表进行操作之前,一定要备份,在操作的时候也要非常小心,因为你的每一次的误操作都可能导致你的系统崩溃。
在了解HTTP断点续传的原理之前,让我们先来了解一下HTTP协议,HTTP协议是一种基于tcp的简单协议,分为请求和回复两种。请求协议是由客户机(浏览器)向服务器(WEB
SERVER)提交请求时发送报文的协议。回复协议是由服务器(web
server),向客户机(浏览器)回复报文时的协议。请求和回复协议都由头和体组成。头和体之间以一行空行为分隔。
以下是一个请求报文与相应的回复报文的例子:
GET
/image/index_r4_c1.jpg HTTP/1.1
Accept: */*
Referer:
http://192.168.3.120:8080
Accept-Language: zh-cn
Accept-Encoding: gzip,
deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET
CLR 1.0.3705)
Host: 192.168.3.120:8080
Connection:
Keep-Alive
HTTP/1.1 200 OK
Server: Microsoft-IIS/5.0
Date: Tue,
24 Jun 2003 05:39:40 GMT
Content-Type: image/jpeg
Accept-Ranges:
bytes
Last-Modified: Thu, 23 May 2002 03:05:40 GMT
ETag:
“bec48eb862c21:934″
Content-Length: 2827
….
下面我们就来说说”断点续传”,顾名思义,断点续传就是在上一次下载时断开的位置开始继续下载。
在HTTP协议中,可以在请求报文头中加入Range段,来表示客户机希望从何处继续下载。
比如说从第1024字节开始下载,请求报文如下:
GET
/image/index_r4_c1.jpg HTTP/1.1
Accept: */*
Referer:
http://192.168.3.120:8080
Accept-Language: zh-cn
Accept-Encoding: gzip,
deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET
CLR 1.0.3705)
Host: 192.168.3.120:8080
Range:bytes=1024-
Connection:
Keep-Alive
.NET中的相关类
明白了上面的原理,那么,我们来看看.NET
FRAMEWORK中为我们提供了哪些类可以来做这些事。
完成HTTP请求
System.Net.HttpWebRequest
HttpWebRequest
类对 WebRequest 中定义的属性和方法提供支持,也对使用户能够直接与使用 HTTP
的服务器交互的附加属性和方法提供支持。
HttpWebRequest 将发送到 Internet 资源的公共 HTTP
标头值公开为属性,由方法或系统设置。下表包含完整列表。可以将 Headers
属性中的其他标头设置为名称/值对。但是注意,某些公共标头被视为受限制的,它们或者直接由
API公开,或者受到系统保护,不能被更改。Range也属于被保护之列,不过,.NET为开发者提供了更方便的操作,就是
AddRange方法,向请求添加从请求数据的开始处或结束处的特定范围的字节范围标头
完成文件访问
System.IO.FileStream
FileStream
对象支持使用Seek方法对文件进行随机访问, Seek
允许将读取/写入位置移动到文件中的任意位置。这是通过字节偏移参考点参数完成的。字节偏移量是相对于查找参考点而言的,该参考点可以是基础文件的开始、当前位置或结尾,分别由SeekOrigin类的三个属性表示。
代码实现
了解了.NET提供的相关的类,那么,我们就可以方便的实现了。
代码如下:
static
void Main(string[] args)
{
string StrFileName=”c:\\aa.zip”;
//根据实际情况设置
string StrUrl=”http://www.xxxx.cn/xxxxx.zip”;
//根据实际情况设置
//打开上次下载的文件或新建文件
long lStartPos =0;
System.IO.FileStream
fs;
if (System.IO.File.Exists(StrFileName))
{
fs=
System.IO.File.OpenWrite(StrFileName);
lStartPos=fs.Length;
fs.Seek(lStartPos,System.IO.SeekOrigin.Current);
//移动文件流中的当前指针
}
else
{
fs = new
System.IO.FileStream(StrFileName,System.IO.FileMode.Create);
lStartPos
=0;
}
//打开网络连接
try
{
System.Net.HttpWebRequest request
=(System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create(StrUrl);
if (
lStartPos>0)
request.AddRange((int)lStartPos);
//设置Range值
//向服务器请求,获得服务器回应数据流
System.IO.Stream ns=
request.GetResponse().GetResponseStream();
byte[] nbytes = new
byte[512];
int nReadSize=0;
nReadSize=ns.Read(nbytes,0,512);
while(
nReadSize
>0)
{
fs.Write(nbytes,0,nReadSize);
nReadSize=ns.Read(nbytes,0,512);
}
fs.Close();
ns.Close();
Console.WriteLine(“下载完成”);
}
catch(Exception
ex)
{
fs.Close();
Console.WriteLine(“下载过程中出现错误:”+ex.ToString());
}
}
刚才一刷新页面发现页头多了一个导航栏,真难看!查源代码,原来是个叫classnavbar的东东。OK,马上清除它!
在[选项]-[配置]-[定制CSS选择器]里加上这么几句,就OK
#classnavbar
{
display:none;
}
保存一下,再来看看。高唱:我回到过去!
using System ;
using System.Drawing ;
using System.Collections ;
using System.ComponentModel ;
using System.Windows.Forms ;
using System.Data ;
using System.Runtime.InteropServices ;
using System.Text ;
namespace C_操作INI文件__写操作
{
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.OpenFileDialog openFileDialog1 ;
private System.Windows.Forms.CheckBox checkBox1;
private System.ComponentModel.Container components = null ;
public Form1 ( )
{
InitializeComponent ( ) ;
}
protected override void Dispose ( bool disposing )
{
if ( disposing )
{
if ( components != null )
{
components.Dispose ( ) ;
}
}
base.Dispose ( disposing ) ;
}
[ DllImport ( "kernel32" ) ]
private static extern long WritePrivateProfileString ( string
section ,
string key , string val , string filePath ) ;
[ DllImport ( "kernel32" ) ]
private static extern int GetPrivateProfileString ( string section ,
string key , string def , StringBuilder retVal ,
int size , string filePath ) ;
private void InitializeComponent ( )
{
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.checkBox1 = new System.Windows.Forms.CheckBox();
this.SuspendLayout();
//
// openFileDialog1
//
this.openFileDialog1.Filter = “INI 文件|*.ini”;
//
// checkBox1
//
this.checkBox1.Location = new System.Drawing.Point(128, 24);
this.checkBox1.Name = “checkBox1″;
this.checkBox1.Size = new System.Drawing.Size(48, 24);
this.checkBox1.TabIndex = 12;
this.checkBox1.Text = “chk”;
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(366, 217);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.checkBox1});
this.MaximizeBox = false;
this.Name = “Form1″;
this.Text = “C#操作INI文件–写操作”;
this.Load += new System.EventHandler(this.Form1_Load);
this.Closed += new System.EventHandler(this.Form1_Closed);
this.ResumeLayout(false);
}
[STAThread]
static void Main ( )
{
Application.Run ( new Form1 ( ) ) ;
}
//读取指定INI文件的特定段落中的关键字的数值
private void Form1_Closed(object sender, System.EventArgs e)
{
if(checkBox1.Checked==true)
WritePrivateProfileString(“checkBox1″,”Checked”,”true”,”D:\\checked.ini”);
if(checkBox1.Checked==false)
WritePrivateProfileString(“checkBox1″,”Checked”,”false”,”D:\\checked.ini”);
}
private void Form1_Load(object sender, System.EventArgs e)
{
StringBuilder temp = new StringBuilder(255);
int i = GetPrivateProfileString(“checkBox1″,”Checked”,”无法读取对应数值”,temp,255,”D:\\checked.ini”);
if(temp.ToString ()==”true”)
checkBox1.Checked=true;
if(temp.ToString ()==”false”)
checkBox1.Checked=false;
}
}
}