发布:2018/7/2 22:52:38作者:管理员 来源:本站 浏览次数:1223
本示例演示了如何在使用 C#.Net 编写的服务应用程序的登录用户会话中以交互方式创建/启动进程。
只是为了演示目的,子进程(本示例中的 Notepad.exe)的路径/名称已在父级服务应用程序中进行了硬编码,但是可以引用本示例来启动任何其他交互式子应用程序。示例的主要实现位于名为“CSCreateProcessAsUserFromService”的类中,可以通过 P/Invoke 调用到某些本机 Windows API 来启动进程。
1) 在 Visual Studio 2010 中打开“CSCreateProcessAsUserFromService.sln”文件。
2) 构建项目并获取服务应用程序 exe,如 CSCreateProcessAsUserFromService.exe。
3) 项目构建完成后,使用命令行服务控制器实用工具“sc”创建/启动/停止/删除 Windows 服务。
“sc”命令的语法(务必以管理员身份运行)–
sc <服务器> [命令] [服务名称] <选项 1> <选项 2>...
例如 –
创建名为“My Sample Service”的 Windows 服务 –
sc create “My Sample Service” binpath= <CSCreateProcessAsUserFromService.exe 的完整路径>
启动“My Sample Service”服务将会启动子进程 –
sc start “My Sample Service”
停止“My Sample Service”服务 –
sc stop "My Sample Service"
删除名为“My Sample Service”的 Windows 服务 –
sc delete "My Sample Service"
1) 子进程的启动已在“CSCreateProcessAsUserFromService”类中实现。
2) 在服务的“OnStart”中,我们已创建了一个线程来启动/创建子进程。在单独的线程中创建子进程始终是很好的做法,因为它不会阻止服务主线程。阻止服务主线程可能会导致服务控制管理器 (SCM) 的超时错误。
protected override void OnStart(string[] args) { // As creating a child process might be a time consuming operation, // its better to do that in a separate thread than blocking the main thread. System.Threading.Thread ProcessCreationThread = new System.Threading.Thread(MyThreadFunc); ProcessCreationThread.Start(); }
// This thread function would launch a child process // in the interactive session of the logged-on user. public static void MyThreadFunc() { CreateProcessAsUserWrapper.LaunchChildProcess("C:\\Windows\\notepad.exe"); }
4)“CSCreateProcessAsUserFromService”类首先通过调用 WTSEnumerateSessions 枚举所有正在运行/可用的会话。
5) 获取所有会话后,我们尝试检查哪个会话是活动会话,即登录用户的会话。
6) 然后,我们通过调用 WTSQueryUserToken 来获取由会话 ID 指定的登录用户的主访问令牌。
7) 然后,将从 WTSQueryUserToken 接收到的用户令牌以及子应用程序的名称传递到函数 CreateProcessAsUser,以便在登录用户的会话中以交互方式启动子进程。
public static void LaunchChildProcess(string ChildProcName) { IntPtr ppSessionInfo = IntPtr.Zero; UInt32 SessionCount = 0; if (WTSEnumerateSessions( (IntPtr)WTS_CURRENT_SERVER_HANDLE, // Current RD Session Host Server handle would be zero. 0, // This reserved parameter must be zero. 1, // The version of the enumeration request must be 1. ref ppSessionInfo, // This would point to an array of session info. ref SessionCount // This would indicate the length of the above array. )) { for (int nCount = 0; nCount < SessionCount; nCount++) { // Extract each session info and check if it is the // "Active Session" of the current logged-on user. WTS_SESSION_INFO tSessionInfo = (WTS_SESSION_INFO)Marshal.PtrToStructure( ppSessionInfo + nCount * Marshal.SizeOf(typeof(WTS_SESSION_INFO)), typeof(WTS_SESSION_INFO) ); if (WTS_CONNECTSTATE_CLASS.WTSActive == tSessionInfo.State) { IntPtr hToken = IntPtr.Zero; if (WTSQueryUserToken(tSessionInfo.SessionID, out hToken)) { // Launch the child process interactively // with the token of the logged-on user. PROCESS_INFORMATION tProcessInfo; STARTUPINFO tStartUpInfo = new STARTUPINFO(); tStartUpInfo.cb = Marshal.SizeOf(typeof(STARTUPINFO)); bool ChildProcStarted = CreateProcessAsUser( hToken, // Token of the logged-on user. ChildProcName, // Name of the process to be started. null, // Any command line arguments to be passed. IntPtr.Zero, // Default Process' attributes. IntPtr.Zero, // Default Thread's attributes. false, // Does NOT inherit parent's handles. 0, // No any specific creation flag. null, // Default environment path. null, // Default current directory. ref tStartUpInfo, // Process Startup Info. out tProcessInfo // Process information to be returned. ); if (ChildProcStarted) { // The child process creation is successful! // If the child process is created, it can be controlled via the out // param "tProcessInfo". For now, as we don't want to do any thing // with the child process, closing the child process' handles // to prevent the handle leak. CloseHandle(tProcessInfo.hThread); CloseHandle(tProcessInfo.hProcess); } else { // CreateProcessAsUser failed! } // Whether child process was created or not, close the token handle // and break the loop as processing for current active user has been done. CloseHandle(hToken); break; } else { // WTSQueryUserToken failed! } } else { // This Session is not active! } } // Free the memory allocated for the session info array. WTSFreeMemory(ppSessionInfo); } else { // WTSEnumerateSessions failed! } }
© Copyright 2014 - 2024 柏港建站平台 ejk5.com. 渝ICP备16000791号-4