随笔 - 85  文章 - 1  评论 - 5 
  置顶随笔
我们没有离开
我们只是在另一个世界守望着我们的故乡
在浩瀚而美丽的夜空中
点点繁星犹如闪耀的烟花
是我们永远不灭的生命的渔火
我们要用我们的坚强
照亮那些曾经走过的曲折的小路
照亮那些曾经欢闹过的涓涓小河
照亮那些曾经挚爱的熟悉的面孔
从那一刻起
我们的故乡不再有黑夜
当你们推开废墟
重建家园的时候
不要忘记
遥远的天空的那一边
有一群孩子
在为这个世界祈福


posted @ 2008-05-25 10:16 颜斌 阅读(70) | 评论 (0)编辑
  2008年8月29日
正如大家所知.Net对内存资源的占用是非常恐怖的,一个空的Form程序就得占用10M的内存。 再加上一个Windows Service那就轻松越过20M了。这不,最近在工作中就遇到了这个问题。需求方要求内存在10M以内。。。郁闷。。。查阅了相关资料后,终于找到解决方法。 

     我们知道,Windows是一个多任务的操作系统,而物理内存却是一个相对贫乏的资源,为避免某个进程(或是系统)耗尽这一资源,引入了工作集(WorkingSet)的概念。进程的工作集是物理 RAM 内存中当前对该进程可见的内存页的集合。这些内存页是常驻内存,可供应用程序使用,而不会触发页面错误。工作集包括共享数据和私有数据。共享数据包括那些包含应用程序执行的所有指令的页(包括 .dll 文件和 system.dll 文件中的页)。随着工作集大小的增加,内存需求也增加。进程具有最小和最大的工作集大小。每次创建进程资源时,系统都会保留等于该进程最小工作集大小的内存量。虚拟内存管理器会尝试在进程处于活动状态时至少保留最小的常驻内存量,但决不会保留超过最大大小的内存量。

在Framework中为我们提供了以下设置进程最大工作集合的属性:

Process.MaxWorkingSet 属性

获取或设置关联进程的允许的最大工作集大小。

命名空间: System.Diagnostics
程序集:  System(在 System.dll 中)

看到这里,笔者迫不及待在代码去测试这个属性:

Code

调用后,内存的确有质的飞跃,从10M+降到到3M左右.如图:

调用前:

调用后:

 

 然而程序运行一段时间后,发现内存又轻松突破15M, 难道要不断去设置这个值。。。。。

 1 public partial class TestPerformance : Form
 2    {
 3        private System.Threading.Timer timer = null;
 4
 5        public TestPerformance()
 6        {
 7            InitializeComponent();
 8        }

 9
10        private void Form1_Load(object sender, EventArgs e)
11        {
12            
13        }

14
15        private void buttonStart_Click(object sender, EventArgs e)
16        {
17            timer = new System.Threading.Timer(new System.Threading.TimerCallback(ReduceMemory), null05000);
18        }

19
20        private void ReduceMemory(object obj)
21        {
22            Process p = Process.GetCurrentProcess();
23            p.MaxWorkingSet = p.MaxWorkingSet;
24        }

25
26        private void ReduceMemoryOnce()
27        {
28            Process p = Process.GetCurrentProcess();
29            p.MaxWorkingSet = new IntPtr(750000);
30        }

31
32        private void buttonOnce_Click_1(object sender, EventArgs e)
33        {
34            ReduceMemoryOnce();
35        }

36    }

这次声明了一个Thread.Timer 间隔5秒去设置MaxWorkingSet的值。内存一直维持在2M以内,如图:

 至此问题得到解决。。。。

 在一个国外网站上找到一篇文章,对该问题有类似的描述,如下

Windows Forms apps are pretty bloated in terms of memory usage. The main reason .Net apps have such a huge footprint is that the JIT compiler loads when the app starts and all that bootstrap code and a ton of the WinForms engine is loaded and compiled at startup and gets loaded into your process. Beside the fact that this takes up processor cycles it also consumes a lot of memory. The JIT is pretty good about which code gets compiled – for the most part it compiles only code that actually gets run, but the framework itself pulls in a lot of code as well and that gets compiled as well. Third party controls - ditto. The result of this is that on startup your app consumes a lot of resources that you will not need any longer once the app is up and running. Actually if you access another new part of the application that part will compile later, but for many apps the startup and main application form make up a huge chunk of what gets loaded and compiled as the data engine and business objects etc. usually are among the things that get called at startup. A large percentage generally gets compiled right at startup.

 If you’ve ever run your app and looked at Task Manager you might have noticed that the app starts out with a significant amount of memory. A basic WinForm app with a couple of textboxes and a button typically will run around 8 megs. If you move the form around a bit closer to 10. You then can minimize the app and it generally reduces to some really low memory usage number which slowly creeps back up as you open the form back up. What’s happening is that the app internally is adjusting the Working Set for the application which aggressively reduces the memory in use by the app. The app will reclaim what it needs, but for that moment the memory usage goes down drastically and it will stay much lower than the original startup usage.

详细文章:

http://www.west-wind.com/Weblog/posts/240.aspx

笔者对这篇文章的翻译,给需要的朋友。翻的不好好请多多见谅

http://www.cnblogs.com/netlife/archive/2008/08/28/1278770.html

疑问:

1. 大家都发现这个语句非常奇怪:P.MaxWorkingSet = P.MaxWorkingSet。那是因为在程序运行中,无法给MaxiWorkingSet设置一个确定的值,所以就有了这个写法。为什么这样就可以了呢?目前笔者正在分析P.MaxWorkingSet 的源代码。相信不久就有结果。也请知道原因的牛人能道破其中的玄机。

2. 这样做对性能有影响吗?

 

笔者水平有限,难免存在错误,希望大家指出和讨论。谢谢。

测试程序的源代码:http://files.cnblogs.com/netlife/PerformanceTest.rar

posted @ 2008-08-29 09:08 颜斌 阅读(11) | 评论 (0)编辑
  2008年8月18日

Sql Server2005 Transact-SQL 新兵器学习总结之-排名函数

Transact-SQL提供了4个排名函数: RANK(),DENSE_RANK(),ROW_NUMBER(),NTILE()


下面是对这4个函数的解释:
RANK()
返回结果集的分区内每行的排名。行的排名是相关行之前的排名数加一。
如果两个或多个行与一个排名关联,则每个关联行将得到相同的排名。
例如,如果两位销售员具有相同的SalesYTD值,则他们将并列第一。由于已有两行排名在前,所以具有下一个最大SalesYTD的销售人员将排名第三。
因此,RANK 函数并不总返回连续整数。


DENSE_RANK()
返回结果集分区中行的排名,在排名中没有任何间断。行的排名等于所讨论行之前的所有排名数加一。
如果有两个或多个行受同一个分区中排名的约束,则每个约束行将接收相同的排名。
例如,如果两位顶尖销售员具有相同的 SalesYTD 值,则他们将并列第一。接下来 SalesYTD 最高的销售人员排名第二。该排名等于该行之前的所有行数加一。
因此,DENSE_RANK 函数返回的数字没有间断,并且始终具有连续的排名。


ROW_NUMBER()
回结果集分区内行的序列号,每个分区的第一行从 1 开始。
ORDER BY 子句可确定在特定分区中为行分配唯一 ROW_NUMBER 的顺序。


NTILE()
将有序分区中的行分发到指定数目的组中。各个组有编号,编号从一开始。对于每一个行,NTILE 将返回此行所属的组的编号。
如果分区的行数不能被 integer_expression 整除,则将导致一个成员有两种大小不同的组。按照 OVER 子句指定的顺序,较大的组排在较小的组前面。
例如,如果总行数是 53,组数是 5,则前三个组每组包含 11 行,其余两个组每组包含 10 行。
另一方面,如果总行数可被组数整除,则行数将在组之间平均分布。
例如,如果总行数为 50,有五个组,则每组将包含 10 行。


--演示例题,建一个table
create table rankorder(
orderid 
int,
qty 
int
)
go
--插入数据
insert rankorder values(30,10)
insert rankorder values(10,10)
insert rankorder values(80,10)
insert rankorder values(40,10)
insert rankorder values(30,15)
insert rankorder values(30,20)
insert rankorder values(22,20)
insert rankorder values(21,20)
insert rankorder values(10,30)
insert rankorder values(30,30)
insert rankorder values(40,40)
go
--查询出各类排名
SELECT orderid,qty,
  ROW_NUMBER() 
OVER(ORDER BY qty) AS rownumber,
  RANK()       
OVER(ORDER BY qty) AS [rank],
  DENSE_RANK() 
OVER(ORDER BY qty) AS denserank ,
  NTILE(
3OVER(ORDER BY qty) AS [NTILE]
FROM rankorder
ORDER BY qty

--结果
--
ROW_NUMBER()是按qty由小到大逐一排名,不并列,排名连续
--
RANK()是按qty由小到大逐一排名,并列,排名不连续
--
DENSE_RANK()是按qty由小到大逐一排名,并列,排名连续
--
NTILE()是按qty由小到大分成3组逐一排名,并列,排名连续
orderid    qty    rownumber    rank    denserank    NTILE
30        10    1            1        1            1
10        10    2            1        1            1
80        10    3            1        1            1
40        10    4            1        1            1
30        15    5            5        2            2
30        20    6            6        3            2
22        20    7            6        3            2
21        20    8            6        3            2
10        30    9            9        4            3
30        30    10            9        4            3
40        40    11            11        5            3

sql 2005实现排名非常方便,但是用sql 2000实现排名就比较麻烦,下面是sql 2000的实现代码:


--RANK在sql 2000中的实现
select orderid,qty,
    (
select count(1)+1 from rankorder where qty<r.qty) as [rank]
from rankorder r
ORDER BY qty
go
 
--ROW_NUMBER在sql 2000中的实现
--
利用临时表和IDENTITY(函数)
select identity(int,1,1as [ROW_NUMBER],orderid,qty
into #tem             
from rankorder

select orderid,qty,[ROW_NUMBER]
from #tem

drop table #tem
go

--DENSE_RANK在sql 2000中的实现
select identity(int,1,1as ids,  qty
into #t
from rankorder
group by qty
order by qty

select r.orderid,r.qty,t.ids as [DENSE_RANK]
from rankorder r join #t  t
on r.qty=t.qty

drop table #t
go


排名函数是与窗口函数OVER()配合一起使用的。
如果借助OVER子句的参数PARTITION BY,就可以将结果集分为多个分区。排名函数将在每个分区内进行排名.


--例题
SELECT orderid,qty,
DENSE_RANK() 
OVER(ORDER BY qty) AS a ,
DENSE_RANK() 
OVER(PARTITION BY orderid ORDER BY qty) AS b     
FROM rankorder
ORDER BY qty

--说明:
--
a列是在全部记录上进行的排名
--
b列是把orderid中的记录分成了10,21,22,30,40,80这6个区,再在每个区上进行的排名。
orderid    qty    a    b
10        10    1    1
30        10    1    1
40        10    1    1
80        10    1    1
30        15    2    2
30        20    3    3
21        20    3    1
22        20    3    1
10        30    4    2
30        30    4    4
40        40    5    2


我们看到排名函数可以很简便的得到各种类型的排名
以下是我对4个排名函数的类比表格:
                               排名连续性   排名并列性
RANK()                 不一定连续    有并列
DENSE_RANK()    连续               有并列
ROW_NUMBER()   连续             无并列
NTILE()                  连续               有并列

 

 

posted @ 2008-08-18 09:17 颜斌 阅读(7) | 评论 (0)编辑
  2008年8月14日

浏览器缓存是很重要的,一次交互,有95%以上的时间是在处理前端的,如果能提高前端的性能,对提高整个系统的性能是很有帮助的。本专题主要讲的是如何更好地使用浏览器缓存,同时包括了一些今后浏览器缓存的发展趋势,如:globalStorage等。

影响浏览器本地缓存的因素及解决方案

因素:子域名

具体描述:berg.sharej.com/img/123.gif 这个图片,如果按照 sharej.com/berg/img/123.gif这样的方式访问,需要重新加载一次。类似的,大小写不同也会造成重复下载
解决办法:统一使用一个地址可避免重复下载。

因素:Meta头

具体描述:<META HTTP-EQUIV=”Pragma” CONTENT=”no-cache”>或者使用脚本输出了要求浏览器不缓存网页的header
解决方案:合理的按照需求使用。

因素:Firefox的cache机制

具体描述:即使是应用了no-cache 头,firefox还是要先cache ,再根据过期设定决定是否使用。via
解决方案:一般无需解决。因为firefox缓存这些文件只是用作前进/后退。

因素:随机文件名

具体描述:可使用abc.js? 2007120来使浏览器重新加载js文件。一种更安全的方是abc_v071201.js来使浏览器重加载(可通过地址重写实现)。
解决方案:在js、css文件升级后,必要时可进行此处理,避免用户浏览器缓存的旧的文件。

因素:innerHTML

具体描述:IE6在window.onload中用innerHTML动态插入图片的时候会忽略Cache策略,一次加载多张相同图片时,会重复请求。
解决方案:避免在window.onload中使用innerHTML插入图片。

因素:IE6无法缓存背景图片的bug

具体描述:IE6的 ““temporay internet files”设置为“每次访问此页时检查”时, 背景图片将无法被缓存,在鼠标滑过链接背景图片更换时,会产生闪烁。
解决方案:document.execCommand(”BackgroundImageCache”, false, true);在ie6下执行这条语句即可,Firefox执行时会报错(可用try-cache解决)。用expression也可以达到这个效果最好是用CSS Sprites解决问题。

在浏览器端预先缓存图片的实现

使用Image()对象缓存

使用JavaScript新建一个新的Image()对象,然后将希望预装载的图片URL传递给此对象。通过onLoad()事件句柄同步装载到页面上。demo

通过数组(arrays)缓存多个图片

定义了变量i以及名为imageObj的Image()对象。然后定义了新数组images[],每一个数组元素将存储需要预装载图片的地址来源。最后,使用一个for()循环来遍历整个数组,并对每个元素指定Image()对象,以此将图片都预装载到缓存中。
demo

上面这两种方法都需要浏览器支持javascript才能正常缓存。

使用CSS隐藏需要缓存的图片

采用css的display:none;属性来隐藏图片。
demo

使用css中的背景图片

可以为一个元素定义背景样式,然后将背景图片移到不可见的位置。IE6在““temporay internet files”设置为“每次访问此页时检查”时无效。
demo
上面这两种方法都需要浏览器正常解释css才能正常使用

相册中图片的预加载

上面提到了四种预先缓存图片的方法,个人感觉第二种方法最好。因为使用第二种方法可以方便的控制加载的时间,不会影响之前页面的打开速度,而且只要支持js的浏览器都能正常使用。
demo
这个例子比较简单,但是已经能实现预加载了,在打开缩略图页面时,只要开启了缓存的浏览器,大图就会在页面结束后逐一被载入。但是一些具体的加载策略还没有做考虑。

鼠标滑过背景图的切换

如前所述,IE6的 “temporay internet files”设置为“每次访问此页时检查”时, 背景图片将无法被缓存,在鼠标滑过链接时(不管是否有背景图切换),会产生闪烁。其他浏览器都能很好的通过超链接的hover来设置背景图片实现鼠标滑过,背景图切换。

IE6闪烁的原因

首先总结ie6中发生闪烁的原因,最后给出一个解决方案。

定义一个这样的样式:
.Example a{
background-image:url(some image);
}
下面是所有会引发闪烁的原因:

Background

当此元素background被设置成以下的值时,会发生闪烁:
background-color: transparent
background-repeat: repeat
background-position: 只要设置了都会闪烁

元素的面积

需要这个元素不闪烁,这个元素的面积必须要大于2500px^2。 =。=
.example a {
width: 50px;
height: 50px;
background-image:url(some image);
}

.example a {
width: 50px;
height: 40px;
background-image:url(some image);
}
上面一个样式不会闪烁而下面一个样式会闪烁……

图片是否透明gif

当背景图片是一个带透明效果gif时,会闪烁。

跨浏览器的解决办法

try {
document.execCommand(’BackgroundImageCache’, false, true);
} catch(e) {}

a{ background:transparent url(logo.gif) no-repeat scroll left bottom;line-height:300px;padding:30px;}
a:hover{ background-position:-2000px 100%;}

 

其中logo为一个包含原图和翻转图片的大图片。在IE6,IE7,firefox2.0,opear9下测试通过

IE中的userdata的使用

Cookies也能达到在客户端缓存数据的作用,但是cookies的大小限制很严格(4K),所以不能用来缓存过多的用户数据, userdata的出现解决了这个问题。每个网页的UserData存储区数据大小可以达到64 Kb,每个域名可以达到640 Kb。
IE 5以上的IE浏览器才支持userdata这个行为。在用户机器上,userdata默认是存储在这个位置:C:Documents and Settingsyour login nameApplication DataMicrosoftInternet ExplorerUserData
userData行为通过sessions为每个对象分配UserData存储区。使用save和load方法将UserData存储区数据保存在缓存 (cache)中。一旦UserData存储区保存以后,即使IE浏览器关闭或者刷新了,下一次进入该页面,数据也能够重新载入而不会丢失。
在HTML、HEAD、TITLE和STYLE标记上应用了userData行为后使用save和load方法将会出错。

使用前,必须先声明样式:

.userData {behavior:url(#default#userdata);}

或者使用脚本绑定:
object.style.behavior = “url(’#default#userData’)”
object.addBehavior (”#default#userData”)

csdn中列有userdata成员和方法表。

demo

Userdata 的作用域问题

当我在/forum/a这个页面中执行一次u.Save(”sss”, “just a forum”, 365, “forum”);后,userdata的目录下出现了一个sss[1].xml文件,内容是:

同时,在/forum/b这个页面中执行alert(u.Load(”sss”, “forum”));时,能够取到userdata中的内容。 而在“/”这个页面中是取不到刚才存放进去的内容的,同样的,在“/topic/1234”也是取不到内容的。
类似的,执行u.Save(”forum”, “just a forum”, 365, “value”);后再alert的结果和上面的结果相同。
个人觉得userdata和cookies一样,是和path相关的。同一目录下的所有页面能共享同一个文件中的同一属性(Attribute)。因此在使用的时候要注意目录结构的问题

Userdata的超时设置

Expires这个属性是用来设置userdata的超时时间的。Userdata的超时设置是针对一个文件的,一旦过期,整个文件都过期了,不能单独设置每个属性的过期时间。

其他问题

如果 userdata被人为删除,此时执行o.getAttribute()、o. setAttribute()会报错:“Error:数据无效。”在使用这两个方法之前, try-catch o.load()可以屏蔽这个错误,但是userdata就无法正常使用了,除非修改存储的文件名。

删除userdata的时候不能像删除cookie一样,用new Date(0)来制造过期时间。315532799000 是格林威治时间1979年12月31日23时59分59秒。这是删除UserData的最靠前的一个有效expires时间了。

如果在一个浏览器进程中重复删除、写入userdata数据,userdata空间将很快被撑满,因为每次删除都是逻辑删除,等到浏览器进程结束后才会真正执行删除操作。

非IE浏览器“userdata”的解决方案

sessionStorage

从firefox 2.0开始,开始支持HTML5,同时也就支持了sessionStorage,这是一个只能在session生命周期内使用的对象,最大的用途在于用于保存一些临时的数据防止用户意外刷新页面,同时,在浏览器意外关闭并恢复页面时,sessionStrorage中存储的信息也会被同时恢复。Firefox默认允许一个域名存储5120KB的数据。
demo(必须要上传到服务器上才能正常运行)

下面是HTML5定义的接口:
interface Storage {
readonly attribute unsigned long length;
DOMString key(in unsigned long index);
DOMString getItem(in DOMString key);
void setItem(in DOMString key, in DOMString data);
void removeItem(in DOMString key);
};

作用域问题

Firefox中的sessionStorage在域名下任意页面存储后,整个域名下都可以使用存储的项目。

其他问题

在浏览器crash后,restore页面的session也不见了,(firefox2.0) 。

globalStorage

这个也是html5中提出来,在浏览器关闭以后,使用globalStorage存储的信息仍能够保留下来,并且存储容量比IE的userdata大得多,一个域下面是5120k。和sessionStorage一样,域中任何一个页面存储的信息都能被所有的页面共享。

作用域

globalStorage['z.baidu.com'] 所有z.baidu.com下面的页面都可以使用这块空间
globalStorage['baidu.com'] 所有baidu.com下面的页面都可以使用这块空间
globalStorage['com']:所有com域名都可以 共享的使用这一块空间
globalStorage[''] :所有页面都可以使用的空间

现在Firefox只支持当前域下的globalStorage存储, 如果使用公用域会导致一个这样一个类似的错误“Security error” code: “1000”。

过期时间

按照HTML5的描述,globalStorage只在安全问题或者当用户要求时才会过期,浏览器应该避免删除那些正在被脚本访问的数据,并且userdata应该是用户可写的。

因此我们的脚本要能够控制过期时间,可以在globalStorage的某个区域存储过期时间,在load的时候判断是否过期,可以在一定程度上解决过期时间的问题。

存储时,同时存储过期时间
Save = function(content, expires, attribute, fileName){
var date = new Date();
date.setSeconds(date.getSeconds() + expires);
globalStorage[domain][fileName + "__expires"] = date.getTime();
}
Load时判断是否过期,过期则删除:
Load = function(attribute, fileName){
var date = new Date();
if(parseInt(globalStorage[domain][fileName + "__expires"]) < parseInt(date.getTime()) ){
d.Remove(attribute, fileName);
d.Remove(attribute, fileName + “__expires”);
}
return globalStorage[domain][fileName + attribute];
}

一个客户端缓存的实例

sharej最近会推出一项功能,里面将用到大量的客户端缓存,等待一阵吧!工作比较忙,晚上回家已经没多少时间可以做了 :(

参考资料

DOM Storage Answers: http://ejohn.org/blog/dom-storage-answers/
DOM Storage:http://ejohn.org/blog/dom-storage/
Mozilla developer center:http://ejohn.org/blog/dom-storage/
Minimize Flickering CSS Background Images in IE6:http://ejohn.org/blog/dom-storage/

posted @ 2008-08-14 11:41 颜斌 阅读(37) | 评论 (0)编辑
  2008年8月12日
Code

  

posted @ 2008-08-12 09:04 颜斌 阅读(9) | 评论 (0)编辑
  2008年8月1日
     摘要: 温故知新 javascript 正则表达式 很长时间没看 正则表达式了,碰巧今天用到,温故知新了一把 看书学习吧50% 的举一反三练习中的原创。一 javascript正则表达式的基本知识1 javascript 正则对象创建 和用法 声明javascript 正则表达式 var reCat = new RegExp("cat");你也可以var reCat = /cat/; //Perl ... 阅读全文
posted @ 2008-08-01 18:59 颜斌 阅读(10) | 评论 (0)编辑
  2008年7月31日
function correctPNG() // correctly handle PNG transparency in Win IE 5.5 & 6.
{
   
var arVersion = navigator.appVersion.split("MSIE")
   
var version = parseFloat(arVersion[1])
   
if ((version >= 5.5&& (document.body.filters)) 
   {
      
for(var j=0; j<document.images.length; j++)
      {
         
var img = document.images[j]
         
var imgName = img.src.toUpperCase()
         
if (imgName.substring(imgName.length-3, imgName.length) == "PNG")
         {
            
var imgID = (img.id) ? "id='" + img.id + "" : ""
            
var imgClass = (img.className) ? "class='" + img.className + "" : ""
            
var imgTitle = (img.title) ? "title='" + img.title + "" : "title='" + img.alt + ""
            
var imgStyle = "display:inline-block;" + img.style.cssText 
            
if (img.align == "left") imgStyle = "float:left;" + imgStyle
            
if (img.align == "right") imgStyle = "float:right;" + imgStyle
            
if (img.parentElement.href) imgStyle = "cursor:hand;" + imgStyle
            
var strNewHTML = "<span " + imgID + imgClass + imgTitle
            
+ " style=\"" + "width:" + img.width + "px; height:" + img.height + "px;" + imgStyle + ";"
            + 
"filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
            + 
"(src=\'" + img.src + "\', sizingMethod='scale');\"></span>" 
            img.outerHTML 
= strNewHTML
            j 
= j-1
         }
      }
   }    
}
posted @ 2008-07-31 16:17 颜斌 阅读(20) | 评论 (0)编辑
  2008年7月21日

C#实现动态分配IP和释放IP

最近在做一个东西,要用到动态分配IP和释放IP。在C++下很容易就可以实现。但是由于因为网络IP设置是要涉及到硬件,C#是没有现成接口调用的.只能通过调用API或者是WMI这道系统提供给我们的桥梁.主要是通过"Win32_NetworkAdapterConfiguration"这个管理类。

下面附上我写的一个Demo,希望对需要的朋友有帮助,更希望高手来拍砖。

using System;
using System.Collections.Generic;
using System.Text;
using System.Management;
using System.Management.Instrumentation;
using System.Collections;

namespace J_Queen
{
    class Program
    {
        static void Main(string[] args)
        {
            Dictionary<string, ManagementObject> allDevices = new Dictionary<string, ManagementObject>();   //保存管理对象
            List<string> listDescription = new List<string>(); //保存网卡描述

            //获得管理类实例和管理对象
            ManagementClass classInstance = new ManagementClass( "Win32_NetworkAdapterConfiguration" );
            ManagementObjectCollection bjectCollection = classInstance.GetInstances();

            foreach (ManagementObject obj in objectCollection)
            {
                //如果没有启用IP设置的网络设备则跳过
                if (!(bool)obj[ "IPEnabled" ])
                {
                    continue;
                }

               //存储相关信息
                allDevices.Add((string)obj[ "Description" ], obj);
                listDescription.Add((string)obj[ "Description" ]);
            }
            for (int i = 0; i < listDescription.Count;i++ )
            {
                Console.WriteLine(i.ToString() + ": " + listDescription[i]);
            }
            Console.Write( "输入上面的数字编号(q:退出),选择网卡:" );
            string xInput = Console.ReadLine();
            int deviceNumber;
            while (xInput != "q" )
            {
                if(!Int32.TryParse(xInput, out deviceNumber))
                {
                    Console.Write( "输入错误,重新输入: " );
                    xInput=Console.ReadLine();
                    continue;
                }
                if (deviceNumber>listDescription.Count-1 || deviceNumber<0)
                {
                    Console.Write( "输入的编号超出范围,重新输入: " );
                    xInput=Console.ReadLine();
                    continue;
                }
                if (allDevices.ContainsKey(listDescription[deviceNumber]))
                {
                    Console.WriteLine( "1:表示释放IP(Release),2:表示重新获得IP(Renew)" );
                    string ptionInput = Console.ReadLine();
                    int option;
                    if(Int32.TryParse(optionInput, out option))
                    {
                        if(option ==1)
                        {
                            int returnValue = IpRelease((ManagementObject)allDevices[listDescription[deviceNumber]]);
                            if (returnValue<2)
                            {
                                Console.WriteLine( "成功释放IP" );
                                Console.Write( "输入上面网卡的数字编号(q:退出),选择网卡:" );
                                xInput=Console.ReadLine();
                                continue;
                            }
                        }
                        else if (option == 2)
                        {
                            int returnValue = IpRenew((ManagementObject)allDevices[listDescription[option]]);
                            if (returnValue<2)
                            {
                                Console.WriteLine( "成功分配IP" );
                                Console.Write( "输入上面网卡的数字编号(q:退出),选择网卡:" );
                                xInput = Console.ReadLine();
                                continue;
                            }
                        }
                        else
                        {
                            Console.WriteLine( "选择有误" );
                            Console.Write( "输入上面网卡的数字编号(q:退出),选择网卡:" );
                            Console.ReadLine();
                            continue;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// Function:重新分配指定网卡的IP
        /// </summary>
        /// <param name="obj">ManagementObject obj --对应网卡的管理对象</param>
        /// <returns>返回值,整数,0和1表示成功
</returns>
        public static int IpRenew(ManagementObject obj)
        {
            ManagementBaseObject utPar = null;
            utPar = obj.InvokeMethod( "RenewDHCPLease" , null, null);
            return Convert.ToInt32(outPar[ "returnValue" ]);
        }
        /// <summary>
        /// Function:释放指定网卡IP
        /// </summary>
        /// <param name="obj">ManagementObject obj--对应网卡的管理对象</param>
        /// <returns>返回值,整数,0和1表示成功
</returns>
        public static int IpRelease(ManagementObject obj)
        {
            ManagementBaseObject utPar = null;
            utPar = obj.InvokeMethod( "ReleaseDHCPLease" , null, null);
            return Convert.ToInt32(outPar[ "returnValue" ] );
        }
    }
}

posted @ 2008-07-20 11:25 J_Queen Lau 阅读(751) 评论(2)  编辑 收藏
posted @ 2008-07-21 09:31 颜斌 阅读(12) | 评论 (0)编辑