使用PowerShell将System.Windows.Interop.InteropBitmap保存到磁盘
概要
需要通过PowerShell读取Windows剪贴板中存储的图像(例如从浏览器复制的System.Windows.Interop.InteropBitmap类型对象),并将图像保存为本地磁盘文件。
问题
如何实现上述剪贴板图像读取、本地保存的需求?
初始测试代码如下:
Add-Type -AssemblyName PresentationCore $DataObject = [System.Windows.Clipboard]::GetDataObject() $DataObject | Get-Member
实现方案
不需要手动解析InteropBitmap对象的底层数据,直接调用WPF内置的剪贴板接口和位图编码器即可完成需求,步骤如下:
- 加载操作剪贴板、处理位图所需的系统程序集
- 校验剪贴板是否存在图像数据,避免空引用报错
- 从剪贴板直接提取位图源对象,自动兼容InteropBitmap等不同的位图实现类型
- 实例化对应格式的位图编码器,将位图源封装为帧加入编码器
- 创建本地文件流,通过编码器将图像数据写入流完成保存
基础可用代码
默认保存为PNG格式,路径为当前用户图片目录下的clipboard_image.png:
# 加载依赖程序集 Add-Type -AssemblyName PresentationCore # 校验剪贴板图像存在性 if ([System.Windows.Clipboard]::ContainsImage()) { # 提取剪贴板位图对象 $clipboardBitmap = [System.Windows.Clipboard]::GetImage() # 初始化PNG编码器,如需存JPG可替换为JpegBitmapEncoder $encoder = New-Object System.Windows.Media.Imaging.PngBitmapEncoder $encoder.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($clipboardBitmap)) # 定义保存路径,可按需修改 $outputPath = Join-Path $env:USERPROFILE "Pictures\clipboard_image.png" # 写入文件 $writeStream = [System.IO.File]::Create($outputPath) $encoder.Save($writeStream) # 释放流资源 $writeStream.Close() $writeStream.Dispose() Write-Host "剪贴板图像已保存至:$outputPath" } else { Write-Error "当前剪贴板未检测到有效图像数据" }
格式调整说明
- 如需保存为JPG格式,将编码器替换为
[System.Windows.Media.Imaging.JpegBitmapEncoder],可通过$encoder.QualityLevel = 90设置画质,取值范围1~100,数值越高画质越好 - 如需保存为BMP、GIF等格式,替换为对应格式的BitmapEncoder即可,类名规则为
格式名+BitmapEncoder
线程兼容处理
部分PowerShell环境默认运行在MTA线程模式,调用WPF剪贴板接口可能触发报错,可通过STA独立运行空间执行代码解决兼容问题:
$outputPath = Join-Path $env:USERPROFILE "Pictures\clipboard_image.png" # 创建STA线程运行空间 $staRunspace = [RunspaceFactory]::CreateRunspace() $staRunspace.ApartmentState = "STA" $staRunspace.ThreadOptions = "ReuseThread" $staRunspace.Open() $staRunspace.SessionStateProxy.SetVariable("outputPath", $outputPath) # 执行图像保存逻辑 $pipeline = $staRunspace.CreatePipeline({ Add-Type -AssemblyName PresentationCore if ([System.Windows.Clipboard]::ContainsImage()) { $clipboardBitmap = [System.Windows.Clipboard]::GetImage() $encoder = New-Object System.Windows.Media.Imaging.PngBitmapEncoder $encoder.Frames.Add([System.Windows.Media.Imaging.BitmapFrame]::Create($clipboardBitmap)) $writeStream = [System.IO.File]::Create($outputPath) $encoder.Save($writeStream) $writeStream.Close() $writeStream.Dispose() } }) $pipeline.Invoke() $staRunspace.Close()
内容的提问来源于stack exchange,提问作者Trevor Sullivan
相关产品推荐
相关产品推荐

