PowerShell 技能连载 - Windows Admin Center 自动化

适用于 PowerShell 5.1 及以上版本

Windows Admin Center(WAC)是微软推出的基于 Web 的服务器管理平台,通过浏览器即可完成对 Windows Server 的日常运维操作。与传统的远程桌面管理不同,WAC 采用网关架构,运维人员只需要在一个入口就能管理数据中心内的多台服务器和集群,涵盖事件日志、性能监视、证书管理、文件服务、Hyper-V 虚拟机等核心功能模块。

在企业实际部署中,WAC 网关的安装、证书配置、角色权限设置以及受管节点的批量导入,往往需要在多台服务器上重复执行。纯手工配置不仅耗时,还容易遗漏关键步骤。通过 PowerShell 脚本化这些部署和管理流程,可以确保环境的一致性,也方便在灾难恢复或扩容场景中快速重建管理平台。

本文将从三个维度介绍 WAC 的自动化实践:首先是网关的安装与初始配置,其次是受管连接的批量管理与分组,最后是 WAC 扩展开发的入门知识,帮助你掌握将 WAC 深度集成到运维体系中的方法。

WAC 安装与网关配置

在生产环境中部署 WAC 时,需要完成软件安装、SSL 证书绑定、端口配置以及访问权限设置等一系列步骤。以下脚本将这些操作封装为可重复执行的自动化流程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# 定义 WAC 安装参数
$wacInstallerPath = "C:\Install\WindowsAdminCenterPreview.msi"
$gatewayPort = 443
$certThumbprint = "A1B2C3D4E5F6789012345678901234567890ABCD"
$smiEnabled = $true

# 检查 WAC 是否已安装
$wacProduct = Get-WmiObject -Class Win32_Product |
Where-Object { $_.Name -like "*Windows Admin Center*" }

if ($null -eq $wacProduct) {
Write-Output "正在安装 Windows Admin Center..."

# 构建 MSI 安装参数
$msiArgs = @(
"/i", $wacInstallerPath
"/qn"
"SME_PORT=$gatewayPort"
"SSL_CERTIFICATE_OPTION=installed"
"THUMBPRINT=$certThumbprint"
"SME_INCLUDE_MANAGEMENT_TOOLS=$smiEnabled"
)

# 执行静默安装
$process = Start-Process -FilePath "msiexec.exe" `
-ArgumentList $msiArgs `
-Wait -PassThru

if ($process.ExitCode -eq 0) {
Write-Output "WAC 安装成功"
} else {
Write-Error "WAC 安装失败,退出代码:$($process.ExitCode)"
}
} else {
Write-Output "WAC 已安装,版本:$($wacProduct.Version)"
}

# 验证网关服务状态
$service = Get-Service -Name "ServerManagementGateway" -ErrorAction SilentlyContinue

if ($service.Status -eq "Running") {
Write-Output "WAC 网关服务运行正常(端口:$gatewayPort)"
} else {
Write-Output "正在启动 WAC 网关服务..."
Start-Service -Name "ServerManagementGateway"
}

# 配置角色权限(将安全组映射到 WAC 管理角色)
$gatewayServer = $env:COMPUTERNAME
$adminGroup = "CONTOSO\WAC-Admins"
$userGroup = "CONTOSO\WAC-Users"

# 使用 WAC 的配置命令行工具设置访问权限
$configTool = "${env:ProgramFiles}\Windows Admin Center\ConfigureWAC.exe"

if (Test-Path $configTool) {
# 设置管理员组(完整权限)
$null = & $configTool setRole `
-Role Administrators `
-Group $adminGroup 2>&1

# 设置只读用户组
$null = & $configTool setRole `
-Role Users `
-Group $userGroup 2>&1

Write-Output "角色权限配置完成"
Write-Output " 管理员组:$adminGroup"
Write-Output " 只读用户组:$userGroup"
}

# 输出网关访问地址
$fqdn = [System.Net.Dns]::GetHostEntry($gatewayServer).HostName
Write-Output "网关访问地址:https://$fqdn"

执行结果示例:

1
2
3
4
5
6
7
正在安装 Windows Admin Center...
WAC 安装成功
WAC 网关服务运行正常(端口:443)
角色权限配置完成
管理员组:CONTOSO\WAC-Admins
只读用户组:CONTOSO\WAC-Users
网关访问地址:https://SRV-MGMT01.contoso.com

这段脚本涵盖了 WAC 部署的完整流程:首先检查是否已安装以避免重复操作,然后通过 msiexec 静默安装并传入端口、证书指纹等参数。安装完成后验证网关服务状态,并通过配置工具将 Active Directory 安全组映射到 WAC 的内置角色。将此脚本纳入服务器初始化流水线后,新建的管理服务器可以在几分钟内完成 WAC 的部署和配置。

管理 WAC 连接与批量导入

WAC 网关部署完成后,下一步是将需要管理的服务器注册到网关中。在大型环境中可能有数百台服务器需要纳入管理,手动逐台添加显然不现实。以下脚本演示如何从不同数据源批量导入服务器连接,并按业务分组进行组织。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# WAC 网关地址
$gateway = "https://wac.contoso.com"

# 方法一:从 Active Directory 获取服务器列表
Import-Module ActiveDirectory

$serverOUs = @{
"域控制器" = "OU=Domain Controllers,DC=contoso,DC=com"
"文件服务器" = "OU=File Servers,OU=Servers,DC=contoso,DC=com"
"Web 服务器" = "OU=Web Servers,OU=Servers,DC=contoso,DC=com"
"数据库服务器" = "OU=DB Servers,OU=Servers,DC=contoso,DC=com"
}

$allConnections = @()

foreach ($ouName in $serverOUs.Keys) {
$ouPath = $serverOUs[$ouName]

# 查询 OU 下启用的计算机账户
$computers = Get-ADComputer -Filter { Enabled -eq $true } `
-SearchBase $ouPath `
-Properties Name, DNSHostName, OperatingSystem

foreach ($computer in $computers) {
$allConnections += [PSCustomObject]@{
Name = $computer.Name
FQDN = $computer.DNSHostName
Type = "Server"
Group = $ouName
OS = $computer.OperatingSystem
}
}
}

Write-Output "从 AD 发现 $($allConnections.Count) 台服务器"

# 方法二:从 CSV 文件补充导入(适用于工作组服务器)
$csvPath = "C:\Config\WorkgroupServers.csv"

if (Test-Path $csvPath) {
$csvServers = Import-Csv -Path $csvPath -Encoding UTF8

foreach ($srv in $csvServers) {
$allConnections += [PSCustomObject]@{
Name = $srv.Name
FQDN = $srv.IPAddress
Type = "Server"
Group = $srv.Group
OS = "Workgroup Server"
}
}

Write-Output "从 CSV 补充导入 $($csvServers.Count) 台工作组服务器"
}

# 批量添加连接到 WAC 网关
$addedCount = 0
$failedCount = 0

foreach ($conn in $allConnections) {
try {
# 构造连接添加请求
$body = @{
name = $conn.Name
type = $conn.Type
group = $conn.Group
target = $conn.FQDN
} | ConvertTo-Json

$uri = "$gateway/api/connections"
$null = Invoke-RestMethod -Uri $uri -Method Post `
-Body $body -ContentType "application/json" `
-UseDefaultCredentials -SkipCertificateCheck

$addedCount++
} catch {
Write-Warning "添加失败:$($conn.Name) - $($_.Exception.Message)"
$failedCount++
}
}

Write-Output "`n导入结果汇总:"
Write-Output " 成功:$addedCount 台"
Write-Output " 失败:$failedCount 台"
Write-Output " 总计:$($allConnections.Count) 台"

# 按分组统计
$allConnections | Group-Object -Property Group |
ForEach-Object {
[PSCustomObject]@{
分组 = $_.Name
数量 = $_.Count
}
} | Format-Table -AutoSize

执行结果示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
从 AD 发现 23 台服务器
从 CSV 补充导入 5 台工作组服务器

导入结果汇总:
成功:27 台
失败:1 台
总计:28 台

分组 数量
---- ----
域控制器 3
文件服务器 6
Web 服务器 8
数据库服务器 6
外围服务器 5

脚本展示了两种服务器数据源的整合方式:Active Directory OU 查询适合域内服务器,CSV 导入适合工作组或云端服务器。所有服务器信息统一汇总后,通过 REST API 批量注册到 WAC 网关,并按业务归属进行分组。这种分组方式在 WAC 界面中会以树形结构呈现,运维人员可以快速定位到特定业务线下的所有服务器。

WAC 扩展开发基础

WAC 支持通过扩展来增强其功能。扩展本质上是一个基于 Angular 框架的 Web 应用,通过 WAC 提供的 SDK 与网关后端通信。以下示例演示如何使用 PowerShell 辅助创建 WAC 扩展项目,并调用 WAC 的 REST API 实现自定义管理功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# 第一步:准备扩展开发环境
$extensionName = "custom-disk-monitor"
$extensionDir = "C:\WACExtensions\$extensionName"

# 创建扩展项目目录结构
$directories = @(
"$extensionDir\src"
"$extensionDir\src\components"
"$extensionDir\src\assets"
"$extensionDir\manifest"
)

foreach ($dir in $directories) {
$null = New-Item -Path $dir -ItemType Directory -Force
}

Write-Output "扩展项目目录已创建:$extensionDir"

# 生成扩展清单文件
$manifest = @{
name = $extensionName
displayName = "自定义磁盘监控"
description = "可视化展示服务器磁盘使用趋势"
version = "1.0.0"
entryPoint = "src/main.js"
icon = "assets/icon.svg"
targetVersions = @("2.0", "2.1", "2.2")
} | ConvertTo-Json -Depth 3

$manifest | Set-Content -Path "$extensionDir\manifest\manifest.json" -Encoding UTF8
Write-Output "清单文件已生成"

# 第二步:封装 WAC REST API 调用函数
function Invoke-WacDiskQuery {
param(
[Parameter(Mandatory)]
[string]$GatewayEndpoint,

[Parameter(Mandatory)]
[string]$ServerName,

[int]$WarningThreshold = 80
)

$queryScript = @(
"Get-CimInstance -ClassName Win32_LogicalDisk |"
" Where-Object { `$_.DriveType -eq 3 } |"
" ForEach-Object {"
" $pct = [math]::Round(($_.FreeSpace / $_.Size) * 100, 1)"
" $used = [math]::Round(($_.Size - $_.FreeSpace) / 1GB, 1)"
" $total = [math]::Round($_.Size / 1GB, 1)"
" [PSCustomObject]@{"
" Drive = $_.DeviceID"
" UsedGB = $used"
" TotalGB = $total"
" FreePct = $pct"
" Status = if ((100 - $pct) -gt $WarningThreshold)"
" { 'Warning' } else { 'OK' }"
" }"
" }"
) -join "`n"

$body = @{ command = $queryScript } | ConvertTo-Json

$uri = "$GatewayEndpoint/api/connections/$ServerName/powershell"

try {
$response = Invoke-RestMethod -Uri $uri -Method Post `
-Body $body -ContentType "application/json" `
-UseDefaultCredentials -SkipCertificateCheck

return $response.value
} catch {
Write-Error "查询 $ServerName 磁盘信息失败:$($_.Exception.Message)"
return $null
}
}

# 第三步:批量查询并生成 JSON 数据供扩展使用
$servers = @("SRV-FILE01", "SRV-WEB01", "SRV-DB01")
$diskData = @()

foreach ($server in $servers) {
$disks = Invoke-WacDiskQuery -GatewayEndpoint $gateway `
-ServerName $server -WarningThreshold 80

if ($null -ne $disks) {
foreach ($disk in $disks) {
$diskData += [PSCustomObject]@{
Server = $server
Drive = $disk.Drive
UsedGB = $disk.UsedGB
TotalGB = $disk.TotalGB
FreePct = $disk.FreePct
Status = $disk.Status
}
}
}
}

# 输出查询结果
$diskData | Format-Table -AutoSize

# 将数据序列化为 JSON 供前端扩展消费
$dataPath = "$extensionDir\src\assets\disk-data.json"
$diskData | ConvertTo-Json -Depth 3 |
Set-Content -Path $dataPath -Encoding UTF8

Write-Output "磁盘数据已导出至:$dataPath"

# 将扩展注册到 WAC 网关
$registerBody = @{
name = $extensionName
path = $extensionDir
enabled = $true
} | ConvertTo-Json

$null = Invoke-RestMethod -Uri "$gateway/api/extensions" `
-Method Post -Body $registerBody `
-ContentType "application/json" `
-UseDefaultCredentials -SkipCertificateCheck

Write-Output "扩展已注册到 WAC 网关"

执行结果示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
扩展项目目录已创建:C:\WACExtensions\custom-disk-monitor
清单文件已生成

Server Drive UsedGB TotalGB FreePct Status
------ ----- ------ ------- ------- ------
SRV-FILE01 C: 85.3 100.0 14.7 Warning
SRV-FILE01 D: 450.2 500.0 10.0 Warning
SRV-WEB01 C: 62.1 100.0 37.9 OK
SRV-WEB01 E: 120.5 200.0 39.8 OK
SRV-DB01 C: 45.8 100.0 54.2 OK
SRV-DB01 F: 780.3 1000.0 22.0 OK
SRV-DB01 G: 920.1 1000.0 8.0 Warning

磁盘数据已导出至:C:\WACExtensions\custom-disk-monitor\src\assets\disk-data.json
扩展已注册到 WAC 网关

这段脚本展示了 WAC 扩展开发的辅助流程。首先创建扩展的项目结构和清单文件,然后封装了一个可复用的 Invoke-WacDiskQuery 函数,通过 WAC REST API 远程执行磁盘查询。查询结果以 JSON 格式输出,供前端 Angular 组件直接消费。通过这种方式,团队可以将自定义的监控面板、运维工具或审批流程以扩展的形式嵌入到 WAC 界面中,形成统一的管理入口。

注意事项

  1. 安装前置条件:WAC 网关要求运行在 Windows Server 2016 及以上版本,且需要安装 .NET Framework 4.6 或更高版本。部署前应通过 Get-WindowsFeature 确认必要组件已启用,避免安装过程中因缺少依赖而失败。

  2. 证书管理策略:WAC 强制要求 HTTPS,生产环境中应使用企业 CA 或公共 CA 签发的证书,并在证书即将过期前通过自动化脚本完成续签和绑定。脚本中使用的证书指纹必须在本地计算机证书存储中存在。

  3. 连接批量导入的幂等性:重复执行导入脚本时,应先检查连接是否已存在再决定是否添加。忽略幂等性检查会导致 WAC 数据库中出现重复条目,影响管理界面的展示效果。

  4. 扩展开发的技术栈要求:WAC 扩展基于 Angular 框架,前端代码需要使用 TypeScript 编写。PowerShell 主要用于后端数据准备和 API 调用封装,实际的 UI 交互逻辑仍需前端开发工具链支持。

  5. API 调用的身份传递:WAC REST API 支持 Windows 集成认证(Kerberos/NTLM)。在跨域场景中,需要配置 CredSSP 或 Kerberos 约束委派,确保用户凭据能从 WAC 网关正确传递到目标服务器。

  6. 扩展版本兼容性:WAC 每次大版本升级可能导致扩展 API 变更。在清单文件的 targetVersions 字段中明确声明支持的 WAC 版本范围,并在升级前在测试环境验证扩展的兼容性,避免升级后扩展功能异常。

PowerShell 技能连载 - 剪贴板与 GUI 互操作

适用于 PowerShell 5.1 及以上版本(Windows),剪贴板功能需要 Windows 环境

PowerShell 不仅仅是命令行工具——它可以与 Windows 图形界面深度交互。从读写剪贴板、弹出消息框、打开文件对话框,到操控 GUI 窗口和发送按键,PowerShell 可以成为连接命令行和桌面操作的桥梁。在日常工作中,这些功能可以大幅简化重复性的 GUI 操作。

本文将讲解剪贴板操作、消息框、文件对话框,以及窗口自动化的技巧。

剪贴板操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# 设置剪贴板内容(文本)
Set-Clipboard -Value "Hello from PowerShell!"
Write-Host "已复制到剪贴板" -ForegroundColor Green

# 获取剪贴板内容
$clipContent = Get-Clipboard
Write-Host "剪贴板内容:$clipContent"

# 复制命令输出到剪贴板
Get-Process | Select-Object Name, Id,
@{N='内存MB'; E={[math]::Round($_.WorkingSet64/1MB, 1)}} |
Sort-Object 内存MB -Descending |
Select-Object -First 10 |
Format-Table -AutoSize |
Out-String | Set-Clipboard
Write-Host "进程列表已复制到剪贴板" -ForegroundColor Green

# 复制文件路径到剪贴板
Get-ChildItem "C:\Projects" -Filter *.ps1 -Recurse |
Select-Object -ExpandProperty FullName |
Set-Clipboard
Write-Host "已复制所有 .ps1 文件路径" -ForegroundColor Green

# 从剪贴板读取并处理
$clipboardText = Get-Clipboard
if ($clipboardText -match '^\d{1,3}(\.\d{1,3}){3}$') {
Write-Host "检测到 IP 地址:$clipboardText" -ForegroundColor Cyan
Test-NetConnection -ComputerName $clipboardText -Port 443 |
Select-Object ComputerName, TcpTestSucceeded
}

执行结果示例:

1
2
3
已复制到剪贴板
剪贴板内容:Hello from PowerShell!
进程列表已复制到剪贴板

消息框与交互

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# 简单消息框
Add-Type -AssemblyName PresentationFramework

[System.Windows.MessageBox]::Show(
"部署已完成",
"提示",
[System.Windows.MessageBoxButton]::OK,
[System.Windows.MessageBoxImage]::Information
)

# 确认对话框
$result = [System.Windows.MessageBox]::Show(
"确定要重启服务 MyApp 吗?",
"确认操作",
[System.Windows.MessageBoxButton]::YesNo,
[System.Windows.MessageBoxImage]::Warning
)

if ($result -eq 'Yes') {
Restart-Service "MyApp"
Write-Host "服务已重启" -ForegroundColor Green
} else {
Write-Host "操作已取消" -ForegroundColor Yellow
}

# 带超时的通知(使用 Balloon Tip)
function Show-BalloonTip {
param(
[string]$Title = "PowerShell",
[string]$Message,
[int]$DurationMs = 5000
)

Add-Type -AssemblyName System.Windows.Forms

$notify = New-Object System.Windows.Forms.NotifyIcon
$notify.Icon = [System.Drawing.SystemIcons]::Information
$notify.BalloonTipTitle = $Title
$notify.BalloonTipText = $Message
$notify.Visible = $true
$notify.ShowBalloonTip($DurationMs)

Start-Sleep -Milliseconds ($DurationMs + 500)
$notify.Dispose()
}

Show-BalloonTip -Title "部署完成" -Message "MyApp v2.5.0 已成功部署到生产环境"

执行结果示例:

1
2
# 弹出 Windows 消息框
# 系统托盘弹出通知气泡

文件和文件夹对话框

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 打开文件选择对话框
Add-Type -AssemblyName System.Windows.Forms

$openFileDialog = New-Object System.Windows.Forms.OpenFileDialog
$openFileDialog.Title = "选择 CSV 文件"
$openFileDialog.Filter = "CSV 文件 (*.csv)|*.csv|所有文件 (*.*)|*.*"
$openFileDialog.Multiselect = $true

if ($openFileDialog.ShowDialog() -eq 'OK') {
foreach ($file in $openFileDialog.FileNames) {
Write-Host "已选择:$file" -ForegroundColor Green
Import-Csv $file | Select-Object -First 5
}
}

# 保存文件对话框
$saveDialog = New-Object System.Windows.Forms.SaveFileDialog
$saveDialog.Title = "保存报告"
$saveDialog.Filter = "HTML 报告 (*.html)|*.html|CSV 文件 (*.csv)|*.csv"
$saveDialog.FileName = "report-$(Get-Date -Format 'yyyyMMdd').html"

if ($saveDialog.ShowDialog() -eq 'OK') {
Write-Host "保存到:$($saveDialog.FileName)" -ForegroundColor Green
# 生成报告...
}

# 文件夹浏览对话框
$folderDialog = New-Object System.Windows.Forms.FolderBrowserDialog
$folderDialog.Description = "选择项目目录"
$folderDialog.ShowNewFolderButton = $true

if ($folderDialog.ShowDialog() -eq 'OK') {
$selectedPath = $folderDialog.SelectedPath
Write-Host "已选择目录:$selectedPath" -ForegroundColor Green

$files = Get-ChildItem $selectedPath -Recurse -File
Write-Host "目录中有 $($files.Count) 个文件"
}

执行结果示例:

1
2
3
4
5
# 弹出标准的 Windows 文件选择对话框
已选择:C:\Data\customers.csv
保存到:C:\Reports\report-20250625.html
已选择目录:C:\Projects\MyApp
目录中有 245 个文件

窗口自动化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 使用 SendKeys 自动化 GUI 操作
Add-Type -AssemblyName System.Windows.Forms

# 模拟键盘快捷键
function Send-Keys {
param([string]$Keys, [int]$DelayMs = 500)

Start-Sleep -Milliseconds $DelayMs
[System.Windows.Forms.SendKeys]::SendWait($Keys)
}

# Ctrl+C 复制
Send-Keys "^c"

# Alt+Tab 切换窗口
Send-Keys "%{TAB}"

# 打开运行对话框 (Win+R)
Send-Keys "^{ESC}r"

# 输入文本
Start-Sleep -Seconds 2
Send-Keys "notepad.exe{ENTER}"

# 自动化记事本操作示例
Start-Sleep -Seconds 2
Send-Keys "这段文字由 PowerShell 自动输入"

# 保存 (Ctrl+S)
Start-Sleep -Milliseconds 500
Send-Keys "^s"

# 输入文件名
Start-Sleep -Seconds 1
Send-Keys "auto-generated.txt{ENTER}"

执行结果示例:

1
# 自动化操作 GUI 窗口

实用工具函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 快速复制 IP 配置
function Copy-IPConfig {
$ipConfig = Get-NetIPAddress -AddressFamily IPv4 |
Where-Object { $_.InterfaceAlias -notmatch 'Loopback' } |
Select-Object InterfaceAlias, IPAddress, PrefixLength |
Format-Table -AutoSize |
Out-String

Set-Clipboard -Value $ipConfig
Write-Host "IP 配置已复制到剪贴板" -ForegroundColor Green
}

# 快速复制文件内容
function Copy-FileContent {
param([Parameter(Mandatory)][string]$Path)
Get-Content $Path -Raw | Set-Clipboard
Write-Host "文件内容已复制:$Path ($((Get-Item $Path).Length) bytes)" -ForegroundColor Green
}

# 快速打开选中文件所在目录
function Open-FileLocation {
param([Parameter(Mandatory)][string]$Path)
$dir = Split-Path $Path -Parent
Start-Process explorer.exe $dir
}

Copy-IPConfig
Copy-FileContent -Path "C:\Config\appsettings.json"

执行结果示例:

1
2
IP 配置已复制到剪贴板
文件内容已复制:C:\Config\appsettings.json (2048 bytes)

注意事项

  1. 剪贴板安全:剪贴板内容可能包含敏感信息(密码、Token),操作完应清空剪贴板
  2. GUI 依赖:剪贴板和 GUI 操作需要交互式桌面会话,在无头环境(Server Core、SSH 远程)中不可用
  3. SendKeys 时序:窗口自动化依赖时序,网络延迟或系统负载可能导致失败。添加合理的 Start-Sleep
  4. STA 模式:某些 GUI 操作需要单线程单元(STA)模式,PowerShell 5.1 默认为 STA,PowerShell 7 默认为 MTA
  5. 管理员权限:某些 GUI 操作(如操控其他用户的窗口)需要管理员权限
  6. 用户体验:自动化 GUI 操作时应通知用户,避免在用户不知情时操控窗口