原文地址:http://www.cnblogs.com/BoyXiao/archive/2011/03/31/2001535.html

回忆刚进公司那会儿,手头的第一个工作就是完成虚拟键盘,也就是通过驱动程序向键盘端口写入数据,

这份活至今记忆犹新,那会儿写的是个过滤驱动程序,也就是将我的虚拟设备绑定到真实的键盘设备上,

当驱动程序编译完成以后,我也总是通过下面的这个工具来安装驱动程序,

每编译好一次就使用这个工具重新安装驱动一次,然后通过 DbgView 来打印消息,

那会儿还真傻,为了弄出这么个虚拟键盘,都不晓得安装了驱动多少回,

直到后来,当驱动程序完成以后,就需要部署驱动程序了,在网上找了很多资料,

大部分也都是通过 INF 文件来实现,而对于 WDM 驱动程序,则还可以通过服务控制台来实现安装,

模模糊糊还记得当初就是通过这个服务控制台来实现驱动程序服务的安装的。

当初的实现是这样的,通过编写一个 DLL 来调用服务控制台 API 从而完成驱动程序的安装,

然后再在 C# (应用程序是使用的 C# WinForm ,驱动程序必须和这个应用程序通信)中通过平台调用,

访问这个 DLL ,这样就可以实现驱动程序的动态加载以及动态启动服务和停止服务等等操作了。

而在下面呢,我也算是对以前写的那个 DLL 做一个总结,将其总结为一个 C# 类,这样以后用起来会更加方便。

整个的类,我按分层的思想将其分为三块(其实这里将其这样划分不是非常合适):

DriverEntity.cs

这里即是所谓的实体层,在该类下面呢,主要包括的是将要在 DriverBLL 中使用到的一些常量数据,

这些数据呢包括服务的类型,服务启动类型,当然也包括了将会使用到的一些结构类型等等信息。

using System;
using System.Runtime.InteropServices;
 
namespace TaskManager.Entity
{
    public class DriverEntity
    {
        // Service Types (Bit Mask)
        public static readonly UInt32 SERVICE_KERNEL_DRIVER          = 0x00000001;
        public static readonly UInt32 SERVICE_FILE_SYSTEM_DRIVER     = 0x00000002;
        public static readonly UInt32 SERVICE_ADAPTER                = 0x00000004;
        public static readonly UInt32 SERVICE_RECOGNIZER_DRIVER      = 0x00000008;
        public static readonly UInt32 SERVICE_WIN32_OWN_PROCESS      = 0x00000010;
        public static readonly UInt32 SERVICE_WIN32_SHARE_PROCESS    = 0x00000020;
        public static readonly UInt32 SERVICE_INTERACTIVE_PROCESS    = 0x00000100;
        public static readonly UInt32 SERVICE_WIN32                  = 
            SERVICE_WIN32_OWN_PROCESS | SERVICE_WIN32_SHARE_PROCESS;
 
        public static readonly UInt32 SERVICE_DRIVER                 = 
            SERVICE_KERNEL_DRIVER | SERVICE_FILE_SYSTEM_DRIVER | SERVICE_RECOGNIZER_DRIVER;
 
        public static readonly UInt32 SERVICE_TYPE_ALL               = 
            SERVICE_WIN32 | SERVICE_ADAPTER | SERVICE_DRIVER | SERVICE_INTERACTIVE_PROCESS;
 
        // Start Type
        public static readonly UInt32 SERVICE_BOOT_START            = 0x00000000;
        public static readonly UInt32 SERVICE_SYSTEM_START          = 0x00000001;
        public static readonly UInt32 SERVICE_AUTO_START            = 0x00000002;
        public static readonly UInt32 SERVICE_DEMAND_START          = 0x00000003;
        public static readonly UInt32 SERVICE_DISABLED              = 0x00000004;
 
        // Error control type
        public static readonly UInt32 SERVICE_ERROR_IGNORE          = 0x00000000;
        public static readonly UInt32 SERVICE_ERROR_NORMAL          = 0x00000001;
        public static readonly UInt32 SERVICE_ERROR_SEVERE          = 0x00000002;
        public static readonly UInt32 SERVICE_ERROR_CRITICAL        = 0x00000003;
 
        // Controls
        public static readonly UInt32 SERVICE_CONTROL_STOP          = 0x00000001;
        public static readonly UInt32 SERVICE_CONTROL_PAUSE         = 0x00000002;
        public static readonly UInt32 SERVICE_CONTROL_CONTINUE      = 0x00000003;
        public static readonly UInt32 SERVICE_CONTROL_INTERROGATE   = 0x00000004;
        public static readonly UInt32 SERVICE_CONTROL_SHUTDOWN      = 0x00000005;
 
        // Service object specific access type
        public static readonly UInt32 SERVICE_QUERY_CONFIG          = 0x0001;
        public static readonly UInt32 SERVICE_CHANGE_CONFIG         = 0x0002;
        public static readonly UInt32 SERVICE_QUERY_STATUS          = 0x0004;
        public static readonly UInt32 SERVICE_ENUMERATE_DEPENDENTS  = 0x0008;
        public static readonly UInt32 SERVICE_START                 = 0x0010;
        public static readonly UInt32 SERVICE_STOP                  = 0x0020;
 
        public static readonly UInt32 SERVICE_ALL_ACCESS            = 0xF01FF;
 
        // Service Control Manager object specific access types
        public static readonly UInt32 SC_MANAGER_ALL_ACCESS         = 0xF003F;
        public static readonly UInt32 SC_MANAGER_CREATE_SERVICE     = 0x0002;
        public static readonly UInt32 SC_MANAGER_CONNECT            = 0x0001;
        public static readonly UInt32 SC_MANAGER_ENUMERATE_SERVICE  = 0x0004;
        public static readonly UInt32 SC_MANAGER_LOCK               = 0x0008;
        public static readonly UInt32 SC_MANAGER_MODIFY_BOOT_CONFIG = 0x0020;
        public static readonly UInt32 SC_MANAGER_QUERY_LOCK_STATUS  = 0x0010;
 
        // These are the generic rights.
        public static readonly UInt32 GENERIC_READ                  = 0x80000000;
        public static readonly UInt32 GENERIC_WRITE                 = 0x40000000;
        public static readonly UInt32 GENERIC_EXECUTE               = 0x20000000;
        public static readonly UInt32 GENERIC_ALL                   = 0x10000000;
 
        //Driver Device Name
        public static readonly String TaskManager_Driver_Nt_Device_Name     = "\\Device\\TaskManagerDevice";
        public static readonly String TaskManager_Driver_Dos_Device_Name    = "\\DosDevices\\TaskManagerDevice";
 
 
 
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct SECURITY_ATTRIBUTES
        {
            public UInt32 nLength;
            public IntPtr lpSecurityDescriptor;
            public bool bInheritHandle;
        }
 
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct OVERLAPPED
        {
            public UInt32 Internal;
            public UInt32 InternalHigh;
            public UInt32 Offset;
            public UInt32 OffsetHigh;
            public IntPtr hEvent;
        }
 
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public struct SERVICE_STATUS
        {
            public UInt32 dwServiceType;
            public UInt32 dwCurrentState;
            public UInt32 dwControlsAccepted;
            public UInt32 dwWin32ExitCode;
            public UInt32 dwServiceSpecificExitCode;
            public UInt32 dwCheckPoint;
            public UInt32 dwWaitHint;
        }
    }
} 

DriverDAL.cs

这个类即是所谓的数据访问层,

一般来说,数据访问层用在使用数据库的情况下比较合适,

但是在这里我将其抽象为只要是提供最基本的数据服务的 API ,我都将其放在数据访问层中,

所以这里主要是 C# 平台调用时,对于将要调用的 Win32 API 的一个声明,

其中包括了 CreateFile ,OpenService 等等 API 的声明。

                     

using System;
using System.Runtime.InteropServices;
using TaskManager.Entity;
 
namespace TaskManager.DAL
{
    public class DriverDAL
    {
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr CreateFile(
            String lpFileName, 
            UInt32 dwDesiredAccess, 
            UInt32 dwShareMode, 
            ref DriverEntity.SECURITY_ATTRIBUTES lpSecurityAttributes, 
            UInt32 dwCreationDisposition, 
            UInt32 dwFlagsAndAttributes, 
            IntPtr hTemplateFile
            );
 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool WriteFile(
            IntPtr hFile, 
            byte[] lpBuffer, 
            UInt32 nNumberOfBytesToWrite, 
            ref UInt32 lpNumberOfBytesWritten, 
            ref DriverEntity.OVERLAPPED lpOverlapped
            );
 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool DeviceIoControl(
            IntPtr hDevice, 
            UInt32 dwIoControlCode, 
            byte[] lpInBuffer, 
            UInt32 nInBufferSize, 
            byte[] lpOutBuffer, 
            UInt32 nOutBufferSize, 
            ref UInt32 lpBytesReturned, 
            ref DriverEntity.OVERLAPPED lpOverlapped
            );
 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern bool CloseHandle(
            IntPtr hObject
            );
 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr CreateEvent(
            ref DriverEntity.SECURITY_ATTRIBUTES lpEventAttributes, 
            bool bManualReset, 
            bool bInitialState, 
            String lpName
            );
 
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
        public static extern UInt32 WaitForSingleObject(
            IntPtr hHandle, 
            UInt32 dwMilliseconds
            );
 
        [DllImport("kernel32.dll")]
        public static extern UInt32 GetLastError();  
 
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr OpenSCManager(
            String lpMachineName, 
            String lpDatabaseName, 
            UInt32 dwDesiredAccess
            );
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr CreateService(
            IntPtr hSCManager, 
            String lpServiceName, 
            String lpDisplayName, 
            UInt32 dwDesiredAccess, 
            UInt32 dwServiceType, 
            UInt32 dwStartType, 
            UInt32 dwErrorControl, 
            String lpBinaryPathName, 
            String lpLoadOrderGroup, 
            ref UInt32 lpdwTagId,
            String lpDependencies, 
            String lpServiceStartName, 
            String lpPassword
            );
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern bool CloseServiceHandle(
            IntPtr hSCObject
            );
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern bool StartService(
            IntPtr hService, 
            UInt32 dwNumServiceArgs, 
            String lpServiceArgVectors
            );
 
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr OpenService(
            IntPtr hSCManager, 
            String lpServiceName, 
            UInt32 dwDesiredAccess
            );
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern bool DeleteService(
            IntPtr hService
            );
 
        [DllImport("advapi32.dll", CharSet = CharSet.Auto)]
        public static extern bool ControlService(
            IntPtr hService, 
            UInt32 dwControl, 
            ref DriverEntity.SERVICE_STATUS lpServiceStatus
            );
    }
}

DriverBLL.cs

这里就是所谓的业务逻辑层了,其实呢,说白了,其中包括几个重要的方法的实现,

比如启动驱动程序服务,停止驱动程序服务,安装启动程序,卸载驱动程序等方法的实现。

该类是为应用程序提供驱动程序安装功能的直接类。

                  

using System;
using TaskManager.Entity;
using TaskManager.DAL;
 
namespace TaskManager.BLL
{
    public class DriverBLL
    {
        /// <summary>
        /// 启动驱动程序
        /// </summary>
        /// <param name="svcName"></param>
        /// <returns></returns>
        public bool StartDriver(String svcName)
        {
            IntPtr scManagerHandle;
            IntPtr schDriverService;
 
            //打开服务控制台管理器
            scManagerHandle = DriverDAL.OpenSCManager(null, null, DriverEntity.SC_MANAGER_CREATE_SERVICE);
            if (null == scManagerHandle || IntPtr.Zero == scManagerHandle)
            {
                return false;
            }
 
            //打开服务
            schDriverService = DriverDAL.OpenService(scManagerHandle, svcName, DriverEntity.SERVICE_ALL_ACCESS);
            if (null == schDriverService || IntPtr.Zero == schDriverService)
            {
                DriverDAL.CloseServiceHandle(scManagerHandle);
                return false;
            }
 
            if (false == DriverDAL.StartService(schDriverService, 0, null))
            {
                DriverDAL.CloseServiceHandle(schDriverService);
                DriverDAL.CloseServiceHandle(scManagerHandle);
                return false;
            }
 
            DriverDAL.CloseServiceHandle(schDriverService);
            DriverDAL.CloseServiceHandle(scManagerHandle);
 
            return true;
        }
 
 
        /// <summary>
        /// 停止驱动程序服务
        /// </summary>
        /// <param name="svcName"></param>
        /// <returns></returns>
        public bool StopDriver(String svcName)
        {
            IntPtr scManagerHandle;
            IntPtr schDriverService;
 
            DriverEntity.SERVICE_STATUS serviceStatus;
 
            //打开服务控制台管理器
            scManagerHandle = DriverDAL.OpenSCManager(null, null, DriverEntity.SC_MANAGER_CREATE_SERVICE);
            if (null == scManagerHandle || IntPtr.Zero == scManagerHandle)
            {
                return false;
            }
 
            //打开服务
            schDriverService = DriverDAL.OpenService(scManagerHandle, svcName, DriverEntity.SERVICE_ALL_ACCESS);
            if (null == schDriverService || IntPtr.Zero == schDriverService)
            {
                DriverDAL.CloseServiceHandle(scManagerHandle);
                return false;
            }
 
            serviceStatus = new DriverEntity.SERVICE_STATUS();
 
            //停止服务
            if (false == DriverDAL.ControlService(schDriverService, DriverEntity.SERVICE_CONTROL_STOP, ref serviceStatus))
            {
                DriverDAL.CloseServiceHandle(schDriverService);
                DriverDAL.CloseServiceHandle(scManagerHandle);
 
                return false;
            }
            else
            {
                DriverDAL.CloseServiceHandle(schDriverService);
                DriverDAL.CloseServiceHandle(scManagerHandle);
 
                return true;
            }
        }
 
 
        /// <summary>
        /// 判断驱动程序是否已经安装
        /// </summary>
        /// <param name="svcName"></param>
        /// <returns></returns>
        public bool DriverIsInstalled(string svcName)
        {
            IntPtr scManagerHandle;
            IntPtr schDriverService;
 
            //打开服务控制台管理器
            scManagerHandle = DriverDAL.OpenSCManager(null, null, DriverEntity.SC_MANAGER_ALL_ACCESS);
            if (null == scManagerHandle || IntPtr.Zero == scManagerHandle)
            {
                return false;
            }
 
            //打开驱动程序服务
            schDriverService = DriverDAL.OpenService(scManagerHandle, svcName, DriverEntity.SERVICE_ALL_ACCESS);
            if (null == schDriverService || IntPtr.Zero == schDriverService)
            {
                DriverDAL.CloseServiceHandle(scManagerHandle);
                return false;
            }
 
            DriverDAL.CloseServiceHandle(schDriverService);
            DriverDAL.CloseServiceHandle(scManagerHandle);
 
            return true;
        }
 
 
        /// <summary>
        /// 安装驱动程序服务
        /// </summary>
        /// <param name="svcDriverPath"></param>
        /// <param name="svcDriverName"></param>
        /// <param name="svcDisplayName"></param>
        /// <returns></returns>
        public bool DriverInstall(String svcDriverPath, String svcDriverName, String svcDisplayName)
        {
            UInt32 lpdwTagId;
            IntPtr scManagerHandle;
            IntPtr schDriverService;
 
            //打开服务控制台管理器
            scManagerHandle = DriverDAL.OpenSCManager(null, null, DriverEntity.SC_MANAGER_CREATE_SERVICE);
            if (null == scManagerHandle || IntPtr.Zero == scManagerHandle)
            {
                return false;
            }
            if (DriverIsInstalled(svcDriverName) == false)
            {
                lpdwTagId = 0;
                schDriverService = DriverDAL.CreateService(
                    scManagerHandle, svcDriverName, svcDisplayName, 
                    DriverEntity.SERVICE_ALL_ACCESS, 
                    DriverEntity.SERVICE_KERNEL_DRIVER, 
                    DriverEntity.SERVICE_DEMAND_START, 
                    DriverEntity.SERVICE_ERROR_NORMAL, 
                    svcDriverPath, null, 
                    ref lpdwTagId, 
                    null, null, null
                    );
 
                DriverDAL.CloseServiceHandle(scManagerHandle);
                if (null == schDriverService || IntPtr.Zero == schDriverService)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
 
            DriverDAL.CloseServiceHandle(scManagerHandle);
            return true;
        }
 
 
        /// <summary>
        /// 卸载驱动程序服务
        /// </summary>
        /// <param name="svcName"></param>
        public void DriverUnInstall(String svcName)
        {
            IntPtr scManagerHandle;
            IntPtr schDriverService;
 
            //打开服务控制台管理器
            scManagerHandle = DriverDAL.OpenSCManager(null, null, DriverEntity.SC_MANAGER_ALL_ACCESS);
            if (null == scManagerHandle || IntPtr.Zero == scManagerHandle)
            {
                return;
            }
 
            //打开驱动程序服务
            schDriverService = DriverDAL.OpenService(scManagerHandle, svcName, DriverEntity.SERVICE_ALL_ACCESS);
            if (null == schDriverService || IntPtr.Zero == schDriverService)
            {
                DriverDAL.CloseServiceHandle(scManagerHandle);
                return;
            }
            else
            {
                DriverDAL.DeleteService(schDriverService);
 
                DriverDAL.CloseServiceHandle(schDriverService);
                DriverDAL.CloseServiceHandle(scManagerHandle);
            }
        }
    }
}

上面的这个类呢,说实在的,对于没用过驱动程序的来说,屁用没一点,

但是如果某位也在烦恼驱动程序的安装的话,那么恭喜你,你中奖了 . . .

(转)驱动程序安装类(C#)的更多相关文章

  1. Linux设备模型(总线、设备、驱动程序和类)

    Linux设备驱动程序学习(13) -Linux设备模型(总线.设备.驱动程序和类)[转] 文章的例子和实验使用<LDD3>所配的lddbus模块(稍作修改). 提示:在学习这部分内容是一 ...

  2. CUDA安装出现图形驱动程序安装失败

    win7安装cuda9时出现图形驱动程序安装失败,解决办法是右键计算机>管理>服务和应用程序>服务>找到“Windows Installer”,右键选择“启动” 参考自http ...

  3. 自动手动随便你 Win7驱动程序安装自己设

    Win7系统是非常智能方便的操作系统,可以自动安装硬件驱动程序,为用户提供了很多方便.但是并不是所有的驱动程序和硬件都能完美兼容,如果不合适就需要卸载了重新安装:还有一些朋友就习惯自己安装驱动,那么, ...

  4. Visual Studio 2017&C#打包应用程序详细教程,重写安装类获取安装路径

    Visual Studio搞了个Click One,在线升级是方便了,但对于俺们这苦逼的业余程序猿就... 别着急,折腾一下,还是能做出打包安装程序的.请移步CSDN看smallbabylong的文章 ...

  5. 在ESXi 5.x 和 ESXi 6.0.x 中如何安装第三方供应商开发的驱动程序

    在 VMware ESXi 5.x 和 ESXi 6.0.x 中如何下载并安装异步驱动程序 (2076262)   Symptoms 免责声明:本文为 How to download and inst ...

  6. 【C#】分享基于Win32 API的服务操作类(解决ManagedInstallerClass.InstallHelper不能带参数安装的问题)

    注:这里的服务是指Windows 服务. ------------------201508250915更新------------------ 刚刚得知TransactedInstaller类是支持带 ...

  7. 42.MySQL数据库安装,及驱动程序选择

    MySQL驱动程序安装: 我们使用Django来操作Mysql,实际上底层还是通过Python来操作的,因此我们想要使用Django来操作mysql,首先还是需要安装一个驱动程序,在Python3中, ...

  8. 第六章 第一个Linux驱动程序:统计单词个数

    现在进入了实战阶段,使用统计单词个数的实例让我们了解开发和测试Linux驱动程序的完整过程.第一个Linux驱动程序是统计单词个数. 这个Linux驱动程序没有访问硬件,而是利用设备文件作为介质与应用 ...

  9. 如何构造一个简单的USB过滤驱动程序

    本文分三部分来介绍如何构造一个简单的USB过滤驱动程序,包括"基本原理"."程序的实现"."使用INF安装".此文的目的在于希望读者了解基本 ...

随机推荐

  1. node ->rman to RAC (迁移)

    版权声明:本文为博主原创文章.未经博主同意不得转载. https://blog.csdn.net/lmocm/article/details/34435699 *.audit_file_dest='/ ...

  2. Yuan先生的博客网址

    1 Web应用  https://www.cnblogs.com/yuanchenqi/articles/8869302.html 2 http协议 https://www.cnblogs.com/y ...

  3. BTrace学习总结

    一.简介: 在生产环境中经常遇到格式各样的问题,如OOM或者莫名其妙的进程死掉.一般情况下是通过修改程序,添加打印日志:然后重新发布程序来完成.然而,这不仅麻烦,而且带来很多不可控的因素.有没有一种方 ...

  4. PHP 换行符 PHP_EOL

    PHP 中换行可以用 PHP_EOL 来替代,以提高代码的源代码级可移植性: unix系列用 \n windows系列用 \r\n mac用 \r <?php echo PHP_EOL; //w ...

  5. centos7下git服务器端搭建(转)

    git的安装: yum 源仓库里的 Git 版本更新不及时,最新版本的 Git 是 1.8.3.1,但是官方最新版本已经到了 2.9.2.想要安装最新版本的的 Git,只能下载源码进行安装. 1. 查 ...

  6. 前端实现在线预览pdf、word、xls、ppt等文件

    最近在做一个公司的资源管理系统,一些知识小记一下. 1.前端实现pdf文件在线预览功能 方式一.pdf文件理论上可以在浏览器直接打开预览但是需要打开新页面.在仅仅是预览pdf文件且UI要求不高的情况下 ...

  7. java.lang.NoSuchMethodError: javax.wsdl.xml.WSDLReader.readWSDL

    CXF调用web service报错:java.lang.NoSuchMethodError: javax.wsdl.xml.WSDLReader.readWSDL 原因,wsdl jar报冲突,系统 ...

  8. Centos7 在 Xshell里 vim的配置

    Centos里的VI只默认安装了vim-minimal-7.x.所以无论是输入vi或者vim查看文件,syntax功能都无法正常启用.因此需要用yum安装另外两个组件:vim-common-7.x和v ...

  9. NGUI的字体加粗效果

    ngui的UILabel可以通过属性面板(inspector)设置字体的样式:加粗 倾斜 正常等. 但是如果通过这里设置了加粗,与实际的加粗不一样,ngui有一个拉伸宽度的变化. 这让人觉得很丑 .如 ...

  10. 峰Redis学习(9)Redis 集群(概述)

    第一节:Redis 集群概述 redis cluster是去中心化,去中间件的,也就是说,集群中的每个节点都是平等的关系,都是对等的,每个节点都保存各自的数据和整个集群的状态.每个节点都和其他所有节点 ...