mcpField
D
DesktopManager Windows Verification

DesktopManager Windows Verification

本地服务
github.com/EvotecIT开发工具1074 天前更新

关于 DesktopManager Windows Verification

DesktopManager 是面向 Windows 桌面操作的工具集,提供 .NET 库、PowerShell 模块、CLI、MCP 服务和托盘应用。其 MCP 服务面向 Agent 自动化,采用先检查、再通过显式会话执行更改的安全模式。

主要功能

  1. 01查询和调整显示器与窗口布局
  2. 02管理壁纸、亮度和桌面配置文件
  3. 03查看音频、电源、会话与无线设备
  4. 04管理已保存的 Wi-Fi 配置文件
  5. 05通过共享核心提供多种操作界面
  6. 06MCP 自动化默认先检查

适用场景

  1. 01检查显示器和窗口状态
  2. 02保存并恢复工作站配置
  3. 03通过脚本或 CLI 管理桌面设置
  4. 04让 Agent 检查并执行桌面操作

MCP 相关

MCP 服务通过 stdio 为 Agent 提供桌面检查与自动化能力。其安全模式要求先检查,并通过显式服务器会话执行更改。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

暂未收录安装方式

我们还没有获取到这个服务的安装包或远程地址,请按项目 README 中的说明安装。

代码仓库
安装包
mcpbdesktopmanager-mcp-win-x64.mcpb

工具

还没有获取到工具列表

本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。

详细介绍

DesktopManager - C# 库和 PowerShell 模块

DesktopManager 是一款 Windows 桌面自动化工具包,提供 .NET 库、PowerShell 模块、CLI、MCP 服务和托盘应用。

.NET 库还提供 PortableDesktopService,可在 Windows、macOS、GNOME 和 KDE Plasma 上管理当前用户的壁纸、发现显示器并诊断会话。每个适配器都会报告其功能;窗口自动化、托盘应用、CLI 和现有 PowerShell 命令仍仅支持 Windows。 使用方法和平台限制请参阅便携式桌面集成。

nuget downloads nuget version

你也可以从 PowerShell Gallery 下载

PowerShell Gallery Version PowerShell Gallery Preview Version PowerShell Gallery Downloads

PowerShell Gallery Platform GitHub top language GitHub code size in bytes GitHub license

如果你想联系我,可以通过 Twitter 或 LinkedIn 联系。

Twitter Follow Blog evotec.xyz LinkedIn pklys Discord Threads @PrzemyslawKlys

项目简介

README 配图

DesktopManager 通过五种方式提供统一的 Windows 自动化核心:

  • C# 库,适用于 .NET 应用程序和服务
  • PowerShell 模块,适用于脚本和操作员工作流
  • CLI 可执行文件,适用于终端和 JSON 自动化
  • MCP 服务,适用于优先检查的 Agent 自动化
  • Windows 托盘应用,适用于日常快捷键和显示器操作

它具有以下功能:

  • 获取显示器信息
  • 获取显示设备信息
  • 获取壁纸信息
  • 设置壁纸
  • 获取/设置桌面背景色
  • 获取/设置显示器位置
  • 获取/设置窗口位置
  • 获取/设置窗口状态(最小化、最大化、还原)
  • 从所有显示器、单台显示器或自定义区域捕获桌面屏幕截图
  • 管理显示器亮度
  • 启动/停止/切换壁纸幻灯片
  • 跟踪壁纸历史记录
  • 调整显示器分辨率和方向
  • 在虚拟桌面上移动显示器
  • 保存和还原窗口布局
  • 将窗口贴靠到其他显示器或在显示器之间移动
  • 订阅分辨率、方向或显示变化
  • 通过定期输入操作,防止非活动窗口进入休眠
  • 管理窗口的保持活动会话
  • 在显示器、音频、个性化设置和任务栏之间保存和还原统一的工作站配置文件
  • 枚举 Core Audio 播放/采集终结点、更改音量和静音状态、设置默认角色,并监视终结点变化
  • 检查电源和交互式会话状态;锁定、注销、睡眠、休眠或保持有时限的防休眠租约
  • 捕获和还原个性化设置快照,并配置任务栏的可见性、位置和自动隐藏
  • 通过受支持的 Windows 无线电 API 枚举、监视并显式启用或禁用 Wi-Fi、Bluetooth、移动宽带和 FM 无线电
  • 列出已保存的 Windows Wi-Fi 配置文件,并连接到指定的已保存配置文件,无需扫描附近网络或公开凭据
  • 检查窗口所属的虚拟桌面,并通过公开的 Windows 虚拟桌面 API 将窗口移动到已知桌面
  • 通过有文档说明的 Windows 原生 API 检查和管理即插即用设备及驱动程序存储包
壁纸使用者

PowerBGInfo 等应用程序可以直接从库中读取显示器几何信息、 显示缩放比例和已登录会话用户:

using DesktopManager;

var monitors = new Monitors();
foreach (var display in monitors.GetMonitorSnapshots()) {
    Console.WriteLine($"{display.Index}: {display.DeviceName}, " +
        $"{display.Width} x {display.Height}, scale {display.Scale}");
}

var user = new DesktopSessionService().GetSessionUser();
Console.WriteLine(user?.AccountName ?? "Unknown");

即使调用方未启用 DPI 感知,快照也包含物理像素边界和每台显示器的 DPI。 调用线程的 DPI 上下文会被还原。索引描述当前显示拓扑;扩展坞连接或重新连接后,请重新读取。 会话主机上缺失的壁纸设备路径会予以保留。

Monitors.SetLogonWallpaperWithResult(imagePath) 可通过 Windows Runtime 为当前帐户设置锁屏壁纸,适用于 .NET Framework、现代 .NET 和 netstandard 使用者。结果会报告是否成功、使用的机制以及任何故障。回退到计算机策略需要显式设置 allowPolicyFallback: true 并提升权限。现有的 SetLogonWallpaper 方法仍会自动回退到策略。示例、操作系统要求、策略限制和会话部署行为请参阅 壁纸使用者 API。

桌面状态与控制

当你想在可重复使用的设置之间切换时,工作站配置文件是高级入口。它会捕获已连接显示器的模式和位置、显示器壁纸以及受支持的亮度/HDR 状态、活动音频终结点状态和默认角色、个性化设置及任务栏。应用配置文件时,会根据稳定标识匹配显示器,将显示更改集中执行,并在必需步骤失败时回滚所选部分。系统范围的个性化策略也会被捕获,但只有在明确请求时才会恢复。

Save-DesktopWorkstationProfile -Name 'office'
Get-DesktopAudioEndpoint -DataFlow Render -ActiveOnly
Get-DesktopPowerStatus
Get-DesktopSession
Get-DesktopRadio
Get-DesktopWifiProfile
Connect-DesktopWifiProfile -Name 'Corporate WiFi'
Get-DesktopDevice -Present -Problem
Get-DesktopDriverPackage
Restore-DesktopWorkstationProfile -Name 'office' -Confirm

相同的功能也可通过 CLI 使用:

desktopmanager workstation save --name office
desktopmanager audio list --flow render --active
desktopmanager system power
desktopmanager system session
desktopmanager radio list
desktopmanager wifi profiles
desktopmanager wifi connect --profile "Corporate WiFi"
desktopmanager device list --present --problem
desktopmanager driver list
desktopmanager workstation apply --name office

无线电控制有两个刻意分开的 API。RadioService 和常规的 radio list / radio set 命令使用受支持的 Windows.Devices.Radios 契约来控制单个无线电。全局飞行模式使用未公开的 Windows Shell COM 契约,因此它归属 ExperimentalAirplaneModeService,并且在 CLI 中需要 --experimental,在 PowerShell 中需要 -Experimental,在 MCP 中需要 --allow-experimental。

Wi-Fi 配置文件连接与无线电控制相互独立。WifiProfileService、Get-DesktopWifiProfile 和 desktopmanager wifi profiles 仅枚举 Windows 中已存储的配置文件。连接指定的配置文件时使用 Native Wi-Fi 配置文件 API 和 ACM 完成通知;它不会扫描附近的网络、返回 BSSID、公开配置文件 XML 或凭据,也不会查询涉及位置的当前连接详情。Windows 仍要求获得位置许可,才能扫描附近网络并使用相关的 Wi-Fi 信息 API。请参阅 Wi-Fi 访问和位置的 API 行为变更。

VirtualDesktopService 仅公开 Windows 的公共操作:检查顶层窗口是否位于当前桌面、获取其桌面 ID,以及将其移动到已知桌面 ID。桌面枚举、创建、重命名、切换和移除不会被作为受支持的 API 提供。

面向操作人员的较新 CLI 和 MCP 接口的补充文档:

应使用哪个接口?

接口最适用于典型入口
C# 库将 DesktopManager 嵌入你自己的 .NET 应用或服务DesktopManager.dll
PowerShell 模块脚本、操作人员、管理工作流、可重复的任务自动化Install-Module DesktopManager
CLI 可执行文件手动使用、Shell 自动化、JSON 输出和托管 MCPdesktopmanager.exe
MCP 服务通过 stdio 实现由 Agent 驱动的自动化,并采用先检查再操作的安全模型desktopmanager mcp serve
Windows 托盘应用日常热键、显示器绑定、HDR 控制、托盘运行时和按用户启动DesktopManager.App.exe

整体架构

DesktopManager 现在采用一个共享核心,并在其上提供多个面向操作人员的界面。

flowchart LR
    A["Your .NET app"] --> B["DesktopManager library"]
    C["PowerShell module"] --> B
    D["desktopmanager.exe CLI"] --> B
    E["MCP server"] --> D
    J["DesktopManager.App tray app"] --> B
    B --> F["Windows desktop APIs"]
    F --> G["Monitors / wallpapers / brightness"]
    F --> H["Windows / controls / input"]
    F --> I["Layouts / snapshots / targets"]

如需查看更完整的组件和请求流图,请参阅 Docs/DesktopManager.Architecture.md。

可以从以下角度理解其实际用法:

  • 将 DesktopManager 集成到自己的应用程序中时,使用库
  • 需要可脚本化的管理/操作自动化时,使用 PowerShell
  • 需要面向用户或支持 JSON 的命令界面时,使用 CLI
  • 需要 Agent 先检查、再通过显式服务器会话执行变更时,使用 MCP

常用入口

目标推荐入口
在自己的代码中添加 DesktopManager 功能引用 DesktopManager NuGet 包
从终端手动执行桌面操作desktopmanager.exe
每天从系统托盘运行 DesktopManagerDesktopManager.App.exe 或 DesktopManager MSI
在 PowerShell 脚本中使用DesktopManager PowerShell 模块
连接 Agent/工具层desktopmanager mcp serve
了解整体连接方式Docs/DesktopManager.Architecture.md

请求流概览

flowchart LR
    A["User, script, or agent"] --> B{"Surface"}
    B -->|".NET"| C["DesktopManager library"]
    B -->|"PowerShell"| D["Cmdlets"]
    B -->|"CLI"| E["desktopmanager.exe"]
    B -->|"MCP"| F["desktopmanager mcp serve"]
    B -->|"Tray app"| J["DesktopManager.App.exe"]

    D --> C
    E --> G["DesktopOperations"]
    F --> G
    J --> C
    G --> C
    C --> H["Win32, UI Automation, monitor, screenshot, and input services"]

重点在于,CLI、MCP 和 PowerShell 会复用相同的共享 C# 行为,以保持一致,而不是在每个界面中分别实现桌面逻辑。

可用的 PowerShell Cmdlet
Cmdlet描述
Get-DesktopMonitor获取显示器信息,并提供筛选选项
Get-DesktopWallpaper获取各显示器当前壁纸路径
Set-DesktopWallpaper从路径、URL 或流应用壁纸
Get-DesktopWallpaperHistory列出已存储的壁纸历史记录
Set-DesktopWallpaperHistory更新或清除壁纸历史记录文件
Get-DesktopSlideshow检查幻灯片放映图片、状态、选项和切换间隔
Set-DesktopSlideshowOptions更新幻灯片放映的随机播放行为和切换间隔
Start-DesktopSlideshow在各显示器上开始播放壁纸幻灯片
Stop-DesktopSlideshow停止当前正在运行的幻灯片放映
Step-DesktopSlideshow将幻灯片放映向前或向后切换
Get-DesktopBackgroundColor读取当前桌面背景颜色
Set-DesktopBackgroundColor更改桌面背景颜色
Get-DesktopBrightness读取显示器亮度级别
Set-DesktopBrightness设置显示器亮度级别
Set-DesktopPosition移动显示器的左上角坐标,且不更改分辨率
Set-DesktopResolution更改显示器分辨率或方向
Set-DefaultAudioDevice设置默认音频播放设备
Get-DesktopAudioEndpoint列出 Core Audio 渲染和采集端点及其音量、静音状态和默认角色
Set-DesktopAudioEndpoint设置端点音量、静音状态或选定的默认角色
Register-DesktopAudioEvent订阅端点、状态、属性和默认角色的更改
Save-DesktopWorkstationProfile将显示器、音频、个性化设置和任务栏捕获为一个命名配置文件
Get-DesktopWorkstationProfile列出或加载命名工作站配置文件
Restore-DesktopWorkstationProfile应用命名工作站配置文件,并提供匹配和回滚选项
Remove-DesktopWorkstationProfile删除命名工作站配置文件
Get-DesktopPowerStatus读取交流电源和电池状态
Get-DesktopSession读取当前交互式会话的身份、连接、锁定和空闲状态
Register-DesktopSessionEvent订阅重要的会话更改
Lock-DesktopSession锁定当前 Windows 会话
Exit-DesktopSession注销当前 Windows 会话,并支持确认
Start-DesktopKeepAwake获取有时限的系统/显示器防休眠租约
Suspend-DesktopSystem请求睡眠或休眠,并支持确认
Get-DesktopPersonalization捕获当前状态,或列出/加载已保存的个性化设置快照
Save-DesktopPersonalization保存命名个性化设置快照
Set-DesktopPersonalization应用明确指定的个性化设置
Restore-DesktopPersonalization恢复命名个性化设置快照
Remove-DesktopPersonalization删除命名个性化设置快照
Get-DesktopTaskbar列出任务栏及其显示器映射、可见性、边缘和边界
Set-DesktopTaskbarAutoHide设置明确的任务栏自动隐藏状态
Get-DesktopRadio通过受支持的 Windows 无线电 API 列出无线电设备
Set-DesktopRadio明确启用或禁用匹配的受支持无线电设备
Register-DesktopRadioEvent订阅受支持的无线电状态更改
Get-DesktopWifiProfile列出已保存的 Windows Wi-Fi 配置文件,不扫描附近网络
Connect-DesktopWifiProfile连接到指定的已保存 Windows Wi-Fi 配置文件
Get-DesktopAirplaneMode在明确确认后读取实验性的全局飞行模式状态
Set-DesktopAirplaneMode在明确确认后应用并验证实验性的全局飞行模式
Get-DesktopVirtualDesktop检查顶层窗口受支持的虚拟桌面状态
Move-DesktopWindowToVirtualDesktop将顶层窗口移动到已知的虚拟桌面 ID
Get-LogonWallpaper获取锁屏壁纸路径
Set-LogonWallpaper设置锁屏壁纸
Set-TaskbarPosition移动或隐藏任务栏
Invoke-DesktopMouseMove移动鼠标光标
Invoke-DesktopMouseClick模拟鼠标单击
Invoke-DesktopMouseScroll滚动鼠标滚轮
Invoke-DesktopScreenshot捕获显示器或区域的屏幕截图
Get-DesktopWindow枚举可见窗口
Get-DesktopWindowGeometry返回匹配窗口的外部窗口和客户区几何信息
Get-DesktopWindowControl枚举 Win32 或 UIA 窗口控件
Get-DesktopWindowControlDiagnostic说明 Win32 与 UIA 控件的发现方式和可操作性
Get-DesktopWindowProcessInfo返回匹配窗口的进程详情
Get-DesktopWindowTarget列出已保存的窗口相对目标,或根据实时窗口解析目标
Get-DesktopControlTarget列出已保存的控件目标,或根据实时窗口解析目标
Get-DesktopHostedSessionDiagnostic读取最新的托管会话输入诊断文件,或读取指定文件
Invoke-DesktopControlClick使用共享控件操作路由单击匹配的控件
Invoke-DesktopWindowClick单击窗口相对位置或已保存的窗口目标
Invoke-DesktopWindowDrag在窗口相对位置或已保存目标之间拖动
Invoke-DesktopWindowScroll在窗口相对位置或已保存目标处滚动
Send-DesktopControlKey向匹配的控件发送按键,而无需重新实现按键路由
Set-DesktopControlTarget保存可重复使用的控件选择器配置文件
Set-DesktopControlText直接向特定控件写入文本
Set-DesktopWindow移动、调整大小或控制窗口
Set-DesktopWindowSnap将窗口贴靠到常用位置
Set-DesktopWindowTarget保存可重复使用的窗口相对位置目标
Set-DesktopWindowText将文本粘贴或输入到窗口中
Wait-DesktopWindow等待窗口出现
Wait-DesktopWindowControl等待控件出现
Test-DesktopWindow验证窗口是否存在或是否与活动窗口匹配
Test-DesktopWindowControl验证控件是否存在
Start-DesktopWindowKeepAlive定期发送输入以保持窗口唤醒
Stop-DesktopWindowKeepAlive停止发送保活输入
Get-DesktopWindowKeepAlive列出已启用保活的窗口
Save-DesktopWindowLayout将当前窗口布局保存到文件
Restore-DesktopWindowLayout恢复已保存的窗口布局
Register-DesktopMonitorEvent订阅显示配置更改
Register-DesktopOrientationEvent订阅方向更改
Register-DesktopResolutionEvent订阅分辨率更改
Cmdlet 到 C# 方法映射

下表展示了每个 PowerShell cmdlet 背后最相关的 API 方法。

CmdletMain C# methods
Get-DesktopMonitorMonitors.GetMonitors
Get-DesktopWallpaperMonitors.GetWallpaper or Monitor.GetWallpaper
Set-DesktopWallpaperMonitors.SetWallpaper, Monitors.SetWallpaperFromUrl
Get-DesktopWallpaperHistoryWallpaperHistory.GetHistory
Set-DesktopWallpaperHistoryWallpaperHistory.SetHistory
Get-DesktopSlideshowMonitors.GetWallpaperSlideshow
Set-DesktopSlideshowOptionsMonitors.SetWallpaperSlideshowOptions
Start-DesktopSlideshowMonitors.StartWallpaperSlideshow
Stop-DesktopSlideshowMonitors.StopWallpaperSlideshow
Step-DesktopSlideshowMonitors.AdvanceWallpaperSlide
Get-DesktopBackgroundColorMonitors.GetBackgroundColor
Set-DesktopBackgroundColorMonitors.SetBackgroundColor
Get-DesktopBrightnessMonitors.GetMonitorBrightness
Set-DesktopBrightnessMonitors.SetMonitorBrightness
Set-DesktopPositionMonitor.SetMonitorPosition or Monitors.SetMonitorPosition
Set-DesktopResolutionMonitors.SetMonitorResolution, Monitors.SetMonitorOrientation
Set-DefaultAudioDeviceAudioService.SetDefaultAudioDevice
Get-LogonWallpaperMonitors.GetLogonWallpaper
Set-LogonWallpaperMonitors.SetLogonWallpaper
Set-TaskbarPositionTaskbarService.SetTaskbarPosition / SetTaskbarVisibility
Invoke-DesktopMouseMoveWindowManager.MoveMouse
Invoke-DesktopMouseClickWindowManager.ClickMouse
Invoke-DesktopMouseScrollWindowManager.ScrollMouse
Invoke-DesktopScreenshotScreenshotService.CaptureScreen, ScreenshotService.CaptureRegion
Get-DesktopWindowWindowManager.GetWindows / GetWindowsForProcess
Get-DesktopWindowGeometryDesktopAutomationService.GetWindowGeometry
Get-DesktopWindowControlDesktopAutomationService.GetControls
Get-DesktopWindowControlDiagnosticDesktopAutomationService.GetControlDiagnostics / GetControlTargetDiagnostics
Get-DesktopWindowProcessInfoWindowManager.GetWindowProcessInfo
Get-DesktopWindowTargetDesktopAutomationService.ListWindowTargets, GetWindowTarget, ResolveWindowTargets
Get-DesktopControlTargetDesktopAutomationService.ListControlTargets, GetControlTarget, ResolveControlTargets
Invoke-DesktopControlClickDesktopAutomationService.ClickControls / ClickControlTarget
Invoke-DesktopWindowClickDesktopAutomationService.ClickWindowPoint / ClickWindowTarget
Invoke-DesktopWindowDragDesktopAutomationService.DragWindowPoints / DragWindowTargets
Invoke-DesktopWindowScrollDesktopAutomationService.ScrollWindowPoint / ScrollWindowTarget
Send-DesktopControlKeyDesktopAutomationService.SendControlKeys / SendControlTargetKeys
Set-DesktopControlTargetDesktopAutomationService.SaveControlTarget
Set-DesktopControlTextDesktopAutomationService.SetControlText
Set-DesktopWindowWindowManager.SetWindowPosition, MoveWindowToMonitor, etc.
Set-DesktopWindowSnapWindowManager.SnapWindow
Set-DesktopWindowTargetDesktopAutomationService.SaveWindowTarget
Set-DesktopWindowTextWindowManager.TypeText, WindowManager.PasteText, WindowInputService
Wait-DesktopWindowDesktopAutomationService.WaitForWindows
Wait-DesktopWindowControlDesktopAutomationService.WaitForControls
Test-DesktopWindowDesktopAutomationService.WindowExists / ActiveWindowMatches
Test-DesktopWindowControlDesktopAutomationService.ControlExists
Start-DesktopWindowKeepAliveWindowKeepAlive.Start
Stop-DesktopWindowKeepAliveWindowKeepAlive.Stop or StopAll
Get-DesktopWindowKeepAliveWindowKeepAlive.ActiveHandles
Save-DesktopWindowLayoutWindowManager.SaveLayout
Restore-DesktopWindowLayoutWindowManager.LoadLayout
Register-DesktopMonitorEventMonitorWatcher.DisplaySettingsChanged
Register-DesktopOrientationEventMonitorWatcher.OrientationChanged
Register-DesktopResolutionEventMonitorWatcher.ResolutionChanged
安装

若要在 PowerShell 中使用,可从 PowerShell Gallery 安装

Install-Module DesktopManager -Force -Verbose

日常使用 Windows 托盘应用时,请在有可用版本时使用 DesktopManager MSI 发布工件。安装程序会创建“开始”菜单快捷方式,应用的“启动”开关会将当前用户设置为最小化到托盘启动。

从源代码构建应用和 MSI 时,请使用 PowerForge:

.\Build\Build-DesktopManagerApp.ps1
.\Build\Build-DesktopManagerApp-MSI.ps1
msiexec.exe /i .\Artefacts\PowerForge\Msi\DesktopManager.App\win-x64\net10.0-windows10.0.19041.0\PortableCompat\output\DesktopManager.msi
已验证的修改示例

如果你希望确认的不只是“调用没有抛出异常”,请优先同时使用 -Verify 和 -PassThru,这样 cmdlet 会返回观察到的后置条件。

# Verify a window move against the observed geometry
Set-DesktopWindow -Name "*Visual Studio Code*" -Left 0 -Top 0 -Width 1600 -Height 1200 -Verify -PassThru

# Verify exact text after a control text update
Set-DesktopControlText -Control $ctrl -Text "Hello world" -Verify -PassThru

# Verify the observed check state
Set-DesktopControlCheck -Control $checkbox -Check $true -Verify -PassThru

# Return a structured record after a control click
Invoke-DesktopControlClick -Control $button -PassThru

# Return a structured record after sending keys
Send-DesktopControlKey -Control $editor -Keys @([DesktopManager.VirtualKey]::VK_RETURN) -PassThru

验证行为会根据操作类型而有所不同:

  • 对于窗口修改,如果后置条件有意义,则会验证几何信息、状态、置顶、关闭或前台条件
  • Set-DesktopControlText -Verify 会在控件可重新查询时验证观察到的文本/值
  • Set-DesktopControlCheck -Verify 会验证观察到的勾选状态
  • 控件点击/按键操作会返回准确的存在状态和前台证据;如果精确的语义验证会造成误导,则不会进行此类验证
测试说明

为避免本地开发期间打开窗口或更改桌面,UI 影响类测试默认选择性启用。使用以下环境变量控制行为:

  • RUN_UI_TESTS=true(或 DESKTOPMANAGER_RUN_UI_TESTS=true)会启用顶层 UI 测试套件。
  • RUN_OWNED_WINDOW_UI_TESTS=true(或 DESKTOPMANAGER_RUN_OWNED_WINDOW_UI_TESTS=true)会启用使用仓库创建的测试窗口的自有窗口 UI 测试。
  • RUN_DESTRUCTIVE_UI_TESTS=true(或 DESKTOPMANAGER_RUN_DESTRUCTIVE_UI_TESTS=true)会启用针对仓库创建的测试窗口进行移动、调整大小、隐藏、贴靠和透明度更改等自有窗口修改测试。
  • RUN_FOREGROUND_UI_TESTS=true(或 DESKTOPMANAGER_RUN_FOREGROUND_UI_TESTS=true)会启用会主动抢占前台焦点的测试,即使这些测试只针对仓库创建的测试窗口。
  • RUN_SYSTEM_UI_TESTS=true(或 DESKTOPMANAGER_RUN_SYSTEM_UI_TESTS=true)会启用系统范围的桌面更改,例如壁纸、亮度、分辨率及其他可能影响当前会话的显示器级修改。
  • RUN_EXTERNAL_UI_TESTS=true(或 DESKTOPMANAGER_RUN_EXTERNAL_UI_TESTS=true)会启用实时外部应用 UI 测试和 MCP 端到端测试框架,这些测试会启动真实的桌面应用。
  • RUN_EXPERIMENTAL_UI_TESTS=true(或 DESKTOPMANAGER_RUN_EXPERIMENTAL_UI_TESTS=true)会启用实验性实时 UI 测试框架,适用于手动验证,但不属于稳定回归测试套件。
  • SKIP_UI_TESTS=true(或 DESKTOPMANAGER_SKIP_UI_TESTS=true)会强制跳过 UI 测试,即使其他位置已启用这些测试。

自有 WinForms 测试装置会在不激活窗口的情况下显示。显式激活窗口或依赖前台焦点的测试还需要启用前台门控。使用桌面期间,请保持 RUN_FOREGROUND_UI_TESTS 和 DESKTOPMANAGER_RUN_FOREGROUND_UI_TESTS 禁用;仅在专门的交互式运行期间启用该部分测试。

这些门控会按预期组合使用:

门控允许的操作典型影响
RUN_UI_TESTS仅启用顶层 UI 测试套件低
RUN_OWNED_WINDOW_UI_TESTS仓库自有的 WinForms/WPF 测试框架窗口低到中
RUN_DESTRUCTIVE_UI_TESTS修改自有测试框架窗口中到高
RUN_FOREGROUND_UI_TESTS主动获取前台焦点的测试中到高
RUN_SYSTEM_UI_TESTS系统范围的桌面更改高
RUN_EXTERNAL_UI_TESTS启动真实的桌面应用中到高
RUN_EXPERIMENTAL_UI_TESTS实验性实时测试框架不定
# Run owned-window UI tests
$env:RUN_UI_TESTS = "true"
$env:RUN_OWNED_WINDOW_UI_TESTS = "true"

# Run repo-owned window mutation tests
$env:RUN_DESTRUCTIVE_UI_TESTS = "true"

# Run tests that intentionally steal foreground focus
$env:RUN_FOREGROUND_UI_TESTS = "true"

# Run system-wide desktop mutations
$env:RUN_SYSTEM_UI_TESTS = "true"

# Run live external-application harnesses
$env:RUN_EXTERNAL_UI_TESTS = "true"

# Run experimental live UI harnesses
$env:RUN_EXPERIMENTAL_UI_TESTS = "true"

# Force skip
$env:SKIP_UI_TESTS = "true"

# Run the repo-owned window mutation slice
dotnet test Sources/DesktopManager.Tests/DesktopManager.Tests.csproj -f net8.0-windows10.0.19041.0 --no-build --filter "WindowPositionTests|WindowStateHelpersTests|WindowVisibilityTests|WindowTransparencyTests|WindowStyleModificationTests|WindowLayoutTests"

# Run the foreground-window slice
dotnet test Sources/DesktopManager.Tests/DesktopManager.Tests.csproj -f net8.0-windows10.0.19041.0 --no-build --filter "DesktopAutomationAssertionTests|WindowManagerFilterTests|WindowTopMostActivationTests"

# Run the live MCP desktop pack backed by the repo-owned DesktopManager.TestApp harness
dotnet test Sources/DesktopManager.Tests/DesktopManager.Tests.csproj -f net8.0-windows10.0.19041.0 --no-build --filter "McpServer_TestApp"

如果托管会话或实验性实时测试框架因焦点或可发现性始终不稳定而跳过测试,现在会生成结构化诊断信息和工件,而不再静默失败。有关托管会话工件流程和门控指南,请参阅 Docs/Build.Runbook.md。

用法
C# 示例

DesktopManager.Example 项目包含更多示例。默认模式为只读;运行修改演示需要显式指定 --run-mutations 选项。

var monitors = new Monitors();
foreach (var monitor in monitors.GetMonitors(connectedOnly: true)) {
    MonitorPosition bounds = monitor.GetMonitorPosition();
    Console.WriteLine($"{monitor.Index}: {monitor.DeviceName} at {bounds.Left},{bounds.Top} " +
        $"({bounds.Right - bounds.Left}x{bounds.Bottom - bounds.Top})");
}

// Moving a monitor changes only its top-left coordinate. Change resolution separately.
// monitors.SetMonitorPosition(selected.DeviceId, left: -1920, top: 0);
C# 示例 - 获取/设置窗口位置
var manager = new WindowManager();
WindowInfo? window = manager.GetWindows(processName: "notepad").FirstOrDefault();
if (window != null) {
    manager.SetWindowPosition(window, left: 100, top: 100, width: 1000, height: 700);
    manager.ActivateWindow(window);
}
平台说明

获取窗口样式时,库会使用一个辅助方法:在 32 位进程中调用 GetWindowLong,在 64 位进程中调用 GetWindowLongPtr。该 方法返回 IntPtr,因此调用方应将该值转换为 相应的数值类型。

PowerShell 示例 - 获取显示器信息
Get-DesktopMonitor | Format-Table

Get-DesktopWallpaper -Index 0

Set-DesktopWallpaper -Index 1 -WallpaperPath "C:\Wallpapers\Landscape.jpg" -Position Fit
Set-DesktopWallpaper -Index 0 -WallpaperPath "C:\Wallpapers\Portrait.jpg"
Set-DesktopBackgroundColor -Color 0x0000FF
Get-DesktopBackgroundColor
PowerShell 示例 - 壁纸幻灯片
Start-DesktopSlideshow -ImagePath 'C:\Wallpapers\img1.jpg','C:\Wallpapers\img2.jpg' -Shuffle -SlideshowTick 300000
Get-DesktopSlideshow
Set-DesktopSlideshowOptions -NoShuffle -SlideshowTick 600000
Step-DesktopSlideshow -Direction Forward
Stop-DesktopSlideshow
$Desktop1 = Get-DesktopMonitor
$Desktop1 | Format-Table

$Desktop2 = Get-DesktopMonitor -ConnectedOnly
$Desktop2 | Format-Table

$Desktop3 = Get-DesktopMonitor -PrimaryOnly
$Desktop3 | Format-Table

$Desktop4 = Get-DesktopMonitor -Index 1
$Desktop4 | Format-Table

$Desktop5 = Get-DesktopMonitor -DeviceName "\\.\DISPLAY2"
$Desktop5 | Format-Table
PowerShell 示例 - 设置显示器位置
$Desktop2 = Get-DesktopMonitor -ConnectedOnly
$Desktop2 | Format-Table

Set-DesktopPosition -Index 0 -Left -3840 -Top 0 -WhatIf
Set-DesktopPosition -Index 1 -Left 0 -Top 0 -WhatIf
PowerShell 示例 - 获取/设置窗口位置
Get-DesktopWindow | Format-Table *
$np = Start-Process notepad -PassThru
Get-DesktopWindow -ProcessId $np.Id
$np | Stop-Process

image

Set-DesktopWindow -Name '*Zadanie - Notepad' -Height 800 -Width 1200 -Left 100
Set-DesktopWindow -Name '*Zadanie - Notepad' -State Maximize
Set-DesktopWindowText -Name '*Notepad*' -Text 'Hello world'
# Send Ctrl+S to Notepad
$notepad = Get-DesktopWindow -Name '*Notepad*'
Invoke-DesktopKeyPress -Window $notepad -Keys @(
    [DesktopManager.VirtualKey]::VK_CONTROL,
    [DesktopManager.VirtualKey]::VK_S
)
# See Examples/KeyboardActions.ps1
PowerShell 示例 - 激活窗口并将其设为最顶层
Set-DesktopWindow -Name '*Notepad*' -TopMost -Activate
C# 示例 - 激活窗口并将其设为最顶层
var manager = new WindowManager();
var window = manager.GetWindows().First();
manager.SetWindowTopMost(window, true);
manager.ActivateWindow(window);
#### Example in PowerShell - Monitoring Display Changes

Use `Register-DesktopMonitorEvent` to react when monitors are plugged in or the display configuration changes.

```powershell
Register-DesktopMonitorEvent -Duration (New-TimeSpan -Seconds 30) -Action { Write-Host 'Display settings changed' }

使用 Register-DesktopOrientationEvent 或 Register-DesktopResolutionEvent,分别处理方向或分辨率变化。

Register-DesktopResolutionEvent -Duration (New-TimeSpan -Seconds 30) -Action { Write-Host 'Resolution changed' }
Register-DesktopOrientationEvent -Duration (New-TimeSpan -Seconds 30) -Action { Write-Host 'Orientation changed' }
C# 示例 - 监控显示器变化

应用程序可以订阅 MonitorWatcher.DisplaySettingsChanged 事件。

MonitorWatcherExample.Run(TimeSpan.FromSeconds(30));
PowerShell 示例 - 保存和还原窗口布局

如需可选的虚拟桌面分配、固定项、资源管理器文件夹以及显式的逐桌面壁纸还原,请参阅工作区恢复。

Save-DesktopWindowLayout -Path './layout.json'
# ... move windows around ...
Restore-DesktopWindowLayout -Path './layout.json' -Validate
C# 示例 - 保存和还原窗口布局
var manager = new WindowManager();
manager.SaveLayout("layout.json");
// ... move windows around ...
manager.LoadLayout("layout.json", validate: true);

布局还原时,每个实时窗口最多使用一次,并跳过目标不明确或缺失的情况。保存的布局包含进程名和原生类名,因此可以匹配已重启的应用程序,而无需仅依赖其标题。旧版文件仍使用精确的进程 ID/标题匹配;已禁用仅按标题和仅按进程的回退匹配。使用 PlanLayout 检查匹配结果,并使用 ApplyLayout 获取每个窗口的处理结果:

var layout = JsonSerializer.Deserialize<WindowLayout>(File.ReadAllText("layout.json"))!;
WindowLayoutPlan plan = manager.PlanLayout(layout);
foreach (WindowLayoutMatch match in plan.Windows) {
    Console.WriteLine($"{match.SavedWindow.Title}: {match.Status} ({match.CandidateCount} candidates)");
}
IReadOnlyList<WindowLayoutApplyResult> results = manager.ApplyLayout(layout);
PowerShell 示例 - 窗口保持活动状态 Cmdlet
# Keep Notepad alive for one minute
Start-DesktopWindowKeepAlive -Name '*Notepad*' -Interval 00:01:00

# List active sessions
Get-DesktopWindowKeepAlive

# Stop the session
Stop-DesktopWindowKeepAlive -Name '*Notepad*'
# Keep Notepad and Calculator alive
Start-DesktopWindowKeepAlive -Name '*Notepad*'
Start-DesktopWindowKeepAlive -Name '*Calculator*' -Interval 00:00:30
Start-Sleep -Seconds 5
Get-DesktopWindowKeepAlive | Format-Table Title, Handle
Stop-DesktopWindowKeepAlive -All
# Monitor RDP windows
Start-DesktopWindowKeepAlive -Name '*RDP*' -Interval 00:00:30
1..3 | ForEach-Object {
    Start-Sleep -Seconds 10
    Get-DesktopWindowKeepAlive | ForEach-Object { "Active: $($_.Title)" }
}
Stop-DesktopWindowKeepAlive -Name '*RDP*'
C# 示例 - 窗口保持活动状态
var manager = new WindowManager();
var notepad = manager.GetWindows("*Notepad*").FirstOrDefault();
if (notepad != null) {
    WindowKeepAlive.Instance.Start(notepad, TimeSpan.FromMinutes(1));
}
foreach (var window in new WindowManager().GetWindows("*Chrome*")) {
    WindowKeepAlive.Instance.Start(window, TimeSpan.FromSeconds(30));
}
foreach (var handle in WindowKeepAlive.Instance.ActiveHandles) {
    Console.WriteLine($"Keeping {handle} alive");
}
WindowKeepAlive.Instance.StopAll();
C# API 亮点

DesktopManager 作为 .NET 库发布,目标框架为 net472、netstandard2.0、net8.0-windows10.0.19041.0 和 net10.0-windows10.0.19041.0。主要入口点包括:

  • Monitors,用于显示器枚举、壁纸管理、亮度、分辨率、方向和幻灯片控制。
  • WindowManager,用于窗口枚举、定位、调整大小和布局持久化。
  • MonitorWatcher,用于在显示设置变化时接收事件。
  • ScreenshotService,用于截取桌面或自定义区域。
  • WorkstationProfileService 和 WorkstationProfileStore,用于管理完整的具名工作站状态。
  • AudioService 和 AudioEndpointWatcher,用于 Core Audio 终结点、默认角色、音量、静音和变更。
  • SystemPowerService、DesktopSessionService 和 DesktopSessionWatcher,用于电源和会话状态/操作。
  • PersonalizationService、PersonalizationStateStore 和 TaskbarService,用于可还原的用户设置和任务栏。
  • RadioService,用于受支持的单个无线电操作;ExperimentalAirplaneModeService 用于需单独确认的未公开全局开关。
  • WifiProfileService,用于已保存配置文件的清单,以及精确连接到指定配置文件,而不扫描附近网络。
  • VirtualDesktopService,用于受支持的窗口到桌面操作。
输入、等待与提供程序运行状况

TypeText 和 PasteText 会在可编辑控件的当前选区插入内容。它们不会为了修复意外结果而替换控件的整个值。后台文本发送优先使用目标中已聚焦的编辑器;如果没有编辑器处于聚焦状态,且存在多个符合条件的编辑器,则会拒绝操作。需要替换内容时,请使用 WindowControlService.SetText。粘贴、原生点击和字符消息都只会发送一次。仅当 SendInput 确认未发送任何输入时,才会应用 InputRetryCount。NativeOperationOutcomeUnknownException 表示目标可能已经发生变化;在决定是否重试前,请先检查其状态。即使发送失败,也会恢复请求的焦点和剪贴板文本。

所有库目标的异步等待都支持取消。超时时间为零时,将无限期等待,直到出现匹配项或收到取消请求:

using var cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(10));
WindowInfo window = await manager.WaitWindowAsync("*Notepad*", cancellationToken: cancellation.Token);

UI Automation 会为每个目标进程使用单独的 STA 工作线程,最多 16 个工作线程,每个工作线程最多排队 64 项操作。每个工作线程最多允许 64 个活动事件订阅,并预留清理容量,因此操作队列已满时也不会丢失清理操作。只要还有可用容量,一个提供程序发生阻塞不会影响其他进程。进行中的原生调用无法安全取消或重放,并会在返回前占用其工作线程。DesktopAutomationDiagnostics.GetUiAutomationHealth() 无需联系提供程序即可报告待处理工作和阻塞调用。工作线程的关闭有时间上限;达到工作线程或队列上限时,新工作将失败。

窗口捕获来源信息

CaptureWindow 保留其桌面回退行为。CaptureWindowDetailed 默认严格捕获窗口,并记录后端、实际屏幕边界、暗像素观测结果和回退原因。暗色图像可能是正常情况;严格模式会保留这些像素。桌面回退图像可能包含遮挡应用程序的像素。

using WindowCaptureResult capture = ScreenshotService.CaptureWindowDetailed(window.Handle);
Console.WriteLine($"{capture.Backend}: {capture.ScreenBounds}");
capture.Bitmap.Save("window.png");

传入 new WindowCaptureOptions { AllowDesktopFallback = true },即可选择启用可见桌面回退。DesktopAutomationService 捕获对象以及 CLI/MCP 截图结果也会公开捕获后端和回退原因。稀疏暗图像采样和视觉差异采样会直接读取已锁定的像素,避免创建完整的图像托管副本;模板匹配仍会保留其密集像素缓冲区。

需要重启的显示请求

当 Windows 接受了需要系统重启的显示请求时,SetMonitorDisplayModeDetailed 会返回 RestartRequired。现有的 void SetMonitorDisplayMode 方法在出现此结果时会抛出 DisplayRestartRequiredException。对于此请求,工作站配置文件结果会报告 Succeeded = false 和 RestartRequired = true。PowerShell 和托盘应用会显示警告;CLI JSON 和 MCP 结果会保留重启要求。没有任何 API 会自动重启 Windows。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。