吴磊的博客

这个暑期深造C语言
随笔 - 13, 文章 - 0, 评论 - 75, 引用 - 0
数据加载中……

2008年8月26日

做成一件小事,收获一份知识。(续)

现在,回顾我编程的过程,其实主要解决的问题有两个:

1.如何使用基于.net框架的C#调用Windows中的服务,控制服务的启动、停止和启动方式;

2.Vista下的编程

 

最后一个问题其实很简单,但我到现在仍然没有给出一个完美的解决。我编好的程序成功运行,但当我试图去控制一个Windows服务的时候,系统会报错。原因是我没有获得权限,因此无法控制Windows服务。这样的原因在Vista之前是不存在的,Vista使用了用户帐户控制(UAC),因此在访问系统文件和程序的时候需要获得权限才可以正常访问,而用户管理员也必须在访问的时候确认访问才可以。这多多少少和Ubuntu中的sudo有些相似,都是为了系统安全考虑。但是这样如何在编程的时候写入代码呢?我不会。我只是修改了编译好的程序属性。

这样程序只有在作为程序可以运行了,但在IDE中无法编译正常运行。因此我只有选择编译完后,到Debug文件夹中双击ServiceControl程序。感叹自己不懂的东西实在是太多了。

对于第一个问题,到google上和msdn上检索一下相关的技术文章就会发现其实“想要控制Windows服务”其实不是一件难事。对于这个问题,要使用到System.ServiceProcess命名空间极其中的主要使的两个类,一个是ServiceController,另一个是ServiceInstaller。前者实现了Windows服务的控制,后者实现了服务启动类型的控制。

如何控制一个Windows服务?
对于一个Windows服务而言,要想控制它的启动、停止、暂停,要使用ServiceController类。控制一个服务,首先要确定这个服务。一个服务的属性有很多,包括服务所在的服务器,服务名称,服务显示名词,服务描述,服务状态等。通过服务所在服务器和服务显示名称,或者服务所在服务器和服务名称即可确定服务。我用到了前者。在.net中即.MachineName和.DisplayName两个属性,为对象的这另个属性赋值即可确定此对象控制哪个服务。下面先展示一下代码,然后再做说明(窗体见本文章的上一期)。代码如下:

 1using System;
 2using System.Windows.Forms;
 3using System.ServiceProcess;
 4
 5namespace ServiceControl
 6{
 7    public partial class Form1 : Form
 8    {
 9        //用于控制服务的两个类
10        ServiceController sc = new ServiceController();
11        ServiceInstaller si = new ServiceInstaller();
12
13        //构造窗体时加载的代码
14        public Form1()
15        {
16            InitializeComponent();
17            listBox1.SelectedIndex = 0;
18            sc.MachineName = "WULEI-PC";
19            si.DisplayName = sc.DisplayName = listBox1.SelectedItem.ToString();
20            lableText();
21            buttonEnable();
22        }

23
24        //三个lable用于显示服务的显示名称、服务名称和服务状态
25        private void lableText()
26        {
27            label1.Text = sc.DisplayName;
28            label2.Text = sc.ServiceName;
29            label3.Text = sc.Status.ToString();
30        }

31
32        //当服务状态为启动时,只有停止按钮有效;亦则相反。
33        private void buttonEnable()
34        {
35            if (sc.Status == ServiceControllerStatus.Running)
36            {
37                btnStart.Enabled = false;
38                btnStop.Enabled = true;
39            }

40            else
41            {
42                btnStop.Enabled = false;
43                btnStart.Enabled = true;
44            }

45        }

46
47        //启动按钮,启动选定的服务
48        private void btnStart_Click(object sender, EventArgs e)
49        {
50            si.StartType = ServiceStartMode.Manual;
51            sc.Start();
52            sc.WaitForStatus(ServiceControllerStatus.Running);
53            buttonEnable();
54            lableText();
55        }

56        //停止按钮,停止选定的服务
57        private void btnStop_Click(object sender, EventArgs e)
58        {
59            sc.Stop();
60            sc.WaitForStatus(ServiceControllerStatus.Stopped);
61            buttonEnable();
62            lableText();
63        }

64
65        //列表。选中服务,显示相关服务状态
66        private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
67        {
68            si.DisplayName=sc.DisplayName = listBox1.SelectedItem.ToString();
69            lableText();
70            buttonEnable();
71        }

72    }

73}

代码18、19行为对象的MachineName和DisplayName赋值,从而确定服务。这之后才可以启动、暂停或者停止服务(代码51、59行),但是要注意一点的是,如果服务的启动类型为“禁用”,那么此服务将无法直接被启动,首先要将启动类型改为“手动”或者“自动”(代码50行将服务的启动类型改为“手动”)。代码52和60行是一个非常关键的内容,这段两行代码执行结果是等待当前服务状态的更改。如第60行,等待服务停止。这之后才会运行后面的buttonEnable()自定义方法,否则可能服务还没有停止就运行后面的方法了;如果后面的方法需要当前的服务状态作为运行的基础,那么程序会出现错误。

 

总结:
1.调用一个Windows服务首先要确定服务

编程时使用System.ServiceProcess命名空间,通过ServiceController类的MachineName和ServiceName / DisplayName)确定服务,ServiceInstaller使用DisplayName确定服务;

2.控制一个服务之前要确定启动类型不为“禁用”

 

通过ServiceController对象的.start()和.stop()方法启动和停止服务,启动服务之前要确定服务的启动类型不是“禁用”;如果为禁用,要将其修改为“自动”或者“手动”,通过ServiceInstaller对象的StartType属性修改启动类型(赋值要用到枚举ServiceStartMode)。

3.如果修改启动类型的状态后要执行与服务状态相关的代码,须要使用WaitForStatus(参数)(括号中的参数使用枚举ServiceControllerStatus)。


今天为了解决一个小问题,编写了一个小程序,收获了几点小知识,很开心。



posted @ 2008-08-26 20:18 SuperWulei 阅读(1052) | 评论 (4)编辑

做成一件小事,收获一份知识。

我的Inspiron 1420的本本最近风扇转个不停,当初为了安装这个Vista Ultimate版本可是花费了我勤俭节约的550元的人民币换来的4GB内存,就是图个快。可电脑速度也没看到快到哪里去,反而CPU的使用一直是“稳固”在50%以上,硬盘灯也曾不停的闪(与其说是频频的闪倒不如说是一直亮着)。这令我十分不解,一会儿等“Windows任务管理器”跑一跑我再贴张图来,让我们博客园的电脑精英们为我分析分析。

 


 

我用电脑的习惯非常好,安装上了Kapersky7也不经常点击网页上诱人的图片,因此可以排除是病毒或者木马造成的了。我想造成资源如此浪费的原因是Vista系统本身后台程序太多了,我不知道的什么程序和知道的程序都在后台运行(像什么计划任务、系统还原、备份等等还有一些监视程序和日志);另外一个原因就是夏天太热了,CPU吃不消了。当然后者并不是资源浪费的一个原因。

说实在的,有些后台服务其实并不怎么经常用,可能只是偶尔使用某些软件时才会用到。但是Windows本身太傻了 ,他不知道,因此他经常开着这些服务,造成了许多不必要的浪费。我曾深有体会。原来在XP下,我安装了SQL Server和VMare,后台的相关的几个服务经常开着。尽管我没有用到这些软件,可是这些相关的服务却吞噬了我超过100多MB的内存。那个时候,我要到服务中把他们都改为手动,并关闭这些服务。后来软件安装的多了,相关软件对应的服务多了,想启动或者停止的时候找到这些服务就成了比较麻烦的事情。于是,我有了一个想法。我想编写一个程序,这个程序会已向导的方式提示人们关闭或者打开那些服务。我从不会到会的过程就不说了,尝试了许多方法也都失败了,最后放弃了原来的方法和许多设想,采用一种方法做成了程序。

放弃了向导,而采用列表的方式,只要做成了就可以了。

放弃了的想法有:

1.采用向导,最原本的想法;

2.采用自定义类控制,刚开始看《大话设计模式》想练练手;

3.使用XML文件存储指定的这些服务;

4.用列表列出服务器上所有的服务,然后用户选出那些特定的服务以后定制。

 

我估计大家一定认为我是一个笨蛋了,那些问题确实没有太执著得花太多的时间去想,我只是非常着急的为了尽快出成果就做了这么一个程序。如果哪位高手有何指点,我将感激不尽!愿讨论,愿进步。 (继续,我先去吃饭了)

posted @ 2008-08-26 18:32 SuperWulei 阅读(1384) | 评论 (16)编辑

2008年8月4日

折半查找(递归)

其实折半查找的递归方法同迭代方法思路上是一样的,在此不再多说。
 1int binarySearch( const int b[], int searchKey, int low, int high )
 2{
 3    int middle = ( low + high ) / 2;
 4    if ( searchKey == b[ middle ] )
 5        return middle;
 6    else if ( searchKey < b[ middle ] )
 7        return binarySearch( b, searchKey, low, middle - 1 );
 8    else if ( searchKey > b[ middle ] )
 9        return binarySearch( b, searchKey, middle + 1, high );
10    else
11        return -1;
12}


posted @ 2008-08-04 18:26 SuperWulei 阅读(17) | 评论 (0)编辑

线性查找(递归)

不使用递归的线性查找的思想是:从数组的第一个元素开始一一遍历数组,如果找到当前被遍历的值与所查找的值相同,则返回当前数组元素的下标;如果到最后一个数组元素还没有找到,则返回-1。

 

使用递归的思想:

 1int linerSearch(int a[], int key, int size)
 2{  
 3    if ( size > 0 )  
 4    {  
 5        if ( a[ size - 1 ] == key )
 6            return  size - 1//反方向,返回下标  
 7        return linerSearch( a, key, size - 1 );  
 8    }
    
 9    
10    return -1//未找到  
11}



posted @ 2008-08-04 18:02 SuperWulei 阅读(54) | 评论 (0)编辑

回文判断(递归)

(回文)回文是前后两个方向拼写完全相同的字符串。编写一个递归函数isPalindrome来判断回文,如果存储在数组中的字符串是一个回文,则返回1,否则返回0.函数应该忽略字符串中的空格和逗号。
 1int isPalindrome( char array[], int size )
 2{
 3    if ( size <= 1 )
 4        return 1;
 5    if ( array[0== array[ size - 1 ] )
 6    {
 7        return isPalindrome( array + 1, size - 2 );
 8    }

 9        /*
10        忽略数组中的空格和逗号
11        */

12    else
13    {
14        if( ( array[ 0 ] == ' ' || array[ 0 ] == ',' ) &&
15            ( array[ size - 1== ' ' || array[ size - 1 ] == ',' ) )
16        {
17            return isPalindrome( array + 2, size - 2 );
18        }

19        else if( ( array[ 0 ] == ' ' || array[ 0 ] == ',' ) &&
20            !( array[ size - 1== ' ' || array[ size - 1 ] == ',' ) )
21        {
22            return isPalindrome( array + 2, size - 1 );
23        }

24        else if!( array[ 0 ] == ' ' || array[ 0 ] == ',' ) &&
25            ( array[ size - 1== ' ' || array[ size - 1 ] == ',' ) )
26        {
27            return isPalindrome( array + 1, size - 2 );
28        }

29    }

30
31    return 0;    
32}

posted @ 2008-08-04 17:13 SuperWulei 阅读(58) | 评论 (0)编辑

2008年8月3日

几个递归练习

1.反向输出字符串
1void stringReverse( char array[] )
2{
3    if ( array[0== '\0' )
4        return;
5    stringReverse( array + 1 );
6    printf( "%c", array[0] );
7}

2.输出数组
1void printArray( int array[], int size )
2{
3    if( size == 0 )
4        return;
5    printf( "%d ", array[0] );
6    printArray( ++array, --size );
7}

3.查找数组中的最小值
 1int recursiveMinimum( int array[], int size )
 2{
 3    if ( size == 1 )
 4        return array[0];
 5
 6    if ( array[ size - 1 ] < recursiveMinimum( array, size-1 ) )
 7        return array[ size - 1 ];
 8    else
 9        return recursiveMinimum( array, size-1 );
10}

4.选择排序
选择排序:从数组中查找最小的值,将其同数组中的第一个元素交换,然后从第二个元素开始查找最小的值同数组第二个元素交换,这样重复一直到只剩最后一个元素为止。
 1void selectionSort( int list[], int n, int start)
 2{
 3    {   
 4        int i;   
 5        int p = start;   
 6        if ( start < n - 1 )   
 7        {       
 8            for ( i = start; i < n; i++ )   
 9            {
10                if ( list[i] < list[p] )   
11                    p = i;  
12            }

13            i = list[ p ];   
14            list [ p ] = list[ start ];   
15            list[ start ] = i;   
16            selectionSort( list , n , start+1 );   
17        }
   
18    }
   
19}
5.线性查找
 1int linerSearch(int a[], int key, int size)
 2{  
 3    if ( size > 0 )  
 4    {  
 5        if ( a[ size - 1 ] == key )
 6            return  size - 1//反方向,返回下标  
 7        return linerSearch( a, key, size - 1 );  
 8    }
    
 9    
10    return -1//未找到  
11}
 

posted @ 2008-08-03 12:29 SuperWulei 阅读(86) | 评论 (4)编辑

2008年7月23日

海龟图形,终于被我征服!(二)

     摘要: 控制面板比较容易,使用while和switch语句就可以解决了,It's too easy.但是如何控制海龟就成了难点和重点,只要这个一旦解决,所有的问题就将迎刃而解。 首先需要一个函数用于输出当笔在海龟下时的轨迹:在数组floor[50][50]中,首先将二维数组初始化为0。如果海龟走过,就将走过的数组元素修改为1,当然这不是此函数的功能。此函数只是输出值为1的元素。[代码]最关键的问题是,如何... 阅读全文

posted @ 2008-07-23 19:50 SuperWulei 阅读(433) | 评论 (0)编辑

海龟图形,终于被我征服!(一)

这个暑期一定要好好温习、巩固、深化C语言,课程中的概念学起来很简单,但是真正做起题来困难重重。曾经我的中学老师从四中考察回来对我们说过,看咱们班同学和他们四中的同学课堂反应没有什么区别,我甚至还觉得咱们班同学比四中的同学在课堂上更聪明。可是人家的升学率为什么比我们高,为什么人家的考试成绩比我们高?因为人家在课后用的功比咱们同学们要多,人家做的题比咱们多。所以学C语言也是一样,想要掌握它,光学不练是不行的。

目前,我学习到了二维数组。现在再做练习题,一道“海龟”的题难住了我,困扰了我三天。终于,今天我灵感来了,解决掉了这道难题。

题目:

 

刚刚看到这道题我真是晕了,无从下手。

间断分析了几天后,终于有了结果。分析见(二)。

posted @ 2008-07-23 19:05 SuperWulei 阅读(639) | 评论 (0)编辑

2008年7月16日

一道求质数的题,不同的算法体现不同的程序性能。

输出1~10000之间素数,编写一个返回是否为质数的程序。

1.用时最长的函数 在2.0GB处理器的运算时间 >19s。
这个性能最差,编写者认为循环测试需要被测试n/2 - 1次。可见没有基本数学知识的掌握,在编写代码时是多么可怕,19s啊!
Code