项目笔记---Windows Service调用Windows API问题

转于:http://www.cnblogs.com/cuiyansong/p/4318551.html


概要

  此文来自于最近一个“诡异”的Windows API调用发现Windows Service在调用某些Windows API的过程中失效,在经过漫长的Baidu,之后终于在StackOverFlow上找到了答案,今天希望把这个问题记录下来,方便大家Baidu  -。-

需求是什么?

                      

  注:PDA一端通过Socket传输一条一维码(如1231223123123123),服务端接收到消息后,在当前(即当前有焦点的任何窗口)模拟键盘敲击一维码。

  最开始服务端是用WinForm实现的,测试成功,所以就想当然希望将服务端重构成Windows服务,实现后台监听并处理的功能,可是事与愿违,各位别着急,请继续往下看。

代码实现及问题是什么?

  Socket通讯我是用《异步Socket通讯》实现的,这里不详细介绍,先将模拟键盘的代码贴出来,此代码在Windows Form下测试可用:

复制代码
    internal class Win32API
    {
        #region Constant
        private const uint KEYEVENTF_EXTENDEDKEY = 0x1;
        private const uint KEYEVENTF_KEYUP = 0x2;
        #endregion

        #region Public Property
        public static IServiceLog Log
        {
            get;
            set;
        }
        #endregion

        #region External Import
        /// <summary>
        /// Keybd_events the specified b vk.
        /// </summary>
        /// <param name="bVk">The b vk.</param>
        /// <param name="bScan">The b scan.</param>
        /// <param name="dwFlags">The dw flags.</param>
        /// <param name="dwExtraInfo">The dw extra information.</param>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo);

        /// <summary>
        /// Messages the box.
        /// </summary>
        /// <param name="h">The h.</param>
        /// <param name="m">The m.</param>
        /// <param name="c">The c.</param>
        /// <param name="type">The type.</param>
        /// <returns></returns>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern int MessageBox(int h, string m, string c, int type);

        /// <summary>
        /// Gets the focus.
        /// </summary>
        /// <returns></returns>
        [System.Runtime.InteropServices.DllImport("user32.dll")]
        public static extern IntPtr GetFocus();

        #endregion

        #region Public Method
        /// <summary>
        /// Sends the key.
        /// </summary>
        /// <param name="str">The string.</param>
        public static void SendKey(string str)
        {
            var charray = str.ToCharArray();
            for (int i = 0; i < charray.Length; i++)
            {
                CharToInt(charray[i]);
            }
            KeyBoardDo(13, 0);
        }
 
        #endregion

        #region Private Method
        /// <summary>
        /// Keys the board do.
        /// </summary>
        /// <param name="key">The key.</param>
        private static void KeyBoardDo(int[] key)
        {
            foreach (int k in key)
            {
                keybd_event((byte)k, 0x45, KEYEVENTF_EXTENDEDKEY | 0, 0);
            }
            foreach (int k in key)
            {
                keybd_event((byte)k, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
            }
        }

        /// <summary>
        /// Keys the board do.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <param name="sheft">The sheft.</param>
        private static void KeyBoardDo(int key, int sheft)
        {
            Log.WriteInfo("KeyBoard Simulate Char: " + key); 
            if (sheft == 16)
            {
                keybd_event((byte)sheft, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
                System.Threading.Thread.Sleep(10);
            }
            keybd_event((byte)key, 0, KEYEVENTF_EXTENDEDKEY | 0, 0);
            System.Threading.Thread.Sleep(10);
            keybd_event((byte)key, 0, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
            System.Threading.Thread.Sleep(10);
            if (sheft == 16)
            {
                keybd_event((byte)sheft, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, 0);
                System.Threading.Thread.Sleep(10);
            }
        }

        /// <summary>
        /// Characters to int.
        /// </summary>
        /// <param name="ch">The ch.</param>
        /// <returns></returns>
        private static int CharToInt(char ch)
        {
            int chint = 32;
            int sheft = 16;
            switch (ch)
            {
                case '0':
                    chint = 48;
                    KeyBoardDo(chint, 0);
                    break;
                case '1':
                    chint = 49;
                    KeyBoardDo(chint, 0);
                    break;
                case '2':
                    chint = 50;
                    KeyBoardDo(chint, 0);
                    break;
                case '3':
                    chint = 51;
                    KeyBoardDo(chint, 0);
                    break;
                case '4':
                    chint = 52;
                    KeyBoardDo(chint, 0);
                    break;
                case '5':
                    chint = 53;
                    KeyBoardDo(chint, 0);
                    break;
                case '6':
                    chint = 54;
                    KeyBoardDo(chint, 0);
                    break;
                case '7':
                    chint = 55;
                    KeyBoardDo(chint, 0);
                    break;
                case '8':
                    chint = 56;
                    KeyBoardDo(chint, 0);
                    break;
                case '9':
                    chint = 57;
                    KeyBoardDo(chint, 0);
                    break;
                case 'A':
                    chint = 65;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'B':
                    chint = 66;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'C':
                    chint = 67;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'D':
                    chint = 68;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'E':
                    chint = 69;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'F':
                    chint = 70;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'G':
                    chint = 71;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'H':
                    chint = 72;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'I':
                    chint = 73;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'J':
                    chint = 74;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'K':
                    chint = 75;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'L':
                    chint = 76;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'M':
                    chint = 77;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'N':
                    chint = 78;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'O':
                    chint = 79;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'P':
                    chint = 80;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'Q':
                    chint = 81;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'R':
                    chint = 82;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'S':
                    chint = 83;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'T':
                    chint = 84;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'U':
                    chint = 85;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'V':
                    chint = 86;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'W':
                    chint = 87;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'X':
                    chint = 88;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'Y':
                    chint = 89;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'Z':
                    chint = 90;
                    KeyBoardDo(chint, sheft);
                    break;
                case 'a':
                    chint = 65;
                    KeyBoardDo(chint, 0);
                    break;
                case 'b':
                    chint = 66;
                    KeyBoardDo(chint, 0);
                    break;
                case 'c':
                    chint = 67;
                    KeyBoardDo(chint, 0);
                    break;
                case 'd':
                    chint = 68;
                    KeyBoardDo(chint, 0);
                    break;
                case 'e':
                    chint = 69;
                    KeyBoardDo(chint, 0);
                    break;
                case 'f':
                    chint = 70;
                    KeyBoardDo(chint, 0);
                    break;
                case 'g':
                    chint = 71;
                    KeyBoardDo(chint, 0);
                    break;
                case 'h':
                    chint = 72;
                    KeyBoardDo(chint, 0);
                    break;
                case 'i':
                    chint = 73;
                    KeyBoardDo(chint, 0);
                    break;
                case 'j':
                    chint = 74;
                    KeyBoardDo(chint, 0);
                    break;
                case 'k':
                    chint = 75;
                    KeyBoardDo(chint, 0);
                    break;
                case 'l':
                    chint = 76;
                    KeyBoardDo(chint, 0);
                    break;
                case 'm':
                    chint = 77;
                    KeyBoardDo(chint, 0);
                    break;
                case 'n':
                    chint = 78;
                    KeyBoardDo(chint, 0);
                    break;
                case 'o':
                    chint = 79;
                    KeyBoardDo(chint, 0);
                    break;
                case 'p':
                    chint = 80;
                    KeyBoardDo(chint, 0);
                    break;
                case 'q':
                    chint = 81;
                    KeyBoardDo(chint, 0);
                    break;
                case 'r':
                    chint = 82;
                    KeyBoardDo(chint, 0);
                    break;
                case 's':
                    chint = 83;
                    KeyBoardDo(chint, 0);
                    break;
                case 't':
                    chint = 84;
                    KeyBoardDo(chint, 0);
                    break;
                case 'u':
                    chint = 85;
                    KeyBoardDo(chint, 0);
                    break;
                case 'v':
                    chint = 86;
                    KeyBoardDo(chint, 0);
                    break;
                case 'w':
                    chint = 87;
                    KeyBoardDo(chint, 0);
                    break;
                case 'x':
                    chint = 88;
                    KeyBoardDo(chint, 0);
                    break;
                case 'y':
                    chint = 89;
                    KeyBoardDo(chint, 0);
                    break;
                case 'z':
                    chint = 90;
                    KeyBoardDo(chint, 0);
                    break;
                case ';':
                    chint = 186;
                    KeyBoardDo(chint, 0);
                    break;
                case '=':
                    chint = 187;
                    KeyBoardDo(chint, 0);
                    break;
                case ',':
                    chint = 188;
                    KeyBoardDo(chint, 0);
                    break;
                case '-':
                    chint = 189;
                    KeyBoardDo(chint, 0);
                    break;
                case '.':
                    chint = 190;
                    KeyBoardDo(chint, 0);
                    break;
                case '/':
                    chint = 191;
                    KeyBoardDo(chint, 0);
                    break;
                case '`':
                    chint = 192;
                    KeyBoardDo(chint, 0);
                    break;
                case '[':
                    chint = 219;
                    KeyBoardDo(chint, 0);
                    break;
                case ']':
                    chint = 221;
                    KeyBoardDo(chint, 0);
                    break;
                case '\'':
                    chint = 222;
                    KeyBoardDo(chint, 0);
                    break;
            }
            return chint;
        }
        #endregion 

    }
复制代码
View Code

  同样的代码在Windows Service调用没有任何效果,原因就出在这里:Session 0 Isolation,简而言之就是在Win XP以及之前的windows服务(系统服务和用户编写的服务)都运行在最高权限的Session 0 中,但是在Vista以及之后的系统中用户所编写的服务被隔离开,为的是系统安全性考虑,被隔离开的服务中受影响的是一些基于图形界面的系统调用都将失效,如“User32.dll”中的MessageBox调用,同时也包含本文中的模拟键盘的keybd_event调用。

有兴趣的朋友可以自行测试下,原理很简单,这里就不给出更多的代码了。

注:Vista之后系统服务权限图。

结语

         说点题外话,其实这个问题就是一句话的事:Win7下Windows服务不能调用键盘模拟事件,为什么在百度搜来搜去,基本没有什么有价值的信息,包括CSDN等等。后来,不得不开着FQ软件去Google,或者再去StackOverFlow提问,搜索问题,这里也不去抱怨什么,只希望作为码农的我以及跟我一样的人能更熟练的掌握英语,Happy To Search On Google.

 

引用

Session 0 Isolation: https://msdn.microsoft.com/en-us/library/windows/hardware/dn653293(v=vs.85).aspx

StackOverFlow Discuss:http://stackoverflow.com/questions/16959963/how-to-reset-windows-idle-timer-through-a-windows-service

 

作者:Stephen Cui
出处:http://www.cnblogs.com/cuiyansong

版权声明:文章属于本人及博客园共有,凡是没有标注[转载]的,请在文章末尾加入我的博客地址。

如果您觉得文章写的还不错,请点击“推荐一下”,谢谢。 


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
springboot学习笔记 spring基础 Spring概述 Spring的简史 xml配置 注解配置 java配置 Spring概述 Spring的模块 核心容器CoreContainer Spring-Core Spring-Beans Spring-Context Spring-Context-Support Spring-Expression AOP Spring-AOP Spring-Aspects Messaging Spring-Messaging WEB Spring-Web Spring-Webmvc Spring-WebSocket Spring-Webmvc-Portlet 数据访问/集成(DataAccess/Intefration) Spring-JDBC Spring-TX Spring-ORM Spring-OXM Spring-JMS Spring的生态 Spring Boot Spring XD Spring Cloud Spring Data Spring Integration Spring Batch Spring Security Spring HATEOAS Spring Social Spring AMQP Spring Mobile Spring for Android Spring Web Flow Spring Web Services Spring LDAP Spring Session Spring项目快速搭建 Maven简介 Maven安装 Maven的pom.xml dependencies dependency 变量定义 编译插件 Spring项目的搭建 Spring Tool Suite https://spring.io/tools/sts/all IntelliJ IDEA NetBeans https://netbeans.org/downloads/ Spring基础配置 依赖注入 声明Bean的注解 @Component组件,没有明确的角色 @Service在业务逻辑层(service层) @Repository在数据访问层(dao层) @Controller在展现层(MVC→SpringMVC) 注入Bean的注解 @Autowired:Spring提供的注解 @Inject:JSR-330提供的注解 @Resource:JSR-250提供的注解 Java配置 @Configuration声明当前类是一个配置类 @Bean注解在方法上,声明当前方法的返回值为一个Bean AOP @Aspect 声明是一个切面 拦截规则@After @Before @Around PointCut JoinPoint Spring常用配置 Bean的Scope Singleton Prototype Request Session GlobalSession SpringEL和资源调用 注入普通字符 注入操作系统属性 注入表达式云算结果 注入其他Bean的属性 注入文件内容 注入网址内容 注入属性文件 Bean的初始化和销毁 Java配置方式 注解方式 Profile @Profile 通过设定jvm的spring.profiles.active参数 web项目设置在Servlet的context parameter中 事件Application Event 自定义事件,集成ApplicationEvent 定义事件监听器,实现ApplicationListener 使用容器发布事件 Spring高级话题 Spring Aware BeanNameAware BeanFactoryAware

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值