【C#】WinForm 之 SQL Server 服务监控器(避免开机启动服务)

由于刚刚开始写博客加上最近人又懒,很多过去的项目都没时间去整理,先把以前写过的一个小工具发上来吧。


关于MS-SQL服务优化

安装过MS-SQL Server的人应该知道,系统会因此多出4、5项新的服务

  • SQL Active Directory Helper 服务
  • SQL Server (SQLEXPRESS)  这个是Visual Studio自带的,单独安装过数据库管理工具的数据库名字会不同
  • SQL Server Browser
  • SQL Server VSS Writer
  • SQL Server 代理 (SQLEXPRESS)  SQLEXPRESS数据库为Visual Studio平台自带

记得当初学习数据库这门课的时候,小伙伴们为了安装一个Microsoft SQL Server 2008可谓是历尽磨难。然而除了平白占用几个G的磁盘空间外,最最不能让人接受的就是多出的这一串服务,以致开机时间立马翻了一番。

为了优化开机服务,我尝试着讲这些服务一一禁用,最后得出

  • 如果需要连接至数据库, SQL Server (SQLEXPRESS) 服务必须开启;
  • 如果不知道本地服务器名与数据库连接地址时,保持SQL Server Browser 服务开启可以让VS平台自动列举,方便手动绑定。

因此本着尽可能加快开机速度并消除DBMS带来的负面影响,我只保留了唯一的服务SQL Server ,禁用了其余服务项。

然而一次无意中连接失败让我发现了其中存在的巨大安全隐患。当时我在查看日志文件(可以参考这个路径 C:\Program Files\Microsoft SQL Server\MSSQL10.SQLEXPRESS\MSSQL\Log),发现其中2Mb多的错误警告文件里密密麻麻的异地IP登陆失败记录,而我的数据库只是用于本地的SQL学习完全不可能有远程访问,也就是说在开启服务期间电脑曾经被攻击!!而我们要知道的是在windows的环境下整个操作系统也是数据库的一部分,遭遇入侵不只是自己建立的数据库,攻击者甚至可以通过登陆服务器控制整个主机。当时自己才意识到网络攻击原来离自己那么近,曾经信誓旦旦的去跟踪那些非法IP,不过这里就不扯远了(关于网络安全问题今后有时间再进行整理吧)。

自从那次经历后,自己也再不敢放着SQL服务长期开启了,而这个小工具也就是那时候写出来的。目的是为了随时启动与关闭SQL服务,避免了每次从任务管理器密密麻麻的服务中寻找这个服务,方便在学习完毕后及时将其关闭。看起来,我还是一如既往的懒哈


功能

言归正传,为了能监控指定的系统服务,并且还要能将服务开启与关闭,C#自然是首选(没办法,我用的是人家windows的系统嘛)。

C# 可以提供 ManagementClass来对机器的信息进行管理,可以通过设定不同的管理类来获得机器的基本信息;

结合 ManagementObjectCollection (用于存储管理对象的集合)、ManagementObject (单个管理对象),我们很快能获得系统的服务并对其进行操作。

此外,为了方便监控,考虑最小化到通知栏进行显示,即使用 System.Windows.Forms.NotifyIcon 控件。



相关代码与界面:

using System;
using System.Management;
using System.Windows.Forms;

namespace Watch
{
    public partial class Form1 : Form
    {
        //创建通知栏点击后的菜单
        ContextMenu notifyContextMenu = new ContextMenu();

        private ManagementClass mc = new ManagementClass("Win32_Service"); //系统管理类里选择Win32服务(不区分64位)
        private ManagementObjectCollection moc; //用于存储系统中的所有服务
        private ManagementObject myService;  //用于选择单个管理对象,即单个服务

        MenuItem m_open; //三个菜单项
        MenuItem m_close;
        MenuItem m_exit;        

        public Form1()
        {
            System.Diagnostics.Process.GetCurrentProcess().MaxWorkingSet = (IntPtr)500000;

            InitializeComponent();
            this.notifyIcon1.Text = "正在监控服务...";
            this.textBox1.Text = "MSSQL$SQLEXPRESS";

            m_open = new MenuItem();
            m_close = new MenuItem();
            m_exit = new MenuItem();

            m_open.Text = "启动服务";
            m_close.Text = "停止服务";
            m_exit.Text = "退出";
            m_open.Click += new EventHandler(m_open_Click);
            m_close.Click += new EventHandler(m_close_Click);
            m_exit.Click += new EventHandler(m_exit_Click);

            notifyContextMenu.MenuItems.Add(m_open);
            notifyContextMenu.MenuItems.Add(m_close);
            notifyContextMenu.MenuItems.Add(m_exit);
            notifyIcon1.ContextMenu = notifyContextMenu;

            getState();
        }

        //关闭指定服务
        void m_close_Click(object sender, EventArgs e)
        {
            if ((bool)myService["AcceptStop"])
            {
                myService.InvokeMethod("StopService", null);
                this.notifyIcon1.Icon = Properties.Resources.close;
            }
            getState();
        }

        //启动指定服务
        void m_open_Click(object sender, EventArgs e)
        {
            if ((string)myService["State"] == "Stopped")
            {
                myService.InvokeMethod("StartService", null);
            }
            else if ((string)myService["State"] == "Paused")
            {
                myService.InvokeMethod("ResumeService", null);
            }
            getState();
        }

        //退出程序
        void m_exit_Click(object sender, EventArgs e)
        {
            this.Dispose();  //释放内存,比第一个好。
            Application.Exit();
        }

        //双击通知栏图标后显示主窗口
        private void notifyIcon1_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            getState();
            if (this.Visible == true)
            {
                this.Hide();
            }
            else
            {
                this.Show();
                this.Activate();
            }
        }

        //获取即时的系统服务信息
        private void getState()
        {
            if (moc != null) //清空历史服务信息
                moc.Dispose();
            moc = mc.GetInstances(); //获取服务列表
            foreach (ManagementObject mo in moc) //查找指定服务
            {
                if ((string)mo["Name"] == this.textBox1.Text)
                {
                    myService = mo;
                    break;
                }
            }

            if ((string)myService["StartMode"] == "Disabled") //判断服务是否被禁用
            {
                this.label1.Text = "Disabled";
                this.notifyIcon1.Icon = Properties.Resources.disabled;
            }
            else if ((string)myService["State"] == "Running") //判断服务是否在运行
            {
                this.notifyIcon1.Icon = Properties.Resources.open;
                m_close.Checked = false;
                m_open.Checked = true;
                this.label1.Text = "Running";
            }
            else if ((string)myService["State"] == "Stopped") //判断服务是否已停止
            {
                this.notifyIcon1.Icon = Properties.Resources.close;
                m_close.Checked = true;
                m_open.Checked = false;
                this.label1.Text = "Stopped";
            }
            else //如果处于中间状态,间隔一段时间后重新获取服务状态
            {
                this.label1.Text = (string)myService["State"];
                System.Threading.Thread.Sleep(500);
                getState();
            }
        }

        //重载系统默认的关闭事件,即点击主窗口的关闭叉叉时不退出程序,仅隐藏窗口(变相实现了最小化到通知栏)
        protected override void WndProc(ref Message m)
        {
            const int WM_SYSCOMMAND = 0x0112;
            const int SC_CLOSE = 0xF060;

            if (m.Msg == WM_SYSCOMMAND && (int)m.WParam == SC_CLOSE)
            {
                // 屏蔽传入的消息事件
                this.Hide();
                return;
            }
            base.WndProc(ref m);
        }

        //为了学习拖动事件,这里增加了一个隐藏的小功能:鼠标在标签处按下时能拖动标签
        private void label2_MouseDown(object sender, MouseEventArgs e)
        {
            this.label2.DoDragDrop(this.label2, DragDropEffects.Move);
        }

        private void textBox1_DragEnter(object sender, DragEventArgs e) //当标签拖入到输入框后鼠标出现拖动标志
        {
            e.Effect = DragDropEffects.Move;
        }

        private void textBox1_DragDrop(object sender, DragEventArgs e) //当拖入的标签在输入框释放后恢复默认的服务名字
        {
            this.textBox1.Text = "MSSQL$SQLEXPRESS";
        }
    }
}

关于“最小化到通知栏”

许多有通知栏图标的应用在关闭主窗口后并没有退出程序,而仅仅是“最小化到通知栏”。

之前代码中就利用重载关闭消息 protected override void WndProc(ref Message m) 实现了这一点。

重写WndProc函数,可以捕捉所有窗口发生的消息。这样,我们就可以"篡改"传入的消息,而人为的让窗口改变行为。

这里再补充一些Windows中常见的消息类型,如下只为部分:

  • WM_NULL = $0000;
  • WM_CREATE = $0001;
    应用程序创建一个窗口
  • WM_DESTROY = $0002;

    一个窗口被销毁

  • WM_MOVE = $0003;

    移动一个窗口

  • WM_SIZE = $0005;

    改变一个窗口的大小

  • WM_ACTIVATE = $0006;

    一个窗口被激活或失去激活状态;

  • WM_SETFOCUS = $0007;

    获得焦点后

  • WM_KILLFOCUS = $0008;

    失去焦点

  • WM_ENABLE = $000A;

    改变enable状态

  • WM_SETREDRAW = $000B;

    设置窗口是否能重画

  • WM_SETTEXT = $000C;

    应用程序发送此消息来设置一个窗口的文本

  • WM_GETTEXT = $000D;

    应用程序发送此消息来复制对应窗口的文本到缓冲区

  • WM_GETTEXTLENGTH = $000E;

    得到与一个窗口有关的文本的长度(不包含空字符)

  • WM_PAINT = $000F;

    要求一个窗口重画自己

  • WM_CLOSE = $0010;

    当一个窗口或应用程序要关闭时发送一个信号

  • WM_QUERYENDSESSION = $0011;

    当用户选择结束对话框或程序自己调用ExitWindows函数

  • WM_QUIT = $0012;

    用来结束程序运行或当程序调用postquitmessage函数

  • WM_QUERYOPEN = $0013;

    当用户窗口恢复以前的大小位置时,把此消息发送给某个图标

  • WM_ERASEBKGND = $0014;

    当窗口背景必须被擦除时(例在窗口改变大小时)

  • WM_SYSCOLORCHANGE = $0015;

    当系统颜色改变时,发送此消息给所有顶级窗口

  • WM_ENDSESSION = $0016;

    当系统进程发出WM_QUERYENDSESSION消息后,此消息发送给应用程序,通知它对话是否结束

完整的消息类型代码见:http://www.cnblogs.com/KC-Mei/p/4334177.html

时间: 2024-08-13 09:58:35

【C#】WinForm 之 SQL Server 服务监控器(避免开机启动服务)的相关文章

SQL Server常用的几种启动方式

各位在公司一般涉猎ORACLE,很少用到sql server,那么今天给大家讲讲sql server常用的启动方式: SQL Server实例分为下面几种启动方法: (1)在Windows服务控制台里手动启动,或者自动启动(默认),这个也是最常用的方式 (2)SQL Server本身自己提供的启动方式,我们这里可以手动启动 (3)在SQL Server的SSMS里面手动启动它,这个方式一般大部分利用这种方式进行手动重启 (4)通过Windows命令窗口,用'net start'命令手动启动,这种

SQL Server快捷方式丢了怎么启动

为了帮助网友解决“SQL Server快捷方式丢了怎么启动”相关的问题,中国学网通过互联网对“SQL Server快捷方式丢了怎么启动”相关的解决方案进行了整理,用户详细问题包括:Microsoft SQL Server\80\Tools\Binn文件夹哪个文件是启动的 ?|,具体解决方案如下: 解决方案1:在所有程序里面肯定有吧 要不就是C:\Program Files\Microsoft SQL Server\80\Tools\Binn 里面的这个文件 sqlmangr.exe 通过对数据库

配置yum仓库安装服务并确保开机启动

实验目标 安装vsftpd,httpd软件包 判断是独立还是临时服务 启动这2个服务 确保开机启动 安装telnet-server,判断是临时还是独立 启动 实验环境 虚拟机 实验步骤 一.环境准备 1. 配置yum仓库 [[email protected] ~]# cd /etc/yum.repos.d/ [[email protected] yum.repos.d]# ls rhel-debuginfo.repo [[email protected] yum.repos.d]# cp rhe

redis加入开机启动服务

我的redis安装的路径是在 /usr/local/redis mkdir /etc/redis #创建文件夹 cp /usr/local/redis/redis.conf /etc/redis/6379.conf  #将redis.conf拷贝到/etc/redis文件夹下 vim /etc/rc.d/init.d/redis #打开编辑器 插入以下内容 #!/bin/sh #chkconfig: 2345 80 90 # Simple Redis init.d script conceive

Ubuntu管理开机启动服务项 -- 图形界面的Boot-up Manager

有时学习时安装的服务太多,比如mysql.mongodb.redis.apache.nginx等等,它们都是默认开机启动的,如果不想让它们开机启动,用到时再自己手工启动怎么办呢? 使用sysv-rc-conf确实是一个不错的选择,但在暂时不了解服务启动的层级细节,又只需要一次过全关掉的情况下,用sysv-rc-conf未免过于繁琐. 好在我们还有图形界面下的工具Boot-up Manager,即bum 1 sudo apt-get install bum 安装之后以root身份运行,就可以直接对

非root用户执行开机启动服务脚 本

一.需求 centos6下面添加开机服务,例如开机启动supervisor服务,然后supervisor会负责拉起配置的进程,从而实现各种服务的开机重启. 二.原理需求 在centos6下面主要通过在/etc/init.d/下面添加服务脚本和chkconfig命令来完成添加启动服务 添加服务的启停脚本如果需要开机启动服务,或者通过service命令控制服务,必须在/etc/init.d/下面有对应服务的启停脚本,如果我们的服务为supervisor,那么在/etc/init.d/下面对应的启停脚

Hortonworks HDP Sandbox定制(配置)开机启动服务(组件)

定制Hortonworks HDP开机启动服务可以这样做:本文原文出处: http://blog.csdn.net/bluishglc/article/details/42109253 严禁任何形式的转载,否则将委托CSDN官方维护权益! 找到文件:/usr/lib/hue/tools/start_scripts/start_deps.mf,Hortonworks HDP启动所有服务和组件的命令都在这个文件中,之所以把这些服务的启动命令写在了一个makefile中而不是一个shell文件,其实就

开机启动服务:chkconfig命令详解

1.查看系统运行级别 # cat /etc/inittab # Default runlevel. The runlevels used are:#   0 - halt (Do NOT set initdefault to this)#   1 - Single user mode#   2 - Multiuser, without NFS (The same as 3, if you do not have networking)#   3 - Full multiuser mode#  

如何自己添加开机启动服务

在centos6如何添加开机启动服务 在centos6中启动某项服务都是用一条service的命令跟服务名来启动关闭(重启),或者查看状态的.只要安装某项服务直接service命令就可以执行三种状态,今天就跟我一起来看看怎么用一个简单的小脚本来用service命令执行它并设置成开机启动! #我实现写好了一个名叫mydeamon的脚本 首先看看我的脚本里都写了些什么: case $1 in [Rr][eE][sS][Tt][aA][Rr][Tt])         re        re调用重启

mysql不能开机启动服务

遇到一件非常郁闷的事情,mysql不能开机启动服务. 用到mysql数据库的时候,需要进入bin目录,手动启动mysqld.exe.非常,非常的不爽. 于是,写了一个小脚本.