Windows 10中SessionEnv服务无法停止的技术问题求助
问题描述
工厂设备操作时,需在手动校准阶段禁用远程桌面(RDP/VNC)以保障安全。开发的控制程序在Windows XP/7上运行正常,但在Windows 10中出现异常:
- 停止
SessionEnv服务时,状态卡在Stopping无法变为Stopped,随后报错Cannot open SessionEnv service on computer - 仅能通过终止
Service Host: Remote Desktop Services进程恢复 - 特殊现象:通过Visual Studio启动程序时一切正常,直接运行
bin/Debug下的程序则触发问题
涉及服务:
SessionEnvTermService
启用/禁用服务的核心代码如下:
启用服务代码
List<string> service_name = new List<string>() { "SessionEnv", "TermService" }; private void Start_Click(object sender, RoutedEventArgs e) { try { if (!windows.Contains("Windows XP")) { foreach (var service in service_name) { ServiceController sc = new ServiceController(service); status = Get_Status(service); if (status == "Running") { continue; } else if (status == "Stopped") { sc.Start(); } } count_running = 2; count_stopped = 0; } if (vnc_installed == true) { Start_VNC(); } ni.ShowBalloonTip(500, "Remote Desktop Enable/Disable Application", "Remote Desktop Connections are enabled", ToolTipIcon.Info); startup_status = "Open"; File.WriteAllText("c:\\temp\\Startup.txt", startup_status); } catch (Exception ex) { System.Windows.MessageBox.Show(ex.Message); } }
禁用服务代码
private void Stop_Click(object sender, RoutedEventArgs e) { try { if (!windows.Contains("Windows XP")) { foreach (var service in service_name) { ServiceController sc = new ServiceController(service); status = Get_Status(service); if (status == "Running") { sc.Stop(); } else if (status == "Stopped" ) { continue; } } count_running = 0; count_stopped = 2; } if (vnc_installed == true) { Close_VNC(); } ni.ShowBalloonTip(500, "Remote Desktop Enable/Disable Application", "Remote Desktop Connections are disabled", ToolTipIcon.Info); startup_status = "Close"; File.WriteAllText("c:\\temp\\Startup.txt", startup_status); } catch (Exception ex) { System.Windows.MessageBox.Show(ex.Message); } }
解决方案
1. 添加管理员权限声明
Visual Studio默认以管理员权限启动程序,而直接运行bin/Debug的程序无此权限,导致服务操作失败。需为程序添加权限声明:
- 右键项目→添加→新建项→选择「应用程序清单文件」(若已存在则跳过)
- 修改
<requestedExecutionLevel>节点为:<requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> - 重新编译程序,运行时会自动请求管理员权限
2. 调整服务停止顺序并等待状态变更
Windows 10中SessionEnv服务依赖TermService,直接停止会导致服务挂起。需调整停止顺序,并等待服务状态完成:
private void Stop_Click(object sender, RoutedEventArgs e) { try { if (!windows.Contains("Windows XP")) { // 先停止SessionEnv,再停止TermService foreach (var service in new List<string>{"SessionEnv", "TermService"}) { ServiceController sc = new ServiceController(service); var currentStatus = sc.Status; if (currentStatus == ServiceControllerStatus.Running) { sc.Stop(); // 等待服务停止,超时30秒 try { sc.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(30)); } catch (TimeoutException) { // 超时后强制结束服务宿主进程 KillServiceHost(sc.ServiceName); } } } count_running = 0; count_stopped = 2; } // 原有VNC关闭、提示、文件写入代码不变 } catch (Exception ex) { System.Windows.MessageBox.Show(ex.Message); } } // 根据服务名找到对应的宿主进程并终止 private void KillServiceHost(string serviceName) { using (var sc = new ServiceController(serviceName)) { int processId = GetServiceProcessId(sc.ServiceHandle); if (processId != 0) { try { Process.GetProcessById(processId).Kill(); } catch (Exception ex) { MessageBox.Show($"无法终止进程: {ex.Message}"); } } } } // P/Invoke获取服务对应的进程ID [DllImport("advapi32.dll", SetLastError = true)] private static extern int GetServiceProcessId(IntPtr hService, out int processId); private int GetServiceProcessId(IntPtr serviceHandle) { int processId; GetServiceProcessId(serviceHandle, out processId); return processId; }
3. 清理残留远程桌面会话
Win10中未关闭的远程会话会导致SessionEnv服务无法正常停止,可在停止服务前先断开所有远程会话:
// 断开所有远程桌面会话 private void DisconnectAllRdpSessions() { ProcessStartInfo psi = new ProcessStartInfo { FileName = "query.exe", Arguments = "session", RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true }; using (Process process = Process.Start(psi)) { string output = process.StandardOutput.ReadToEnd(); var lines = output.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries); foreach (var line in lines.Skip(1)) // 跳过表头 { var parts = line.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); if (parts.Length >= 2 && parts[0] != "console") // 跳过本地控制台会话 { string sessionId = parts[0]; Process.Start("logoff.exe", sessionId).WaitForExit(); } } } }
在Stop_Click方法开头调用DisconnectAllRdpSessions()后再执行服务停止逻辑。
内容的提问来源于stack exchange,提问作者dadou
相关产品推荐
相关产品推荐

