将Keith Hill的PowerShell Get-Clipboard和Set-Clipboard转换为PSM1脚本

Eri*_*ver 11 c# powershell multithreading sta

我想将Keith Hill的Get-Clipboard和Set-Clipboard的C#实现转换为纯PowerShell作为.PSM1文件.

有没有办法在PowerShell中启动STA线程,就像他在使用剪贴板时在Cmdlet中那样?

博客发布
代码

小智 15

TextBox不需要-STA开关.

function Get-ClipBoard {
    Add-Type -AssemblyName System.Windows.Forms
    $tb = New-Object System.Windows.Forms.TextBox
    $tb.Multiline = $true
    $tb.Paste()
    $tb.Text
}


function Set-ClipBoard() {
    Param(
      [Parameter(ValueFromPipeline=$true)]
      [string] $text
    )
    Add-Type -AssemblyName System.Windows.Forms
    $tb = New-Object System.Windows.Forms.TextBox
    $tb.Multiline = $true
    $tb.Text = $text
    $tb.SelectAll()
    $tb.Copy()
}
Run Code Online (Sandbox Code Playgroud)


mkl*_*nt0 8

请参阅底部部分,了解跨版本,跨平台模块,该模块在PowerShell Core和Windows PowerShell v2-v4 中提供剪贴板文本支持.

试图总结事务和选项的状态的Windows PowerShell的V5.1/PowerShell的核心 V6.1.0:

  • Windows PowerShell v5.0 +:使用内置 Get-ClipboardSet-Clipboard cmdlet.

  • Windows PowerShell v4.0-(v1 - v4.0):没有用于与剪贴板交互的内置cmdlet,但有一些解决方法:

    • 使用PowerShell社区扩展(PSCX; http://pscx.codeplex.com/),它附带了几个与剪贴板相关的cmdlet,它们不仅仅处理文本.
    • 管道到标准命令行实用程序clip.exe(W2K3 +服务器端,Vista +客户端)[1]:

      • 注意:除了下面讨论的编码问题之外,... | clip.exe总是在输入中附加一个尾随换行符 ; 避免这种情况的唯一方法是使用临时文件,其内容通过cmd<输入重定向提供 - 请参阅Set-ClipboardText下面的函数.

      • 如果仅需要ASCII字符(7位)支持:默认情况下有效.

      • 如果仅需要OEM编码(8位)支持(例如,美国的IBM437),请首先运行以下命令:

        • $OutputEncoding = [System.Text.Encoding]::GetEncoding([System.Globalization.CultureInfo]::CurrentCulture.TextInfo.OEMCodePage)
      • 如果需要完整的Unicode支持,则必须使用不带BOMUTF-16 LE编码 ; 先运行以下命令:

        • $OutputEncoding = New-Object System.Text.UnicodeEncoding $false, $false # UTF-16 encoding *without BOM*
        • 用于测试的示例(PS控制台将亚洲字符显示为"??",但仍然正确处理它们 - 例如,在记事本中验证剪贴板内容):

          • "I enjoyed Thomas Hübl's talk about ??" | clip # should appear as is on the clipboard
      • 注意:$OutputEncoding如上所述分配在全局范围内工作正常,但在其他方面(例如在函数中)由于Windows PowerShell v5.1/PowerShell Core v6.0.0-rc.2中的错误而无法正常工作 - 请参阅https:// github.com/PowerShell/PowerShell/issues/5763

        • 在非全局环境中,用于(New-Object ...).psobject.BaseObject解决错误,或者 - 在PSv5 +中 - 使用[...]:new().
      • 注意:clip.exe显然理解2种格式:

        • 系统的当前OEM代码页(例如,IBM 437)
        • UTF-16 LE("Unicode")
        • 遗憾的是,clip.exe始终把一个BOM的数据,因此需要使用BOM- 编码.
        • 注意,上述编码仅与正确检测输入有关 ; 一旦在剪贴板上,输入字符串可用于以下所有编码:UTF-16 LE,"ANSI"和OEM.
    • 使用基于PowerShell的解决方案直接使用.NET类:

      • 请注意,剪贴板访问只能从STA(单线程单元)模式中的线程发生 - 而不是MTA(多线程单元):

        • v3:STA是默认值(可以通过powershell.exe使用-mta开关调用来输入MTA模式).
        • v2和v1:MTA是默认值 ; 可以通过powershell.exe使用-sta开关调用来输入STA模式.
        • Ergo:强大的功能应该能够在任一模式下从会话访问剪贴板.
  • PowerShell Core(多平台),从v6.1.0开始,没有用于与剪贴板交互的内置cmdlet,即使在Windows上运行也没有.

    • 解决方法是使用特定于平台的实用程序或API - 请参阅下文.

我的ClipboardText模块提供 "polyfill"功能Get-ClipboardText以及从剪贴板Set-ClipboardText获取和设置文本 ; 它们适用于Windows PowerShell v2 +以及PowerShell Core(有限制,请参见下文).

在最简单的情况下(安装了包管理模块的PSv5 +或v3/v4),您可以从提升/ 会话中的PowerShell库安装它,如下所示sudo:

Install-Module ClipboardText
Run Code Online (Sandbox Code Playgroud)

有关更多信息,包括先决条件和手动安装说明,请参阅存储.

  • 注意:严格来说,这些函数不是polyfill,因为它们的名称与内置cmdlet不同.但是,选择了名称后缀Text,以便明确表示这些函数仅处理文本.

  • 代码非常感谢来自不同网站的信息,特别是@ hoge的回答(/sf/answers/110130681/)和http://techibee.com/powershell/powershell-script-to-copy-powershell-指令输出到剪贴板/ 1316

  • 在STA模式下Windows PowerShell v5 +上运行:

    • 内置cmdlet(Get-Clipboard/ Set-Clipboard)在后台调用.
      请注意,STA模式(COM线程模型)是自v3以来的默认模式,但您可以使用命令行选项选择进入MTA(多线程模式)-MTA.
  • 在所有其他情况下(Windows PowerShell v4-和/或MTA模式,所有支持的平台上的PowerShell Core):

    • 视窗:
      • 通过使用编译的ad-hoc C#代码,使用基于AP/Invoke的调用Windows API的解决方案Add-Type.
    • 类Unix的平台:在幕后调用本机实用程序:
      • macOS:pbcopypbpaste
      • Linux : xclip, 如果可用并已安装 ;
        例如,在Ubuntu上,用于sudo apt-get xclip安装.
  • Set-ClipboardText可以接受任何类型的对象作为输入(然后直接或从管道接收转换为文本的方式与它们在控制台中呈现的方式相同).

  • 调用-Verbose以查看幕后使用的技术来访问剪贴板.


[1]这个答案的早期版本错误地声称clip.exe:
- 在复制到剪贴板时总是附加换行符(它没有)
- 正确处理重定向到stdin的文件中的 UTF-16 LE BOM,<当输入通过管道传输时|(clip.exe 始终将BOM复制到剪贴板).