最近遇到要做回传服务内增加开关,可以自定义运行一些脚本已方便收集PC状态,发现Bat始终无法运行,上网找了半天才发现和Session0有关,也就是程序有不同级别的访问权限,Vista以上版本为了安全因素,限制了不同Session间的访问,可以使用Windows API还直接穿透Session0,也就是获得最高权限
相关类如下
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Runtime.InteropServices; 5 using System.Security.Principal; 6 using System.Text; 7 8 namespace IctInfo 9 { 10 /// <summary> 11 /// 解决vista和win7在windows服务中交互桌面权限问题:穿透Session 0 隔离 12 /// </summary> 13 public class Interop 14 { 15 public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero; 16 17 public static void ShowMessageBox(string message, string title) 18 { 19 int resp = 0; 20 WTSSendMessage( 21 WTS_CURRENT_SERVER_HANDLE, 22 WTSGetActiveConsoleSessionId(), 23 title, title.Length, 24 message, message.Length, 25 0, 0, out resp, false); 26 } 27 28 [DllImport("kernel32.dll", SetLastError = true)] 29 public static extern int WTSGetActiveConsoleSessionId(); 30 31 [DllImport("wtsapi32.dll", SetLastError = true)] 32 public static extern bool WTSSendMessage( 33 IntPtr hServer, 34 int SessionId, 35 String pTitle, 36 int TitleLength, 37 String pMessage, 38 int MessageLength, 39 int Style, 40 int Timeout, 41 out int pResponse, 42 bool bWait); 43 //在ShowMessageBox 函数中调用了WTSSendMessage 来发送信息窗口,这样我们就可以在Service 的OnStart 函数中使用,打开Service1.cs 加入下面代码: 44 public static void CreateProcess(string app, string path) 45 { 46 bool result; 47 IntPtr hToken = WindowsIdentity.GetCurrent().Token; 48 IntPtr hDupedToken = IntPtr.Zero; 49 50 PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); 51 SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES(); 52 sa.Length = Marshal.SizeOf(sa); 53 54 STARTUPINFO si = new STARTUPINFO(); 55 si.cb = Marshal.SizeOf(si); 56 57 int dwSessionID = WTSGetActiveConsoleSessionId(); 58 result = WTSQueryUserToken(dwSessionID, out hToken); 59 60 if (!result) 61 { 62 ShowMessageBox("WTSQueryUserToken failed", "AlertService Message"); 63 } 64 65 result = DuplicateTokenEx( 66 hToken, 67 GENERIC_ALL_ACCESS, 68 ref sa, 69 (int)SECURITY_IMPERSONATION_LEVEL.SecurityIdentification, 70 (int)TOKEN_TYPE.TokenPrimary, 71 ref hDupedToken 72 ); 73 74 if (!result) 75 { 76 ShowMessageBox("DuplicateTokenEx failed", "AlertService Message"); 77 } 78 79 IntPtr lpEnvironment = IntPtr.Zero; 80 result = CreateEnvironmentBlock(out lpEnvironment, hDupedToken, false); 81 82 if (!result) 83 { 84 ShowMessageBox("CreateEnvironmentBlock failed", "AlertService Message"); 85 } 86 87 result = CreateProcessAsUser( 88 hDupedToken, 89 app, 90 String.Empty, 91 ref sa, ref sa, 92 false, 0, IntPtr.Zero, 93 path, ref si, ref pi); 94 95 if (!result) 96 { 97 int error = Marshal.GetLastWin32Error(); 98 string message = String.Format("CreateProcessAsUser Error: {0}", error); 99 ShowMessageBox(message, "AlertService Message"); 100 } 101 102 if (pi.hProcess != IntPtr.Zero) 103 CloseHandle(pi.hProcess); 104 if (pi.hThread != IntPtr.Zero) 105 CloseHandle(pi.hThread); 106 if (hDupedToken != IntPtr.Zero) 107 CloseHandle(hDupedToken); 108 } 109 110 [StructLayout(LayoutKind.Sequential)] 111 public struct STARTUPINFO 112 { 113 public Int32 cb; 114 public string lpReserved; 115 public string lpDesktop; 116 public string lpTitle; 117 public Int32 dwX; 118 public Int32 dwY; 119 public Int32 dwXSize; 120 public Int32 dwXCountChars; 121 public Int32 dwYCountChars; 122 public Int32 dwFillAttribute; 123 public Int32 dwFlags; 124 public Int16 wShowWindow; 125 public Int16 cbReserved2; 126 public IntPtr lpReserved2; 127 public IntPtr hStdInput; 128 public IntPtr hStdOutput; 129 public IntPtr hStdError; 130 } 131 132 [StructLayout(LayoutKind.Sequential)] 133 public struct PROCESS_INFORMATION 134 { 135 public IntPtr hProcess; 136 public IntPtr hThread; 137 public Int32 dwProcessID; 138 public Int32 dwThreadID; 139 } 140 141 [StructLayout(LayoutKind.Sequential)] 142 public struct SECURITY_ATTRIBUTES 143 { 144 public Int32 Length; 145 public IntPtr lpSecurityDescriptor; 146 public bool bInheritHandle; 147 } 148 149 public enum SECURITY_IMPERSONATION_LEVEL 150 { 151 SecurityAnonymous, 152 SecurityIdentification, 153 SecurityImpersonation, 154 SecurityDelegation 155 } 156 157 public enum TOKEN_TYPE 158 { 159 TokenPrimary = 1, 160 TokenImpersonation 161 } 162 163 public const int GENERIC_ALL_ACCESS = 0x10000000; 164 165 [DllImport("kernel32.dll", SetLastError = true, 166 CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 167 public static extern bool CloseHandle(IntPtr handle); 168 169 [DllImport("advapi32.dll", SetLastError = true, 170 CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)] 171 public static extern bool CreateProcessAsUser( 172 IntPtr hToken, 173 string lpApplicationName, 174 string lpCommandLine, 175 ref SECURITY_ATTRIBUTES lpProcessAttributes, 176 ref SECURITY_ATTRIBUTES lpThreadAttributes, 177 bool bInheritHandle, 178 Int32 dwCreationFlags, 179 IntPtr lpEnvrionment, 180 string lpCurrentDirectory, 181 ref STARTUPINFO lpStartupInfo, 182 ref PROCESS_INFORMATION lpProcessInformation); 183 184 [DllImport("advapi32.dll", SetLastError = true)] 185 public static extern bool DuplicateTokenEx( 186 IntPtr hExistingToken, 187 Int32 dwDesiredAccess, 188 ref SECURITY_ATTRIBUTES lpThreadAttributes, 189 Int32 ImpersonationLevel, 190 Int32 dwTokenType, 191 ref IntPtr phNewToken); 192 193 [DllImport("wtsapi32.dll", SetLastError = true)] 194 public static extern bool WTSQueryUserToken( 195 Int32 sessionId, 196 out IntPtr Token); 197 198 [DllImport("userenv.dll", SetLastError = true)] 199 static extern bool CreateEnvironmentBlock( 200 out IntPtr lpEnvironment, 201 IntPtr hToken, 202 bool bInherit); 203 204 } 205 }
特别感谢以下大牛的技术分享