您的位置:首页 > 其它

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

2015-03-06 16:08 357 查看

概要

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

需求是什么?

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: