使用 PowerShell 脚本对剪切板进行监控

这个脚本能做什么

有时剪贴板会出现一些莫名奇妙的问题,使用这个脚本来对剪贴板进行监控,有助于发现问题。

其功能和 Win11 的「剪贴板历史记录」功能类似,支持对文本、文件、图像的复制动作进行监控。

下面是脚本内容:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

function Get-ImageHash {
    param([System.Drawing.Image]$image)
    
    # 将图片转换为字节数组
    $ms = New-Object System.IO.MemoryStream
    $image.Save($ms, [System.Drawing.Imaging.ImageFormat]::Png)
    $bytes = $ms.ToArray()
    $ms.Dispose()
    
    # 计算MD5哈希
    $md5 = [System.Security.Cryptography.MD5]::Create()
    $hash = [System.BitConverter]::ToString($md5.ComputeHash($bytes))
    $md5.Dispose()
    
    return $hash
}

function Get-ClipboardContent {
    $content = @{
        Type = "None"
        Data = $null
        Hash = $null  # 添加哈希属性
    }
    
    # 检查是否包含文件路径
    if ([Windows.Forms.Clipboard]::ContainsFileDropList()) {
        $content.Type = "Files"
        $content.Data = @([Windows.Forms.Clipboard]::GetFileDropList())
        $content.Hash = [string]::Join("|", $content.Data)
    }
    # 检查是否包含图片
    elseif ([Windows.Forms.Clipboard]::ContainsImage()) {
        $content.Type = "Image"
        $content.Data = [Windows.Forms.Clipboard]::GetImage()
        $content.Hash = Get-ImageHash $content.Data
    }
    # 检查是否包含文本
    elseif ([Windows.Forms.Clipboard]::ContainsText()) {
        $content.Type = "Text"
        $content.Data = [Windows.Forms.Clipboard]::GetText()
        $content.Hash = $content.Data
    }
    
    return $content
}

# 创建临时目录用于存储图片
$tempPath = Join-Path $env:TEMP "ClipboardMonitor"
if (-not (Test-Path $tempPath)) {
    New-Item -ItemType Directory -Path $tempPath | Out-Null
}

# 初始化上一次的剪贴板内容
$previousContent = Get-ClipboardContent

Write-Host "开始监控剪贴板变化..." -ForegroundColor Green
Write-Host "临时文件保存位置: $tempPath" -ForegroundColor Gray
Write-Host "按 Ctrl+C 停止监控`n" -ForegroundColor Yellow

try {
    while ($true) {
        # 获取当前剪贴板内容
        $currentContent = Get-ClipboardContent
        
        # 比较内容是否发生变化(使用哈希值比较)
        if ($currentContent.Hash -ne $previousContent.Hash) {
            $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
            $timestampFile = Get-Date -Format "yyyyMMdd_HHmmss"
            Write-Host "`n[$timestamp] 检测到剪贴板内容变化!" -ForegroundColor Cyan
            
            switch ($currentContent.Type) {
                "Files" {
                    Write-Host "复制的文件路径:" -ForegroundColor Green
                    $currentContent.Data | ForEach-Object {
                        Write-Host $_ -ForegroundColor White
                    }
                }
                "Image" {
                    $imagePath = Join-Path $tempPath "clipboard_${timestampFile}.png"
                    $currentContent.Data.Save($imagePath, [System.Drawing.Imaging.ImageFormat]::Png)
                    Write-Host "图片已保存到:" -ForegroundColor Green
                    Write-Host $imagePath -ForegroundColor White
                }
                "Text" {
                    Write-Host "文本内容:" -ForegroundColor Green
                    Write-Host $currentContent.Data -ForegroundColor White
                }
                "None" {
                    Write-Host "剪贴板已清空" -ForegroundColor Red
                }
            }
            
            # 更新上一次的内容
            $previousContent = $currentContent
        }
        
        # 暂停一段时间再检查
        Start-Sleep -Milliseconds 500
    }
} finally {
    Write-Host "`n停止监控剪贴板" -ForegroundColor Yellow
}

直接粘贴到 ISE 中运行,或者保存到本地并命名为 .ps1 文件后运行:

# 直接运行
powershell -File "PATH_TO_.PS1_FILE"
# 或者
powershell -ExecutionPolicy Bypass -File "PATH_TO_.PS1_FILE"

补充一点

我工作用的笔记本动不动就剪贴板出故障,Ctrl-C 要么没反应,要么复制出来的中文文本变成一堆问号,很讨厌。但我发现把剪贴板清空一下就能解决:

Set-Clipboard $null

评论