Windows 服务:获取所有用户的进程,包括 MainWindowHandle

Posted

技术标签:

【中文标题】Windows 服务:获取所有用户的进程,包括 MainWindowHandle【英文标题】:Windows Service: Get processes for all users, including MainWindowHandle 【发布时间】:2020-06-18 04:15:51 【问题描述】:

我在 PowerShell 中编写了一个 Windows 服务。它运作良好,但我需要找到一个解决方案来解决一个主要限制。我需要列出所有带有 Windowed 应用程序的进程 - 这是用于被动应用程序计量(即每个登录用户打开和使用的应用程序)。

服务以Local System 运行。我可以看到所有进程,但由于服务位于非交互式桌面(会话 ID 0)中,我看不到 MainWindowTitle 或 MainWindowhandle,标题全为 null,句柄全为 0。

我尝试过使用Get-ProcessGet-CIMInstance Win32_Process[System.Diagnostics.Process]::GetProcesses()。这些都不起作用(我得到了所有进程,但数据已被编辑)。

我决定创建一个 C# 控制台应用程序,PowerShell 服务将执行该应用程序并从中收集响应。这有效,但仍然排除了“敏感”信息,因此关键属性 MainWindowhandle 始终为 0。

这里是 C# 控制台应用程序(它只是一个快速的测试工作):

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Security.Permissions;

namespace ProcessManager


    public class ProcessRecord
    
        // Auto-Initialized properties  
        public string Name  get; set; 
        public int MainWindowHandle  get; set; 
        public string WindowTitle  get; set; 
        public int SessionId  get; set; 
        public DateTime StartTime  get; set; 
    

    class Program
    
        [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
        [HostProtectionAttribute(SecurityAction.LinkDemand, SharedState = true, Synchronization = true, ExternalProcessMgmt = true, SelfAffectingProcessMgmt = true)]
        [PermissionSetAttribute(SecurityAction.InheritanceDemand, Name = "FullTrust")]
        static void Main(string[] args)
        
            listProcesses();
        

        public static void listProcesses()
        
            List<ProcessRecord> processesList = new List<ProcessRecord>;
            Process.GetProcesses().ToList().ForEach(p =>
            
                try 
                
                    processesList.Add(new ProcessRecord
                    
                        Name = p.ProcessName,
                        MainWindowHandle = (int) p.MainWindowHandle,
                        WindowTitle = p.MainWindowTitle,
                        SessionId = p.SessionId,
                        StartTime = p.StartTime
                    );
                
                catch (Win32Exception)
                
                    // Just ignoring this to avoid the Access Denied exception for low-level system processes
                
                
            );
            Console.WriteLine(JsonConvert.SerializeObject(processesList));
        
    

我尝试在本地管理员组中以本地用户身份运行该服务。出于绝望,我还尝试启用“允许服务与桌面交互”。

我不需要知道 MainWindowHandle,我只需要列出 MainWindowhandle 不为 0 的进程。不幸的是,我需要知道会话 ID。

我应该如何进行?答案是简单的“无法完成”,还是有一个顽皮的解决方法,例如冒充?

也许有一种更简单的方法可以列出用户打开的应用程序,而不必依赖MainWindowHandle != 0

感谢您的指点!

【问题讨论】:

感谢@vad,但问题是我在非交互式桌面中将其作为服务运行。 Get-process 将为所有进程返回 mainwindowhandle 为 0,因为出于安全原因,该属性不可读。 那么,您正在尝试查找所有非交互式进程,而不是专门针对您的工具?如果它只是为了你的工具,在创建过程中,捕获那里的信息。机器上的任何进程仍然应该有“StartInfo”。 --- docs.microsoft.com/en-us/dotnet/api/… --- docs.microsoft.com/en-us/windows/win32/api/winuser/… 我只能想象,感谢指导! 【参考方案1】:

如果您需要带有窗口应用程序的进程,您可以按属性过滤进程mainwindowhandle

Get-Process | Where-Object $_.mainwindowhandle -ne 0 | select ProcessName | ft -HideTableHeaders

【讨论】:

谢谢@vad,这是我尝试的第一件事。问题是我在非交互式桌面中将其作为服务运行。 Get-process 将所有进程的 mainwindowhandle 返回为 0,因为出于安全原因,该属性不可读。我确实在问题中明确了这一点?

以上是关于Windows 服务:获取所有用户的进程,包括 MainWindowHandle的主要内容,如果未能解决你的问题,请参考以下文章

Linux中查询所有用户进程的详细信息,包括后台进程。。。。

如何以与 Windows 服务不同的用户身份运行进程

应急响应——Windows入侵排查

Linux 进程管理

Linux下怎么使用任务管理器和进程管理

如何允许 SYNCHRONIZE 访问所有进程的权限