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

时间:2022-09-05 13:38:22

概要

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

需求是什么?

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

  注: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 = ; i < charray.Length; i++)
{
CharToInt(charray[i]);
}
KeyBoardDo(, );
} #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 | , );
}
foreach (int k in key)
{
keybd_event((byte)k, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, );
}
} /// <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 == )
{
keybd_event((byte)sheft, , KEYEVENTF_EXTENDEDKEY | , );
System.Threading.Thread.Sleep();
}
keybd_event((byte)key, , KEYEVENTF_EXTENDEDKEY | , );
System.Threading.Thread.Sleep();
keybd_event((byte)key, , KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, );
System.Threading.Thread.Sleep();
if (sheft == )
{
keybd_event((byte)sheft, 0x45, KEYEVENTF_EXTENDEDKEY | KEYEVENTF_KEYUP, );
System.Threading.Thread.Sleep();
}
} /// <summary>
/// Characters to int.
/// </summary>
/// <param name="ch">The ch.</param>
/// <returns></returns>
private static int CharToInt(char ch)
{
int chint = ;
int sheft = ;
switch (ch)
{
case '':
chint = ;
KeyBoardDo(chint, );
break;
case '':
chint = ;
KeyBoardDo(chint, );
break;
case '':
chint = ;
KeyBoardDo(chint, );
break;
case '':
chint = ;
KeyBoardDo(chint, );
break;
case '':
chint = ;
KeyBoardDo(chint, );
break;
case '':
chint = ;
KeyBoardDo(chint, );
break;
case '':
chint = ;
KeyBoardDo(chint, );
break;
case '':
chint = ;
KeyBoardDo(chint, );
break;
case '':
chint = ;
KeyBoardDo(chint, );
break;
case '':
chint = ;
KeyBoardDo(chint, );
break;
case 'A':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'B':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'C':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'D':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'E':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'F':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'G':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'H':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'I':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'J':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'K':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'L':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'M':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'N':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'O':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'P':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'Q':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'R':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'S':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'T':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'U':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'V':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'W':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'X':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'Y':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'Z':
chint = ;
KeyBoardDo(chint, sheft);
break;
case 'a':
chint = ;
KeyBoardDo(chint, );
break;
case 'b':
chint = ;
KeyBoardDo(chint, );
break;
case 'c':
chint = ;
KeyBoardDo(chint, );
break;
case 'd':
chint = ;
KeyBoardDo(chint, );
break;
case 'e':
chint = ;
KeyBoardDo(chint, );
break;
case 'f':
chint = ;
KeyBoardDo(chint, );
break;
case 'g':
chint = ;
KeyBoardDo(chint, );
break;
case 'h':
chint = ;
KeyBoardDo(chint, );
break;
case 'i':
chint = ;
KeyBoardDo(chint, );
break;
case 'j':
chint = ;
KeyBoardDo(chint, );
break;
case 'k':
chint = ;
KeyBoardDo(chint, );
break;
case 'l':
chint = ;
KeyBoardDo(chint, );
break;
case 'm':
chint = ;
KeyBoardDo(chint, );
break;
case 'n':
chint = ;
KeyBoardDo(chint, );
break;
case 'o':
chint = ;
KeyBoardDo(chint, );
break;
case 'p':
chint = ;
KeyBoardDo(chint, );
break;
case 'q':
chint = ;
KeyBoardDo(chint, );
break;
case 'r':
chint = ;
KeyBoardDo(chint, );
break;
case 's':
chint = ;
KeyBoardDo(chint, );
break;
case 't':
chint = ;
KeyBoardDo(chint, );
break;
case 'u':
chint = ;
KeyBoardDo(chint, );
break;
case 'v':
chint = ;
KeyBoardDo(chint, );
break;
case 'w':
chint = ;
KeyBoardDo(chint, );
break;
case 'x':
chint = ;
KeyBoardDo(chint, );
break;
case 'y':
chint = ;
KeyBoardDo(chint, );
break;
case 'z':
chint = ;
KeyBoardDo(chint, );
break;
case ';':
chint = ;
KeyBoardDo(chint, );
break;
case '=':
chint = ;
KeyBoardDo(chint, );
break;
case ',':
chint = ;
KeyBoardDo(chint, );
break;
case '-':
chint = ;
KeyBoardDo(chint, );
break;
case '.':
chint = ;
KeyBoardDo(chint, );
break;
case '/':
chint = ;
KeyBoardDo(chint, );
break;
case '`':
chint = ;
KeyBoardDo(chint, );
break;
case '[':
chint = ;
KeyBoardDo(chint, );
break;
case ']':
chint = ;
KeyBoardDo(chint, );
break;
case '\'':
chint = ;
KeyBoardDo(chint, );
break;
}
return chint;
}
#endregion }

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

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

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

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

结语

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

引用

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

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

项目笔记---Windows Service调用Windows API问题的更多相关文章

  1. C&num; 编写Windows Service(windows服务程序)

    C# 编写Windows Service(windows服务程序)   Windows Service简介: 一个Windows服务程序是在Windows操作系统下能完成特定功能的可执行的应用程序.W ...

  2. C&num; Windows Service调用IBM Lotus Notes发送邮件

    近日研究了下IBM Lotus Mail,这货果然是麻烦,由于公司策略,没有开放smtp,很多系统邮件都没有办法发送,于是入手google学习Lotus Mail,想做成Windows服务,提供wcf ...

  3. windows service宿主web api使用&quot&semi;依赖注入&quot&semi;和&OpenCurlyDoubleQuote;控制反转”的技术实践

    前言 自从几年前抛弃wcf,使用web api 来做服务器端开发之后,就不再迷惑了.但是因为本来从事传统行业管理软件开发,一般都以分布式应用开发为主.纯BS还是比较少,于是比较喜欢用windows s ...

  4. 如何将&period;NET 4&period;0写的Windows service和Web API部署到docker上面

    Web API. 看这篇文章: https://docs.microsoft.com/en-us/aspnet/mvc/overview/deployment/docker-aspnetmvc Win ...

  5. C&num; 编写Windows Service(windows服务程序)【转载】

    [转]http://www.cnblogs.com/bluestorm/p/3510398.html Windows Service简介: 一个Windows服务程序是在Windows操作系统下能完成 ...

  6. C&num; 创建Windows Service(Windows服务)程序

    本文介绍了如何用C#创建.安装.启动.监控.卸载简单的Windows Service 的内容步骤和注意事项. 一.创建一个Windows Service 1)创建Windows Service项目 2 ...

  7. Windows Desktop 调用 WinRT api

    <Reference Include="Windows"> <HintPath>..\..\..\..\..\..\Program Files (x86)\ ...

  8. HTML5项目笔记4:使用Audio API设计绚丽的HTML5音乐播放器

    HTML5 有两个很炫的元素,就是Audio和 Video,可以用他们在页面上创建音频播放器和视频播放器,制作一些效果很不错的应用. 无论是视屏还是音频,都是一个容器文件,包含了一些音频轨道,视频轨道 ...

  9. Create a new Windows service on windows server2012

    netsh http add iplisten ipaddress=0.0.0.0:15901 sc.exe create "FPPService" binPath= " ...

随机推荐

  1. xamarin UWP设置HUD加载功能

    使用xamarin开发的时候经常用到加载HUD功能,就是我们常见的一个加载中的动作,Android 下使用 AndHUD , iOS 下使用 BTProgressHUD, 这两个在在 NuGet 上都 ...

  2. 关于Ajax中http协议

    关于ajaxajax是异步的JavaScript和XML,优点是无刷新的与后天通信并获取数据,只更改页面中需要更改的部分,而不是刷新整个页面,减少无意义的数据传输,提高了效率和用户体验 1.协议和HT ...

  3. C&num; 中的&quot&semi;yield&quot&semi;使用

    yield是C#为了简化遍历操作实现的语法糖,我们知道如果要要某个类型支持遍历就必须要实现系统接口IEnumerable,这个接口后续实现比较繁琐要写一大堆代码才能支持真正的遍历功能.举例说明 usi ...

  4. BZOJ-1800 飞行棋 数学&plus;乱搞

    这道题感觉就是乱搞,O(n^4)都毫无问题 1800: [Ahoi2009]fly 飞行棋 Time Limit: 10 Sec Memory Limit: 64 MB Submit: 1172 So ...

  5. mysql查询语句分析 explain用法

    explain显示了mysql如何使用索引来处理select语句以及连接表.可以帮助选择更好的索引和写出更优化的查询语句. 使用方法,在select语句前加上explain就可以了,如: explai ...

  6. 一&period;Kylin的伪分布式安装

    一.伪分布式安装kylin 2018年4月15日 15:06 安装需要的环境 1. hadoop集群环境:由于安装的是CDH5.14.0的版本,所以相关组件都是跟5.14.0相关 2. spark采用 ...

  7. nodejs与Promise的思想碰撞

    玩node的同志们都知道,当这门语言被提出来的时候,作为自己最为骄傲的异步机制,却被PHP和Python等战团喷得不成样子的是,他们嘲笑着nodejs那蠢蠢的无限嵌套,nodejs战团只能以我们只要性 ...

  8. 【laravel】passport的scope作用域

    1.根据作用域生成token $user->createToken($request->name,['test1'])->accessToken; 2.注册中间件 'scopes' ...

  9. 我的Android进阶之旅------>Android使用9Patch图片作为不失真背景

    做人要大度,海纳百川,做事要圆滑,左右逢源,这让我想到了编程也是如此,代码要扩展,界面也要考虑自适应. 这篇文章是android开发人员的必备知识,是我特别为大家整理和总结的,不求完美,但是有用. 1 ...

  10. Android逆向基础知识Smali

    什么是Smali: 我们用工具反编译一些APP的时候,会看到一个smali文件夹,里面其实就是每个Java类所对应的smali文件.Android虚拟机Dalvik并不是执行java虚拟机JVM编译后 ...